Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to statically weave JPA entities using EclipseLink when there is no persistence.xml as the entities are managed by Spring

I've got a project that is Spring based, so the entity manager is set up progammatically, with no need for persistence.xml files to list all the entities.

I'm currently using load time weaving but am trying to get static weaving working using Eclipselink and Gradle. I want to replicate what is performed by the maven eclipselink plugin:

https://github.com/ethlo/eclipselink-maven-plugin

I have the following gradle set up (note that it's Kotlin DSL not groovy):

task<JavaExec>("performJPAWeaving") {


    val compileJava: JavaCompile = tasks.getByName("compileJava") as JavaCompile
    dependsOn(compileJava)

    val destinationDir = compileJava.destinationDir

    println("Statically weaving classes in $destinationDir")
    inputs.dir(destinationDir)
    outputs.dir(destinationDir)
    main = "org.eclipse.persistence.tools.weaving.jpa.StaticWeave"
    args = listOf("-persistenceinfo", "src/main/resources", destinationDir.getAbsolutePath(), destinationDir.getAbsolutePath())

    classpath = configurations.getByName("compile")


}

When I try and run the task the weaving tasks fails as it's looking for a non-existent persistence.xml.

Is there any way you can statically weave JPA entities in a Spring based JPA project ?

Exception Description: An exception was thrown while processing persistence.xml from URL: file:/home/blabla/trunk/my-module/src/main/resources/
Internal Exception: java.net.MalformedURLException
        at org.eclipse.persistence.exceptions.PersistenceUnitLoadingException.exceptionProcessingPersistenceXML(PersistenceUnitLoadingException.java:117)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceXML(PersistenceUnitProcessor.java:579)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceArchive(PersistenceUnitProcessor.java:536)
        ... 6 more
Caused by: java.net.MalformedURLException
        at java.net.URL.<init>(URL.java:627)
        at java.net.URL.<init>(URL.java:490)
        at java.net.URL.<init>(URL.java:439)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:620)
        at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:148)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:806)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
        at org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.processPersistenceXML(PersistenceUnitProcessor.java:577)
        ... 7 more
Caused by: java.lang.NullPointerException
        at java.net.URL.<init>(URL.java:532)
        ... 17 more
like image 404
PaulNUK Avatar asked Mar 14 '19 11:03

PaulNUK


2 Answers

According to org.eclipse.persistence.tools.weaving.jpa.StaticWeave documentation, it requires the persistence.xml in place to generate the static weaving sources.

Usage:
StaticWeave [options] source target

Options:
-classpath Set the user class path, use ";" as the delimiter in Window system and ":" in Unix system.

-log The path of log file, the standard output will be the default.

-loglevel Specify a literal value for eclipselink log level(OFF,SEVERE,WARNING,INFO,CONFIG,FINE,FINER,FINEST). The default value is OFF.

-persistenceinfo The path contains META-INF/persistence.xml. This is ONLY required when the source does not include it. The classpath must contain all the classes necessary in order to perform weaving.

I run a maven build using eclipselink maven plugin, it works without the persistence.xml as you mentioned, because it generates the persistence.xml before invoking the StaticWeave.class when It is not located in the CLASSPATH, using this method.

 private void processPersistenceXml(ClassLoader classLoader, Set<String> entityClasses)
    {
        final File targetFile = new File(this.persistenceInfoLocation + "/META-INF/persistence.xml");
        getLog().info("persistence.xml location: " + targetFile);

        final String name = project.getArtifactId();
        final Document doc = targetFile.exists() ? PersistenceXmlHelper.parseXml(targetFile) : PersistenceXmlHelper.createXml(name);

        checkExisting(targetFile, classLoader, doc, entityClasses);

        PersistenceXmlHelper.appendClasses(doc, entityClasses);
        PersistenceXmlHelper.outputXml(doc, targetFile);
    }

The complete source code is here

I believe you could follow the same approach in your gradle build.

like image 132
eHayik Avatar answered Sep 29 '22 10:09

eHayik


Kinda late to the party but this is definitely possible with Gradle.

There are 3 steps to do in order to make this work:

  • Copy the persistence.xml file into the source folder next to the classes
  • Do the weaving
  • Remove the persistence.xml file from the classes source folder to avoid duplicate persistence.xml conflicts on the classpath

Also, it's very important to hook the weaving process into the compileJava task's last step in order to not break Gradle's up-to-date check, otherwise Gradle will just recompile everything all the time which can be quite inconvenient when developing.

For a more detailed explanation, check out my article on it: EclipseLink static weaving with Gradle.

like image 34
Arnold Galovics Avatar answered Sep 29 '22 12:09

Arnold Galovics