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.

Advertisements

2010/02/13

Spring Roo and JSF 2?

Filed under: development — Tags: , , , , , , , , — digitaljoel @ 2:07 pm

In my latest project we’ve been playing with Spring Roo.  You can read all about the advantages of it on that site, but the gist is that it creates your entities and JPA persistence code for them.  It will also configure your database connection, generate unit tests, generate a JSP/JSTL based UI with all of the Spring MVC controllers, and selenium tests for it.  It will also optionally integrate Spring Web Flow into the mix.  It’s basically a web based CRUD application in a box.

I spent the last 3 days trying to figure out how to use JSF 2 in Glassfish 3 with a Roo generated application.  Much of this pain may have been caused by my lack of experience with JPA and Spring, but here are a few of the difficulties I faced.

  • JSF 2 is not well supported in eclipse yet, whereas Netbeans 6.8 has excellent JSF 2 support.
  • All of the entities created by Roo just have properties.  All of the getters, setters, and other methods are all included in aspect files and compiled into the entity through AspectJ.  The AspectJ plugin for eclipse takes care of this if you have weaving enabled.  Guess what… There’s no aspect based plugin available for Netbeans, so you get a ton of compile problems in your Roo generated project if you try to open it within Netbeans.
  • The Roo projects are all maven based.  I have yet to see really good success with any maven integration within Eclipse.  Netbeans maven integration is spot on.  For the past 2.5 years I’ve been developing within Eclipse and simply doing all of the maven stuff from the command line because it’s much simpler than dealing with Maven in Eclipse.
  • JSF can’t be used to call Spring MVC controllers.  The Spring MVC controllers generated by Roo are nice.  They are simple and clean, and having them managed by Roo is just that much better.  Unfortunately, Spring MVC is stateless, whereas JSF is stateful, so calling any Spring MVC controller from JSF without using Spring’s Web Flow just doesn’t work.
  • JSF 2 can’t be used in the current version of Spring Web Flow.  Even though a sub component of Web Flow is Spring Faces, the current version of Spring Faces only supports JSF 1.x.  As soon as I put Spring Faces in the classpath, my JSF 2 app wouldn’t render any .xhtml files for me.  Removing Spring Faces from the classpath allowed me to render .xhtml with JSF 2.
  • The transaction type specified in the Roo generated persistence unit is RESOURCE_LOCAL.  Glassfish 3 told me I had to use JTA.  I believe Roo can generate a jndi based data source, which I haven’t tried yet.  I ended up manually modifying the persistence unit (after a lot of time on Google) to be jndi based and have the JTA transaction type.  Unfortunately, this means that all of the Roo generated unit tests fail.  I suspect if I had Roo generate the jndi data source then the unit tests would also pass, so hopefully this issue was self inflicted.  Update: I created a simple project with a jndi datasource.  Unfortunately, all of the unit tests fail.   There is some information in the (closed as won’t fix) bug at https://jira.springsource.org/browse/ROO-311 It would be nice if the unit tests that are created for Roo would use the Spring SimpleNamingContext (and I may be just making stuff up now because I don’t know a lot about Spring/JNDI stuff) or something to allow the unit tests to run if the persistence setup uses jndi.

So why would I continue in my endeavor to use JSF 2 with my Roo project, and where do I go from here?

We are trying to make development as easy as possible for the designers.  They have next to no Java experience at best and just want to tweak styles, layout, and images.  I believe JSF can do a great job of giving us that separation.  I can get the controls working in the form, and they can move them around and do whatever they want with them.  Also, with the composite components in JSF 2, we should be able to make some very nice reusable components for the designers to use in our application.  Finally, many of those components we should be able to share with other projects in the company.

So what is the solution to all of the above problems?

  • Education.  Obviously learning more about JPA and Spring will make the whole journey a little easier for me.
  • Separate projects.  If we have all of the domain model in one maven project, and have the web based UI in another (which is how it really ought to be anyway) then the java developers can use Eclipse or STS for their IDE and get the AspectJ support, and the web designers can use Netbeans 6.8 for the JSF 2 project and get the great support there.  Because the domain model will simply be a jar dependency for the web project all of the aspect based methods will be compiled into the class, meaning we won’t need any Aspect support within Netbeans.

What would it take to get a JSF 2 UI generator into Roo?

  • The Roo team has released a nearly 100 page document about Roo.  Unfortunately, all of the parts about how to implement a new addon for Roo are marked as TBC.  There’s precious little detail on the web too.  Unfortunately, I’m not quite ready to dive into the source code to try to figure it out.  So, a simple Roo addon isn’t quite there.  Update: The only reference I found regarding writing your own Roo addon is at http://www.slideshare.net/desmax74/spring-roo-internals-javaday-iv and the slides leave a lot to the imagination of the reader.
  • Rumors in the Spring forums are that Spring Faces is going to be a new top level project, freed from the grasp of Spring Web Flow, and that the next version (due in June 2010?) will support JSF 2.  I was quite excited to use Web Flow with JSF 2 for the bean management relating to flows.  For instance, a new whatsit wizard that spans multiple pages and manages the scope of the new whatsit bean.
  • Because JSF doesn’t work so well with Spring MVC without Web Flow, and Web Flow won’t support JSF 2 until Spring Faces is split out and both Web Flow and Spring Faces release their next version I believe it’ll be months at best before we see any JSF 2 capabilities within Roo.  The only way it could happen sooner is if someone dives into the Roo source code and creates a third-party addon that will generate JSF 2 controllers and xhtml pages.

So, there it is.  At least 3 days of pain, trial and error, and research all wrapped up in one blog post.

Create a free website or blog at WordPress.com.