How do I configure dynamic weaving using EclipseLink & Spring?

21,601

Solution 1

For weaving with Spring I believe you need something like,

<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    <property name="defaultDataSource" ref="dataSource" />
    <property name="dataSources">
        <map>
            <entry>
                <key>
                    <value>jdbc/__default</value>
                </key>
                <ref bean="dataSource" />
            </entry>
            <entry>
                <key>
                    <value>jdbc/jta</value>
                </key>
                <ref bean="dataSource" />
            </entry>
        </map>
    </property>
    <property name="loadTimeWeaver">
        <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    </property>
</bean>

There is some information here,

http://wiki.eclipse.org/EclipseLink/Examples/JPA/JPASpring

Ensure you are not accessing your classes before accessing the Spring context.

Another solution is to use static weaving.

Solution 2

Now, I am also using EclipseLink 2.2 and Spring 3.1 as below. My configuration is a little different with yours. There is no loadTimeWeaver configuration in your eclipseLinkEntityManagerFactory. I think, it will be ok if you use as below.

Please, try as below with your Oracle DB information..

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:faces="http://www.springframework.org/schema/faces"
       xmlns:int-security="http://www.springframework.org/schema/integration/security"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:sec="http://www.springframework.org/schema/security"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/integration/security http://www.springframework.org/schema/integration/security/spring-integration-security-2.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/faces http://www.springframework.org/schema/faces/spring-faces-2.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <context:annotation-config/>    
    <context:component-scan base-package="your-package"/>
    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="your-driver"/>
        <property name="url" value="your-database-url"/>
        <property name="username" value="your-username"/>
        <property name="password" value="your-passowrd"/>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!--        <property name="dataSource" ref="dataSource"/>-->
        <property name="persistenceUnitName" value="your-persistence-unit-name"/>
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>
        </property>
        <property name="jpaPropertyMap">
            <props>
                <prop key="eclipselink.weaving">false</prop>
            </props>
        </property>

        <property name="loadTimeWeaver">
            <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver">
            </bean>
        </property>
    </bean>

    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
        <property name="databasePlatform" value="org.eclipse.persistence.platform.database.OraclePlatform" />
        <property name="generateDdl" value="false"/>
        <property name="showSql" value="true"/>
    </bean>
</beans>

Solution 3

copy org.springframework.instrument-3.1.0.M2.jar into tomcat/lib directory and try it again.

Solution 4

Considering the instrumentation for unit tests, one can add it as VM argument to the maven-surefire-plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>-javaagent:lib/test/spring-instrument-4.0.2.RELEASE.jar</argLine>
    </configuration>
</plugin>

assuming spring-instrument jar was placed at corresponding location.

(For that, the following dependency could be added temporarily to the project pom.xml

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-instrument</artifactId>
    <scope>test</scope>
</dependency>

and then after the build, the corresponding artifact copied from local .m2 directory to project's lib/test directory.)

Share:
21,601
Kaypro II
Author by

Kaypro II

Updated on July 26, 2020

Comments

  • Kaypro II
    Kaypro II almost 4 years

    How do I configure dynamic weaving using EclipseLink & Spring? Right now I'm trying to get this working with a Junit test, but I'll later have to have it work with Tomcat (my department has been standardized on it for something like 10 years).

    I'm running into two main problems:

    1. Spring wants a load time weaver:

    Exception:

    java.lang.IllegalStateException: Failed to load ApplicationContext
        at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:181)
        at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
    <snip>
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.context.weaving.AspectJWeavingEnabler#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
    <snip>
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
    <snip>
    Caused by: java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
        at org.springframework.context.weaving.DefaultContextLoadTimeWeaver.setBeanClassLoader(DefaultContextLoadTimeWeaver.java:91)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1437)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1408)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
        ... 44 more
    

    I can fix this by configuring the Spring Instrumentation:

    JVM parameter:
    -javaagent:/path/to/org.springframework.instrument-3.1.0.M2.jar
    

    2. Eclipselink is not satisfied with the Spring Instrumentation:

    Error:

    (similar error messages repeated many times)
    
    [EL Severe]: 2011-06-20 16:12:57.951--ServerSession(979781372)--Local Exception Stack: 
    Exception [EclipseLink-0] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.IntegrityException
    Descriptor Exceptions: 
    ---------------------------------------------------------
    
    Exception [EclipseLink-60] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DescriptorException
    Exception Description: The method [_persistence_set_shellType_vh] or [_persistence_get_shellType_vh] is not defined in the object [ps.entity.JudicialArtifactFamily].
    Internal Exception: java.lang.NoSuchMethodException: ps.entity.JudicialArtifactFamily._persistence_get_shellType_vh()
    Mapping: org.eclipse.persistence.mappings.ManyToOneMapping[shellType]
    Descriptor: RelationalDescriptor(ps.entity.JudicialArtifactFamily --> [DatabaseTable(JUDICIAL_ARTIFACT_FAMILY)])
    
    Exception [EclipseLink-218] (Eclipse Persistence Services - 2.2.0.v20110202-r8913): org.eclipse.persistence.exceptions.DescriptorException
    Exception Description: A NullPointerException would have occurred accessing a non-existent weaved _vh_ method [_persistence_get_shellType_vh].  The class was not weaved properly - for EE deployments, check the module order in the application.xml deployment descriptor and verify that the module containing the persistence unit is ahead of any other module that uses it.
    

    I tried to fix this by using the EclipseLink weaver:

    -javaagent:/dev/tools/javaagents/eclipselink.jar
    

    But then I get the same exception from problem #1.

    Library versions

    I am using:

    • Java 1.6.0_24
    • EclipseLink 2.2.0.v20110202-r8913
    • Spring 3.1.0 M2

    Configuration files

    Here is my persistence.xml:

    <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 version="2.0"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="eclipseLinkHashPU" transaction-type="RESOURCE_LOCAL">
            <class>ps.entity.Artifact</class>
            <class>ps.entity.JudicialArtifactFamily</class>
            <class>ps.entity.ShellType</class>
            <class>ps.entity.SourceArtifact</class>
            <class>ps.entity.Health</class>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
            <properties>    
                <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
                <property name="eclipselink.ddl-generation.output-mode" value="database"/>
            </properties>
        </persistence-unit>
    </persistence>
    

    Here is my application.xml:

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jaxrs="http://cxf.apache.org/schema/jaxrs" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
               http://www.springframework.org/schema/tx 
               http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-2.5.xsd
               http://cxf.apache.org/schema/jaxrs
               http://cxf.apache.org/schema/jaxrs.xsd
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd          
               http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
               http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">
    
        <context:component-scan base-package="ps">
        </context:component-scan>
    
        <context:load-time-weaver/>
    
        <alias alias="entityManagerFactory" name="eclipseLinkEntityManagerFactory"/>
    
        <bean id="eclipseLinkEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="persistenceXmlLocation" value="classpath:eclipselink-persistence.xml" />
            <property name="persistenceUnitName" value="eclipseLinkHashPU" />
            <property name="jpaPropertyMap">
                <map>
                    <entry key="eclipselink.logging.level" value="Severe"/>
                    <entry key="eclipselink.target-database" value="org.eclipse.persistence.platform.database.oracle.OraclePlatform"/>
                    <entry key="javax.persistence.nonJtaDataSource" value-ref="hash1DataSource"/>
                    <!-- it's not good that I'm turning weaving off -->
                    <!-- <entry key="eclipselink.weaving" value="false"/> -->
                </map>
            </property>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
                    <property name="databasePlatform" value="oracle" />
                    <property name="database" value="ORACLE" />
                    <property name="generateDdl" value="true" />
                    <property name="showSql" value="true" />
                </bean>
            </property>
        </bean>
    
        <!-- datasources, etc -->
    </beans>
    
  • ngCoder
    ngCoder almost 7 years
    Hi @James "Ensure you are not accessing your classes before accessing the Spring context." How to achieve this because I'm facing the same issue.Please suggest.