0

This is not a duplicate as the tag above purports. This question has not yet been answered.

I am trying to set up this tutorial to get hyperjaxb to work in an eclipse project. How can I get it to see a persistence provider? hbm2ddl has NOT created the table structure in the database yet. Is that why the app is not seeing a persistence provider? Or is it because the contents of persistence.xml in target/generated-sources are not accessible from the src/main/java directory in which my TestFunctions.java is trying to call it? Here are the specifics... This line of code:

entityManagerFactory = Persistence.createEntityManagerFactory("persistence.xml", persistenceProperties);  

Is throwing this error:

Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named persistence.xml
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
    at maintest.TestFunctions.setUpPersistence(TestFunctions.java:119)
    at maintest.Main.main(Main.java:10)

The code throwing the error is in this method:

public void setUpPersistence(){
    final Properties persistenceProperties = new Properties();
    InputStream is = null;
    try {
        Class<? extends TestFunctions> c = getClass();
        ClassLoader cl = c.getClassLoader();
        is = cl.getResourceAsStream("persistence.properties");
        persistenceProperties.load(is);
    }catch (IOException i) {i.printStackTrace();}
    finally {if (is != null) {try {is.close();} catch (IOException ignored) {}}}
    entityManagerFactory = Persistence.createEntityManagerFactory("persistence.xml", persistenceProperties);
}  

persistence.xml:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <persistence-unit name="org.jvnet.hyperjaxb3.ejb.tests.po">
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.Items</class>
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.Items$Item</class>
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.PurchaseOrderType</class>
            <class>org.jvnet.hyperjaxb3.ejb.tests.po.USAddress</class>
        </persistence-unit>
    </persistence>

persistence.properties is:

hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.username=someusername
hibernate.connection.password=somepassword
hibernate.connection.url=jdbc:mysql://localhost/somedatabasename
hibernate.hbm2ddl.auto=create-drop
hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
hibernate.jdbc.batch_size=0

The directory structure for the eclipse project is:


**EDIT: **

Just for kicks, I moved the META-INF folder to the same level as the calling class, but I get the same error. Here are two new screen shots showing locations of persistence.xml in which the error is still thrown:


SECOND EDIT:

I added Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider"); at line 116 of TestFunctions.java, which triggers the following error when I right click on Main.java and do Run As..Java Application:

Exception in thread "main" java.lang.ClassNotFoundException: org.eclipse.persistence.jpa.PersistenceProvider
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:169)
    at maintest.TestFunctions.setUpPersistence(TestFunctions.java:116)
    at maintest.Main.main(Main.java:10)  

Here is the new TestFunctions.setUpPersistence() method:

public void setUpPersistence() throws ClassNotFoundException{
    final Properties persistenceProperties = new Properties();
    InputStream is = null;
    try {
        Class<? extends TestFunctions> c = getClass();
        ClassLoader cl = c.getClassLoader();
        is = cl.getResourceAsStream("persistence.properties");
        persistenceProperties.load(is);
    }catch (IOException i) {i.printStackTrace();}
    finally {if (is != null) {try {is.close();} catch (IOException ignored) {}}}//org.jvnet.hyperjaxb3.ejb.tests.po
    Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider");
    entityManagerFactory = Persistence.createEntityManagerFactory(/*"org.jvnet.hyperjaxb3.ejb.tests.po"*//*"persistence.xml"*/"org.jvnet.hyperjaxb3.ejb.tests.po", persistenceProperties);
}

When I replace Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider"); with Class c = Class.forName("org.hibernate.ejb.HibernatePersistence");, I get a similar error. However, Class c = Class.forName("javax.persistence.spi.PersistenceProvider"); does not throw any error, so the program continues until the same javax.persistence.PersistenceException: No Persistence provider for EntityManager named org.jvnet.hyperjaxb3.ejb.tests.po error gets thrown further downstream.

Does this tell us more about the cause of the error? Also, hyperjaxb creates a persistence.xml and places it in the target folder. This error occurred when persistence.xml was in that location, and has persisted when I move persistence.xml as shown above. Is hyperjaxb causing this problem by not playing nicely with eclipse?

Community
  • 1
  • 1
CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • possible duplicate of [No Persistence provider for EntityManager named X](http://stackoverflow.com/questions/19322827/no-persistence-provider-for-entitymanager-named-x) – lexicore Oct 14 '14 at 20:11
  • @lexicore This is not a duplicate because I tried every answer in the other question, and still get the error. I am looking for a deeper explanation. The only thing from the other posting I have not tried is `Class c = Class.forName("org.eclipse.persistence.jpa.PersistenceProvider");`. Where would I place that? – CodeMed Oct 14 '14 at 20:19
  • @lexicore Is this caused by a clash between `hyperjaxb` and eclipse? Please see my second edit above. – CodeMed Oct 14 '14 at 20:51
  • The tutorial uses Hibernate als JPA provider, you're trying to instantiate EclipseLink. – lexicore Oct 14 '14 at 21:49
  • @lexicore Thank you! I did figure that out. (See my second edit above.) At the moment, I am starting through the steps in your answer. – CodeMed Oct 14 '14 at 21:52

2 Answers2

3

I just can't resist, this is my final attempt to help. :) I'm writing this for you and for any users who may encounter similar issues.

I believe you simply have a problem in the Eclipse project configuration. The paths in your Eclipse project do not seem correct.

Normally, when you import an existing Maven project into Eclipse using File > Import... > Existing Maven Projects, m2eclipse should analyse the structure of the Maven project and create Eclipse project with (.classpath and .project files) automatically.

The paths in these projects are derived from your Eclipse pom.xml. So you actually should not create/modify/add/remove/copy/move/whatever Eclipse source folders. If you do this, your Eclipse project will no longer be synchronized with your Maven project and you'll get really weird results.

Sometimes m2eclipse does not do its job well. Sometimes you don't get the right source folders, things go missing etc. From my experience, this got radically better over the time and right now m2eclipse works like a charm. From what I saw in your struggles, it might be that you have an older version of m2eclipse. Maybe not, but I'd suggest to check it anyway.

Next, sometimes m2eclispe still clamps. In this cases it is highly recommended to do the following things:

  • Clean the project: Project > Clean...
  • Update the Maven project (Alt + F5). Make sure to update the project configuration from pom.xml

enter image description here

Finally you should get the following project structure:

enter image description here

Specifically, you should get the following source folders:

  • src\main\java - source folder for your main Java files
  • src\main\resources - source folder for resources
  • target\generated-sources\xjc - source folder for the generated code.
    • Important: not target\generated-sources like you have but target\generated-sources\xjc.
    • This folder contains the generated Java classes. (Hyperjaxb adds JPA annotations to them).
    • It also contains META-INF\persistence.xml which is a persistence unit descriptor. The META-INF\persistence.xml resource is specified by the JPA spec. This is where the persistence unit will be loaded from.
    • If you've generated a roundtrip test (xml-to-the-db-and-back), then you'll also see a RoundtripTest class somewhere. This is a JUnit test class, it should be possible to execute it directly. (Run As > JUnit Test)
  • src\test\java - test classes.
  • src\test\resources - test resources

This is a standard directory layout for Maven projects. The only peculiarity is the target\generated-sources\xjc source folder which holds the code generated by the schema compiler. And even this is absolutely standard, it is a usual convention for Maven code-generation plugins to generate code in target\generated-sources\some-tool directories.

Below I post the .classpath file from my project:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" output="target/classes" path="src/main/java">
        <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry including="**/*.java" kind="src" output="target/classes" path="target/generated-sources/xjc">
        <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="src" output="target/test-classes" path="src/test/java">
        <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="output" path="target/classes"/>
</classpath>

Important

If you don't have this directory structure (and your screenshots show that you don't) DO NOT move on. It will fail (it does for you). Fix your project structure first. Do not move on, don't try to run anything, you'll run into all kinds of strange things like not found resources etc. (which you do).

Regenerate project structure from pom.xml and clean the project in Eclipse. Open your .classpath file and compare it line-by-line with what I posted. But please do fix the project structure first.

Next, it is important that you understand that you are not supposed to move or drag-and-drop the generated code. It is not the right thing to do. Don't do it. Please don't move on until you accept this as an imperative. Don't move or modify the generated code. If you do, you overtake the responsibility for this code. Things are generated the way they are because it works this way. So if you change it it is very likely that it won't work anymore (it does not for you). If you will need to change anything, you change the pom.xml which configures the generation, not the resulting code.

Now, let us analyse your current project structure based on the following screenshot:

enter image description here

What I can notice:

  • src\main\java contains maintest\Main and TestFunctions. If you're trying to write a test, put your test classes into src\test\java, not src\main\java.
  • src\main\resources contains persistence.xml, sun-jaxb.episode, persistence.properties and schema.xsd. Only schema.xsd should be there.
    • persistence.xml and sun-jaxb.episode are generated files. And, see above, you must not move them.
    • persistence.properties defines the connection to the database used for testing. So it must be in test resources, namely src\test\resources. Putting it into src\main\resources will finally add this file into the resulting JAR, it's like telling everyone username and password of the database you use for testing
  • src\test\java - this is OK, but your test classes should be here.
  • src\test\resources - persistence.properties should be here.
  • target\generated-sources - this is wrong, this should be target\generated-sources\xjc
    • org.jvnet.hyperjaxb3.ejb.test.po package is under target\generated-sources. It is generated under target\generated-sources\xjc, so what I see means you've moved. Don't do this, see above.
    • xjc is displayed as package. This is actually a leftover after you've (incorrectly) configured target\generated-sources as a source folder. This folder must contain all of the generated sources, now it only contains the RoundtripTest. Which means you moved the generated code. Don't do this, see the imperative above.

So your Eclipse project configuration as displayed above is invalid. Here's my theory on why this happened. I think that your m2eclipse did not process the pom.xml correctly, you were probably missing folders etc. But instead of getting the Eclipse project files to be correctly generated my m2eclipse you have manually added the target\generated-sources and started moving the generated code around. This is not the right way.

Please check and re-check your .classpath until it is equivalent to what I posted. I have zipped and uploaded my sample project which definitely works for me. You can unzip and import it using File > Import... > Existing Projects into Eclipse (not as Maven project).

Finally, you must be able to execute the RoundtripTest as a JUnit test. The test will probably fail, but it must run, you should not be getting NPEs etc. I don't have a MySQL database at hand, so this is what I get at the moment:

Detected [file:/C:/Projects/workspaces/hj3/hyperjaxb3-ejb-template-basic-0.6.0/target/classes/META-INF/persistence.xml].
    RoundtripTest

Loading entity manager factory properties.
    RoundtripTest

Loading entity manager factory properties from [file:/C:/Projects/workspaces/hj3/hyperjaxb3-ejb-template-basic-0.6.0/target/test-classes/persistence.properties].
    RoundtripTest

Could not obtain connection to query metadata
    org.hibernate.cfg.SettingsFactory

com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: 

** BEGIN NESTED EXCEPTION ** 

java.net.ConnectException
MESSAGE: Connection refused: connect

This means that entity manager started correctly but could not connect to the database. If you've configured your test database in the src\test\resources\persistence.properties corretcly, you should be able to connect to the database. And if you'll put a po.xml file to src\test\samples, the roundtrip test will:

  • unmarshal this files
  • save it into the database
  • load it back
  • compare it to the original result

Please get the roundrip test run first before you start your own experiments. Don't copy the code, don't modify it, don't try to bend it to your directory structure. It must run as it is. Don't move on until it does.

Good luck.

Update.

You might also be facing an issue with unresolved dependencies. Please make sure your dependencies are resolved correctly. This is what I see:

enter image description here

If you don't see this, it is bad. Something is wrong with your workspace. Check if you have any error messages in Eclipse. Maybe you have something like:

Plugin execution not covered by lifecycle configuration: org.codehaus.mojo:hibernate3-maven-plugin

Quick-fix it first ("Permanently mark goal ... as ignored in Eclispe build"). Don't move on until this error is gone. This is a blocker.

Community
  • 1
  • 1
lexicore
  • 42,748
  • 17
  • 132
  • 221
  • I want to re-import the project from scratch to reproduce your steps. Note that your project name is `hyperjaxb3-ejb-template-basic-0.6.0` and mine is `hyperjaxb3-ejb-samples-po-initial-maven`. Is that part of our problem communicating? I can only find `version 0.5.6` at your web site. – CodeMed Oct 14 '14 at 22:20
  • https://github.com/highsource/hyperjaxb3/releases but this should not make any difference as the projects are almost identical. – lexicore Oct 14 '14 at 22:24
  • +1. I need to spend time with this tomorrow to check everything & assess the situation. For now, it seems to be creating the tables in the MySQL database, inserting data into & retrieving data from the database. My eclipse project has a slightly different structure than yours, but the `classpath` file is the same. It has not generated the `ddl`, though I imagine I can find a way to generate that from `hbm2ddl` or MySQL. When I finally get everything checked and tested, let's you & I collaborate to cleanup all these postings so other users can benefit, & so that neither you nor I feels beat up. – CodeMed Oct 15 '14 at 01:19
  • +1 for the effort. I think this should help solving the problem. – Eduardo Briguenti Vieira Oct 15 '14 at 12:34
  • After studying the installed code, I have one comment and one question: `Comment:` I had to disable a JPA compile error in eclipse using `Properties-->Java Compiler-->Errors/Warnings`. `Question:` Where do I put production code that needs to work with the generated classes? `Main.java/TestFunctions.java` work when located in `src/test/java` but fail after being moved to `src/main/java`. – CodeMed Oct 15 '14 at 17:28
  • Please ask two further separate questions, it's ok. JPA - would be good to know the error (JPA can't be _compile_ error). Prod code - ask it. We're overblowing the comments. :) – lexicore Oct 15 '14 at 18:56
  • ok. I will save those questions to ask later. I saved a backup of the working eclipse project and used a copy to test swapping out the xsd and xml files with real files I have tested in jaxb. I would like to debug them myself, but I am getting nebulous error messages. I posted that as a separate question at this link: http://stackoverflow.com/questions/26391467/importing-new-schema-into-hyperjaxb – CodeMed Oct 15 '14 at 21:40
  • @lexicore the thing that might be relevant still to this question is that following your instructions above explicitly created a `...po` package instead of a `...pocustomized` package, so I had to change the line in the pom.xml that contains `pocustomized` to `po` when running `mvn clean install` in the question linked in my preceding comment. If this does not matter, then we can ignore it and move on. I really do not care unless it creates other problems further down the line. – CodeMed Oct 15 '14 at 21:43
  • @CodeMed It is important that you use exactly the same persistence unit name in `RoundtripTest.getPersistenceUnitName()`, `persistence.xml`, must be also the name of the package where the classes are generated (see `bindings.xjb`). – lexicore Oct 15 '14 at 21:48
  • @lexicore The persistence unit name in both the generated `persistence.xml` and the generated `RoundtripTest.getPersistenceUnitName()` are both `org.jvnet.hyperjaxb3.ejb.tests.po` instead of `org.jvnet.hyperjaxb3.ejb.tests.pocustomized` from the `pom.xml`, so `RoundtripTest,java` and `persistence.xml` at least match each other even if they are different than the `pom`. There was no `bindings.xjb` generated when I explicitly followed all your steps above. – CodeMed Oct 15 '14 at 21:54
  • @lexicore I just downloaded your zip file above. Let me make a copy of it, then swap out the `xsd` and `xml` files before doing `mvn clean install` on its root folder. This will help determine whether we should focus on my other question or on why my system gave me a slightly different structure from your same explicit instructions. – CodeMed Oct 15 '14 at 22:02
  • @CodeMed Ok, then it's good. Just update the `pom.xml` then. I think you mean the `jpaconfiguration` line in `hbm2ddl`, right? The `persistenceunit` there should have the same name as everywhere else. For `bindings.xjb` check `src\main\resources`. It is not generated, it is manually written. Maybe you don't have that in your sample. I think I use this one: https://github.com/highsource/hyperjaxb3/blob/master/ejb/tests/po-customized/src/main/resources/bindings.xjb This file basically customizes the generation. – lexicore Oct 15 '14 at 22:06
2

The parameter you should pass is the persistence-unit. (Not the file name.)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="1.0" ... >
    <persistence-unit name="generated">
        <class>generated.Items</class>
        <class>generated.Items$Item</class>
        <class>generated.PurchaseOrderType</class>
        <class>generated.USAddress</class>
    </persistence-unit>
</persistence>

So it should be generated for the persistence.xml above:

entityManagerFactory = Persistence.createEntityManagerFactory("generated", persistenceProperties);

For your persistence, should be:

entityManagerFactory = Persistence.createEntityManagerFactory("org.jvnet.hyperjaxb3.ejb.tests.po", persistenceProperties);
Eduardo Briguenti Vieira
  • 4,351
  • 3
  • 37
  • 49
  • I now have `entityManagerFactory = Persistence.createEntityManagerFactory("org.jvnet.hyperjaxb3.ejb.tests.po", persistenceProperties);` and kept `` in `persistence.xml` but the error is now `No Persistence provider for EntityManager named org.jvnet.hyperjaxb3.ejb.tests.po`. Did I do what you suggest? – CodeMed Oct 14 '14 at 17:34
  • @CodeMed Can you double-check the persistence.xml is actually in the JAR and at the proper location? – Puce Oct 14 '14 at 18:02
  • @Puce Which JAR? persistence.xml is indeed in the eclipse directory structure. I have not created any JARs, and I would not know which imported JAR if any to look in. – CodeMed Oct 14 '14 at 18:25
  • Take a look at the solution provided here: http://stackoverflow.com/questions/19322827/no-persistence-provider-for-entitymanager-named-x/19327322#19327322 – cmd Oct 14 '14 at 20:08
  • @cmd Please see in my edit above the printscreens that show the `src\main\java\META-INF\persistence.xml` location suggested in your link. The same error is still being thrown when I run Main.java with `persistence.xml` in the new location. What else could be causing this problem? – CodeMed Oct 14 '14 at 20:21
  • @edubriguenti I added more information after trying different variations of `Class.forName()` at the end of my posting above. – CodeMed Oct 14 '14 at 21:40
  • @CodeMed You have a Maven project (pom.xml). Please runt "mvn clean install" and inspect the generated JAR in the target directory. Double-check that the persistence.xml file is in the correct location and the content of the persistence.xml is as you want it. – Puce Oct 15 '14 at 08:03