static weaving eclipselink jpa with spring and tom

2019-09-10 07:34发布

问题:

I am trying to achieve static weaving with Eclipselink+Spring+JPA using maven. I have configured my spring project with Java Configuration, no context.xml. I tried following things:

  1. In persistence.xml:

Added following weaving specification.

<property name="eclipselink.weaving" value="static" />
  1. In DBConfig.java, I have configured beans

as follow :

 @Bean()
    public DataSource getDataSource() {
        BoneCPDataSource ds = new BoneCPDataSource();
        log.debug("Driver Name : " + driverClassName);
        try {
            Class.forName(driverClassName);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        log.debug("DB Url : " + url);
        ds.setDriverClass(driverClassName);
        ds.setJdbcUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        ds.setMaxConnectionsPerPartition(5);
        ds.setMinConnectionsPerPartition(2);
        ds.setAcquireIncrement(2);
        ds.setDefaultAutoCommit(false);     
        Properties props = new Properties();
        props.put("eclipselink.weaving", "static");
        try {
            ds.setProperties(props);
        } catch (Exception e) {         
            e.printStackTrace();
        }
        return ds;
    }

    @Bean(name = "em")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(getDataSource());      
        em.setJpaDialect(jpaDialect());
        em.setPackagesToScan("com.cdl.hp50.model", "com.cdl.hp50.model.person");
        em.setPersistenceUnitName(persistenceUnitName);
        DatabasePlatform dp = new MySQLPlatform();
        em.setJpaVendorAdapter(getEclipseLinkJpaVendorAdapter());       
        return em;
    }
  1. In pom.xml, I have added following plugin as per stated on eclipselink documentation:

As follow:

              <plugin>
                    <groupId>de.empulse.eclipselink</groupId>
                    <artifactId>staticweave-maven-plugin</artifactId>
                    <version>1.0.0</version>
                    <executions>
                        <execution>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>weave</goal>
                            </goals>
                            <configuration>
                                <persistenceXMLLocation>META-INF/persistence.xml</persistenceXMLLocation>
                                <logLevel>FINE</logLevel>
                            </configuration>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>org.eclipse.persistence</groupId>
                            <artifactId>org.eclipse.persistence.jpa</artifactId>
                            <version>${eclipselink.version}</version>
                        </dependency>
                    </dependencies>
                </plugin>

I have specified clearly to use static (build time) weaving. And while I create war using maven install, entities listed in persistence.xml are weaved successfully. But when I deploy war into the tomcat, it gives following exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'em' defined in class com.cdl.hp50.config.DBConfig: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Cannot apply class transformer without LoadTimeWeaver specified
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1568)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:540)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:956)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:747)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4992)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5492)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:649)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1245)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1895)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Cannot apply class transformer without LoadTimeWeaver specified
    at org.springframework.orm.jpa.persistenceunit.SpringPersistenceUnitInfo.addTransformer(SpringPersistenceUnitInfo.java:80)
    at org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntityManagerFactory(PersistenceProvider.java:348)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:341)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1627)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1564)
    ... 25 more

I have event tried setting eclipselink.weaving as false. But still it gives same error. I don't know why it is looking for LoadTimeWeaver. Please suggest me what I am missing over here.

Update:

I have uploaded starter project that includes eclipselink, spring mvc, spring data jpa, sitemesh on github

回答1:

Edit: I think i found your problem

   props.put("eclipselink.weaving", "static");
    try {
        ds.setProperties(props);

Are you trying to apply eclipselink properties to your datasource? If you check my example context.xml (form the app below), the jpaPropertyMap needs to be applied to the LocalContainerEntityManagerFactoryBean.

So, you should change your code to

 em.setjpaPropertyMap(props)

Old answer:

First of all, for such questions, an example project would be really good. Well, i did it for you, it can be found at: https://github.com/baumgartner/eclipselink-static-weaving

And the bad news: I can't reproduce your problem, my Application works fine on tomcat 7.

Did you check your .class files if they got extended by the static-weaving-plugin? Are the weaved files in your tomcat folder? Are the correct files in tomcat wtpwebapps-folder? (Sometimes synchronisation just fails) Did you use JAD (java decompiler) to decompile your classes and check if they got enhanced? An enhanced entity would look like this:

public class asdf.User implements java.lang.Cloneable, org.eclipse.persistence.internal.weaving.PersistenceWeaved, org.eclipse.persistence.internal.descriptors.PersistenceEntity, org.eclipse.persistence.internal.descriptors.PersistenceObject, org.eclipse.persistence.queries.FetchGroupTracker, org.eclipse.persistence.internal.weaving.PersistenceWeavedFetchGroups, org.eclipse.persistence.descriptors.changetracking.ChangeTracker, org.eclipse.persistence.internal.weaving.PersistenceWeavedChangeTracking, org.eclipse.persistence.internal.weaving.PersistenceWeavedRest {

Does your app work if you deploy the war? Does it work if you run your app from the IDE?



回答2:

I was trying to achieve static weaving with Eclipselink+Spring+JPA using maven too. Everything was working great except that the fetch type was never working Lazy. Finally I found this article with a solution that worked perfect for me.
The solution was to add a plugin to my maven pom.xml.

<plugin>
    <artifactId>eclipselink-staticweave-maven-plugin</artifactId>
    <groupId>au.com.alderaan</groupId>
    <version>1.0.4</version>
    <executions>
        <execution>
            <goals>
                <goal>weave</goal>
            </goals>
            <phase>process-classes</phase>
            <configuration>
                <logLevel>ALL</logLevel>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>${eclipselink.version}</version>
        </dependency>
    </dependencies>
</plugin>  

Suggested by EclipseLink also.
The only problem I have with the static weaving is that you cannot fetch eager, even if you wish to. Thus, I am not using weaving but batch or join fetch