I am trying to add Repository support to an Eclipselink JPA Spring project. Eclipselink requires LoadTimeWeaving - even though that's not absolutely true I'd later like to get Aspects working as well.
The production application runs under Tomcat, and I might be done by now if I had gone along and not tried to create JUnits. I have a feeling that maybe what I really have is an Eciplse (STS 3.4) problem since it seems to be ignoring my alternate class loader. But it seems so basic that this must work, and that I'm doing something wrong.
I am using exclusively Annotations and Java configuration. The relevant code below.
Configuration
@Configuration
@Profile("data")
@EnableJpaRepositories(basePackages="com.xxx.ieexb.repository",transactionManagerRef="transactionManager",entityManagerFactoryRef="entityManagerFactory")
@ComponentScan(basePackages= {"com.xxx.ieexb.jpa"
,"com.xxx.ieexb.repository"})
@EnableTransactionManagement
@EnableLoadTimeWeaving
@ImportResource("classpath:/properties-config.xml")
public class IeexbDataContextConfig {
@Value("#{ieexbProperties['com.xxx.ieexb.dataSource.Url']}")
public String dataSourceUrl;
@Value("#{ieexbProperties['com.xxx.ieexb.dataSource.Username']}")
public String dataSourceUsername;
@Value("#{ieexbProperties['com.xxx.ieexb.dataSource.Password']}")
public String dataSourcePassword;
@Value("#{ieexbProperties['com.xxx.ieexb.persistenceUnitName']}")
public String persistenceUnitName;
@Autowired
EntityManagerFactory entityManagerFactory;
@Bean()
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.springframework.jdbc.datasource.DriverManagerDataSource");
dataSource.setUrl(dataSourceUrl);
dataSource.setUsername(dataSourceUsername);
dataSource.setPassword(dataSourcePassword);
return dataSource;
}
@Bean()
EclipseLinkJpaVendorAdapter eclipseLinkJpaVendorAdapter() {
EclipseLinkJpaVendorAdapter eclipseLinkJpaVendorAdapter = new EclipseLinkJpaVendorAdapter();
eclipseLinkJpaVendorAdapter.setShowSql(true);
eclipseLinkJpaVendorAdapter.setGenerateDdl(false);
eclipseLinkJpaVendorAdapter.setDatabasePlatform("org.eclipse.persistence.platform.database.OraclePlatform");
return eclipseLinkJpaVendorAdapter;
}
@Bean()
EclipseLinkJpaDialect jpaDialect() {
EclipseLinkJpaDialect jpaDialect = new EclipseLinkJpaDialect();
return jpaDialect;
}
@Bean()
public FactoryBean<EntityManagerFactory> entityManagerFactory() {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
//TODO Does this @Configuration do away with need for persistence.xml?
//emf.setPersistenceXmlLocation("classpath:persistence.xml");
emf.setPersistenceUnitName(persistenceUnitName);
emf.setDataSource(dataSource());
emf.setLoadTimeWeaver(loadTimeWeaver());
emf.setJpaDialect(new EclipseLinkJpaDialect());
emf.setJpaVendorAdapter(eclipseLinkJpaVendorAdapter());
//emf.setPersistenceProvider(persistenceProvider());
return emf;
}
@Bean()
public LoadTimeWeaver loadTimeWeaver() {
LoadTimeWeaver loadTimeWeaver = new ReflectiveLoadTimeWeaver();
return loadTimeWeaver;
}
}
The dead simple Entity (with some of the truly boring columns removed):
@Entity
@Cacheable(false)
@Table(name="PENDING_QUEUE"
, uniqueConstraints = @UniqueConstraint(columnNames="IEEXB_ID,QUEUE_TIMESTAMP")
)
public class PendingQueue implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
@AttributeOverrides( {
@AttributeOverride(name="ieexbId", column=@Column(name="IEEXB_ID", nullable=false) ),
@AttributeOverride(name="queueTimestamp", column=@Column(name="QUEUE_TIMESTAMP", nullable=false) ) } )
private PendingQueueId id;
@Column(name="IE_USER", nullable=false, length=21)
private String ieUser;
@Column(name="COMMAND_TYPE", nullable=false, length=3)
private String commandType;
public PendingQueue() {
;
}
public PendingQueue(PendingQueueId id, String ieUser, String commandType) {
super();
this.id = id;
this.ieUser = ieUser;
this.commandType = commandType;
}
public PendingQueueId getId() {
return id;
}
public void setId(PendingQueueId id) {
this.id = id;
}
public String getIeUser() {
return ieUser;
}
public void setIeUser(String ieUser) {
this.ieUser = ieUser;
}
public String getCommandType() {
return commandType;
}
public void setCommandType(String commandType) {
this.commandType = commandType;
}
....
}
The Repository of course:
@Repository
public interface PendingQueueRepository extends CrudRepository<PendingQueue, PendingQueueId> {
List<PendingQueue> findByIeUser(String ieUser);
}
And finally the JUnit:
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles(profiles = {"data"})
@ContextConfiguration(classes = IeexbDataContextConfig.class, loader = AnnotationConfigContextLoader.class)
public class TestPendingQueue {
@Autowired
PendingQueueRepository pendingQueueRepository;
@Test
public void testFindByIeUser() {
List<PendingQueue> results = pendingQueueRepository.findByIeUser("JPA.XXX.BOB1");
System.out.println("Found Items:" + results.size());
System.out.println("First item is:" + results.get(0));
}
}
I am trying to run the JUnit with this VM ARG: -javaagent:C:\Users\Terry\.m2\repository\org\springframework\spring-agent\2.5.6.SEC03\spring-agent-2.5.6.SEC03.jar
I also tried adding the AspectJ weaver, but it didn't help -javaagent:C:\Users\Terry\.m2\repository\org\aspectj\aspectjweaver\1.8.0\aspectjweaver-1.8.0.jar
I have not tried the Spring Tomcat weaver but that doesn't seem like the right direction. I've read people then had problems with JUnit finding class files.
Without pasting in the rather huge stack trace it all boils down to this:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.instrument.classloading.LoadTimeWeaver
com.xxx.ieexb.config.IeexbDataContextConfig.loadTimeWeaver()] threw exception; nested exception is java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method.
Which is of course true. That classloader doesn't support weaving. But I have tried very very hard to not use that loader. Any help appreciated