Maven, spring-data JPA, EclipseLink and static weaving

Introduction

My last Vaadin project at work is a somehow complex application and I was looking for a persistence layer which matches perfectly the given techniques Maven and Spring.

I wanted to avoid Hibernate’s lazy loading exceptions, so I searched for alternatives and found EclipseLink as standard JPA implementation (I also planed to use JPA to be able to switch the object relational mapper – just in case…).

In the meantime I found spring-data JPA which is a real cool framework which reduces persistence boiler plate code dramatically.

The only problem was: I was not able to find any example project which had a running setup for spring-data JPA and EclipseLink.

Weaving? Load Time Weaving? Static Weaving?

EclipseLink modifies the model classes bytecode to provide Lazy-Loading. This process is called weaving. EclipseLink is able to weave dynamically in run-time or the weaving can be done statically in compile-time. So what to choose?

We used Tomcat as servlet container and no full J2EE server so we had the opportunity to choose and I learned: dynamic weaving is no good in Java SE environments! It works, but is is very fragile and if you plan to use dynamic weaving in your JUnit tests, then you are on your way right to hell.

Project setup

As I don’t want to explain everything detailed here in my blog, I created a fully working example project which can be found in my GIT repository

https://bitbucket.org/flexguse/spring-data-jpa-demo

At the time of writing you can check-out the trunk, but to be sure use the tag “general-setup”.

EclipseLink static weaving with Maven

EclipseLink does not provide any Maven plugin to do extend the Java bytecode for lazy loading but fortunately somebody else did the job.

Add

<!-- This plugin ensures the EclipseLink static weaving -->
<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>

to your POM file. If you are working with Eclipse and m2e you need to configure the m2e lifecycle-mapping plugin to have the static weaving in Eclipse (see my POM as example).

Normally you should not be aware of the working static weaving, but you can control it for example in a decompiler or your debugger (dynamic weaving adds the methods, too!). In your models there should be now a couple of methods you haven’t added.

weaving-added-methodsEclipseLink configuration

In a lot of examples I found in the web EclipseLink was configured using the persistence.xml to set the datasource. In my world I often deploy an application on different servers (local, development, staging, production) so it is not the best idea to have some static database credentials in the persistence.xml.

In my example I gave the credentials in the persistence.xml but in a real world project one would use LocalContainerEntityManagerFactoryBean and set the datasource (see src/test/resources/repository-context.xml).

The EclipseLink properties can also be set in the Spring configuration and not in persistence.xml, which gives you additional flexibility.

What you need to do (no there seems to be no way to omit this), is to give all model classes in persistence.xml, which shall be statically woven!

Spring-Data JPA AuditorAware

spring-data JPA provides a built in auditing mechanim (creator, lastChanger, creationDate and lastUpdate date are set automatically), which are quite handy. To have this, you just need to extend

org.springframework.data.jpa.domain.AbstractAuditable

and you are ready to go. That works perfectly, but NOT with static weaving!

AbstractAuditable is annotated as

@MappedSuperclass

which caused EclipseLink in my setup to stop the weaving process and so several methods required for lazy-loading were not present.

My workaround was to create a custom audatible class

de.flexguse.demo.model.CustomAbstractAuditable

(ok, it mainly was copy&paste) and the static weaving worked perfectly.

Further configuration

Well, from now on there is no special to configure, everything is documented in the spring-data JPA documentation.

Just add some JPA 2.0 annotations to your model classes, create your repository interfaces and configure Spring so seach for your repository interfaces to the classpath.

Running examples

In the repository you can find some JUnit testcases (some would say that are integrations tests…) which should run out of the box. A H2 database is started in the JUnit tests and all persistence operations are done against it.

Enjoy to try it out!

Conclusion

Maven, spring-data JPA and EclipseLink work quite nice together if some pitfalls are avoided and if you know where to do the configurations.

In the real life work project lazy-loading with EclipseLink works quite nice and we have a robust and performant solution. Spring-data JPA makes you very flexible in extending your models and it is very easy to persist, update, delete and find.

Even if you are not in a J2EE heavy duty business application, try spring-data JPA and EclipseLink!

Advertisements

4 thoughts on “Maven, spring-data JPA, EclipseLink and static weaving

  1. Hello,

    How can you say that the static weaving took place ? I wrote this code :
    ======================================================
    public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext(“repository-context.xml”);
    AuthorRepository authorRepository = context.getBean(“authorRepository”, AuthorRepository.class);
    BookRepository bookRepository = context.getBean(“bookRepository”, BookRepository.class);

    Book book = new Book();

    book.setIsbnNumber(“1234567890”);
    book.setDescription(“This is a wonderful book.”);
    book.setTitle(“The Art of living”);

    // the author must be existend in the persistence when it is assigned to
    // the book -> CascadingType
    Author author = createAuthor();
    authorRepository.save(author);
    book.setAuthor(author);

    bookRepository.save(book);

    // check a book was persisted
    Book availableBook = bookRepository.findOne(book.getId());

    // with lazy loading [@ManyToOne(fetch = FetchType.LAZY) Author author] should not be available outside the JPA context that is now closed
    // nevertheless I got ‘Simon’
    System.out.println(availableBook.getAuthor().getFirstName());
    }

    static Author createAuthor() {
    Author author = new Author();
    author.setFirstName(“Simon”);
    author.setLastName(“Becket”);
    author.seteMail(“simon.becket@book.de”);
    return author;
    }

    }

    ========================
    When I ask a book, because of the lazyness of the relationship [@ManyToOne(fetch = FetchType.LAZY) Author author] i shouldn’t get the author. Isn’t that so ? But i obtained ‘Simon’.

    In fact, I could comment the lines :

    <!–

    –>

    and I obtained the same result. Where is my mistake ?

  2. Hi Serge,

    I’m not sure if I understood your code. In case you are using Eclipselink, Spring and JPA I can’t see anything which closed the JPA context. As far I understood Eclipselink one main feature is your models are extended (dynamic or static weaving) so Eclipselink is able to reopen a JPA session.

    If you want to check if static weaving took place you could use a Java decompiler and inspect the generated .class files of your model beans. If static waving took place several methods are added by Eclipselink starting with underscore “_”.

    Additionally I recommend to use the Maven Plugin http://search.maven.org/#artifactdetails|de.empulse.eclipselink|staticweave-maven-plugin|1.0.0|maven-plugin. This plugin tells you in the maven build process which classes were statically woven.

    Good luck!
    Christoph

    1. “In case you are using Eclipselink, Spring and JPA I can’t see anything which closed the JPA context”. So that’s the point. I thought that the JPA context was closed as with Hibernate. Thank you.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s