DigitalJoel

2012/11/23

Eclipselink static weaving

Filed under: development, eclipse, java — Tags: , , — digitaljoel @ 11:26 pm

I’m playing with a new project and decided to get eclipselink static weaving working in this one. I started on the official eclipselink project documentation on the subject. That’s nice and all, but it doesn’t say anything about getting the weaving to work with maven or eclipse. I really wanted both. Here’s what I did.

First, in persistence.xml you should add the following property:

    <properties>
      <property name="eclipselink.weaving" value="static" />
    </properties>

My maven project has several modules. domain-api contains the entity definitions. domain-impl contains the code for interacting with the database. That means that my persistence.xml is contained in domain-impl and the @Entity classes are in domain-api. That’s alright. To get this all working I decided to use the command line option rather than use the ant task.

The weaving needs to take place on the entities, so the weaving step is placed in the domain-api pom.xml. Within build/plugins I added this plugin.

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>1.2.1</version>
        <executions>
          <execution>
            <id>weave-classes</id>
            <phase>process-classes</phase>
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>org.eclipse.persistence.tools.weaving.jpa.StaticWeave</mainClass>
          <commandlineArgs>-classpath %classpath -loglevel FINE -persistenceinfo ${basedir}/../domain-impl/src/main/resources ${basedir}/target/classes ${basedir}/target/classes</commandlineArgs>
        </configuration>
      </plugin>

That’ll run the java program to weave the class files in place. Note that my -persistenceinfo argument points to ../domain-impl/src/main/resources. That’s because the StaticWeave class will look for META-INF/persistence.xml within that directory, and my persistence.xml is contained in the domain-impl module, not within domain-api. If you are using maven resource filtering on your persistence.xml this will cause a problem since domain-impl builds after domain-api. That’s not a problem in my case so I’m going to be lazy and not address it.

Once you have that in your pom you should be able to do a mvn clean install and see output something like:

[INFO] --- exec-maven-plugin:1.2.1:java (weave-classes) @ domain-api ---
[EL Config]: metadata: 2012-11-23 23:15:42.798--ServerSession(1166215941)--Thread(Thread[org.eclipse.persistence.tools.weaving.jpa.StaticWeave.main(),5,
org.eclipse.persistence.tools.weaving.jpa.StaticWeave])--
The access type for the persistent class [class com.xyg.model.JoelTest] is set to [FIELD].

I added line breaks for formatting. Anyway, that kind of output means things are working.

Sadly, Eclipse’s maven integration isn’t smart enough to figure this part of the pom out. If we tell Eclipse to ignore this part of the build then the classes won’t get weaved and it’s likely that if you try to run the project from within eclipse it’s not going to work properly. Fortunately, we can work around this.

Within the same pom (in my case, in domain-api) you can add another plugin. This plugin is NOT within the plugins element, but is within a pluginManagement element. You can get eclipse to generate the entry for you by telling it to ignore the execution when it tells you it has an error because it has no lifecycle mapping for the given execution. When you do that it’ll generate an xml block in your pom.xml that will look like this:

    <pluginManagement>
      <plugins>
        <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
        <plugin>
          <groupId>org.eclipse.m2e</groupId>
          <artifactId>lifecycle-mapping</artifactId>
          <version>1.0.0</version>
          <configuration>
            <lifecycleMappingMetadata>
              <pluginExecutions>
                <pluginExecution>
                  <pluginExecutionFilter>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <versionRange>[1.2.1,)</versionRange>
                    <goals>
                      <goal>java</goal>
                    </goals>
                  </pluginExecutionFilter>
                  <action>
                    <execute/>
                  </action>
                </pluginExecution>
              </pluginExecutions>
            </lifecycleMappingMetadata>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>

The version eclipse generates will say something like <ignore></ignore> in the action section of this configuration. If you simply change that to <execute/> then eclipse will execute it. It will execute it every time, even on incremental builds, so hopefully it isn’t too intrusive. I’m just getting started on this project so I don’t have many entity classes yet, but if there’s an issue I’ll get back and update this post.

With this configuration I’m able to execute my integration tests from the command line and I’m also able to run the tests and launch the webapp from within eclipse, and I don’t incur the runtime penalty of dynamic weaving.

Blog at WordPress.com.