1

我正在尝试将存储库支持添加到 Eclipselink JPA Spring 项目。Eclipselink 需要 LoadTimeWeaving——尽管这不是绝对正确的,但我稍后希望 Aspects 也能正常工作。

生产应用程序在 Tomcat 下运行,如果我继续进行而不尝试创建 JUnit,我现在可能已经完成了。我有一种感觉,也许我真正拥有的是 Eciplse (STS 3.4) 问题,因为它似乎忽略了我的备用类加载器。但这似乎很基本,必须起作用,而且我做错了什么。

我只使用注释和 Java 配置。相关代码如下。

配置

@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;
}
}

死的简单实体(删除了一些真正无聊的列):

@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;
}
....
}

当然是存储库:

@Repository
public interface PendingQueueRepository extends CrudRepository<PendingQueue, PendingQueueId> {
List<PendingQueue> findByIeUser(String ieUser);
}

最后是 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));


}
}

我正在尝试使用此 VM ARG 运行 JUnit:-javaagent:C:\Users\Terry\.m2\repository\org\springframework\spring-agent\2.5.6.SEC03\spring-agent-2.5.6.SEC03 。罐

我也尝试添加 AspectJ weaver,但没有帮助 -javaagent:C:\Users\Terry\.m2\repository\org\aspectj\aspectjweaver\1.8.0\aspectjweaver-1.8.0.jar

我没有尝试过 Spring Tomcat weaver,但这似乎不是正确的方向。我读过人们在 JUnit 查找类文件时遇到问题。

如果不粘贴相当大的堆栈跟踪,这一切都归结为:

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.

这当然是真的。该类加载器不支持编织。但是我已经非常非常努力地不使用该加载程序。任何帮助表示赞赏

4

4 回答 4

0

我有一个类似的设置,并为单元测试添加以下 VM 参数对我有用:

-javaagent:/path/to/spring-instrument-4.0.0.RELEASE.jar -javaagent:/path/to/aspectjweaver-1.8.0.jar
于 2014-05-01T16:30:17.977 回答
0

看来问题是在 @Configuration 类中我包含了 LoadTimeWeaver bean 的定义。我还在 EntityManagerFactory 构造函数中设置了该值。通过删除它,我不再在 spring 容器启动期间遇到运行时错误。

查看 Spring 控制台,它说我的实体 Bean 已被转换(编织),所以也许延迟加载仍然可以工作 - 我没有任何数据库关联可以在这个特定项目中尝试它。

另一个注意事项不仅是persistence.xml 不是必需的,而且是不允许的。Eclipselink 正在寻找另一个我不知道的persistence.xml 副本,这导致支持我的存储库的实体未被发现。

但是现在我相信我发布的示例(减去 loadTimeWeaving bean)显然是最好的,或者至少是最完整的示例之一 - 谁会预料到这一点!

于 2014-05-02T16:59:22.220 回答
0

我无法让上述工作。amazon aws 不允许我将检测 jar 放在 tomcat/lib 文件夹中,所以我不能使用 -javaagent 方法(相信我我试过了!)。我不得不切换到eclipselink静态编织

这并不难,需要一个 persistence.xml 文件,但如果您已经在使用带注释的配置,它可以短至:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="ADD_NAME_HERE">
        <!--this is necessary for the eclipselink static weaving maven plugin-->
        <!--this setting auto-detects entities in the project-->
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
    </persistence-unit>
</persistence>

但请注意,它必须在包含实体类的项目中。我犯了将 pom.xml 文件中的 persistence.xml 文件和 maven 插件放入我的网站项目而不是我的域项目的错误。

于 2016-11-04T15:54:26.017 回答
0

如果需要通过 maven 设置 -javaagent,可以这样做:

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.20</version>
                <configuration>
                    <argLine>
                        -javaagent:"${settings.localRepository}/org/springframework/spring-instrument/${org.springframework.version}/spring-instrument-${org.springframework.version}.jar"
                    </argLine>
                </configuration>
            </plugin>
        </plugins>

(只需为 ${org.springframework.version} 设置属性或替换相应版本)这样它就与您的项目相关联,而不是与您的 jvm 或网络服务器相关联

于 2017-08-28T09:01:27.150 回答