2

I created a dynamic web project named HibernateSetUpTest2, jpa is marked as one of the project facets. I want to put this on a tomcat server in the future but right now I simply need to test if hibernate is working and it isn't.

I followed the MySQL DBCP Example on here (except for the jsp part): https://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html

Now my xmls look like this:

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence     http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="unitName" transaction-type="JTA">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <jta-data-source>jdbc/TestDB</jta-data-source>
        <class>entities.TestDataRow</class>
        <properties>
            <property name="hibernate.transaction.jta.platform"
                value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
            <!-- andere properties hier definiëren -->
            <!-- geen properties definiëren voor password, user, driver etc; want 
                we gebruiken datasource -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.connection.autocommit" value="true" />
        </properties>
    </persistence-unit>
</persistence>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>HibernateSetUpTest2</display-name>
  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/TestDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

In the project explorer of eclipse it shows a separate folder named Servers and in it is the context.xml :

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
        <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/javatest"/>
</Context>

In my src folder I wrote a Test:

package tests;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import entities.TestDataRow;

public class Hibernate {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("unitName");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        TestDataRow t = em.find(TestDataRow.class, 1);
        System.out.println(t.getFoo());

        tx.commit();
        em.close();
        emf.close();
    }
}

This uses the entity:

package entities;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="testdata")
public class TestDataRow {
    @Id
    private int id;
    private String foo;
    private int bar;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getFoo() {
        return foo;
    }
    public void setFoo(String foo) {
        this.foo = foo;
    }
    public int getBar() {
        return bar;
    }
    public void setBar(int bar) {
        this.bar = bar;
    }
}

When I run the test as a java application it throws errors:

Dec 14, 2015 3:34:31 PM org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
    name: unitName
    ...]
Dec 14, 2015 3:34:31 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.0.5.Final}
Dec 14, 2015 3:34:31 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Dec 14, 2015 3:34:31 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Dec 14, 2015 3:34:31 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
Exception in thread "main" javax.persistence.PersistenceException: Unable to build entity manager factory
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:66)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
    at tests.Hibernate.main(Hibernate.java:12)
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:244)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:208)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:51)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.handleTypes(MetadataBuildingProcess.java:352)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:111)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:770)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:797)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
    ... 3 more
Caused by: org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [jdbc/TestDB]
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:124)
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:95)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:98)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:94)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:217)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:189)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:88)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:234)
    ... 14 more
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
    at javax.naming.InitialContext.getNameParser(InitialContext.java:505)
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:118)
    ... 24 more

What am I doing wrong?

BRNTZN
  • 564
  • 1
  • 7
  • 21

2 Answers2

1

Your code itself looks fine (can't tell for sure but nothing seems to be seriously wrong) but you have a huge issue with your test itself:

It is a standalone test.

What the errormessage is telling you:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property

Basically means, that while attempting to lookup the JNDI variable (your DB resource definition) it had nowhere to "look". There is no context in your test. That is why it failed.

The standard ways of dealing with this kind of problem are:

  • either programmatically creating a context
  • or - just for the sake of the test - inserting a DB resource definition via simple autowiring, and not using JNDI at all.

Example and source for further ideas can be found here: Setting up JNDI Datasource for uni testing

Community
  • 1
  • 1
Gergely Bacso
  • 14,243
  • 2
  • 44
  • 64
  • If I do the "test" in a servlet instead, should that work? `protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { EntityManagerFactory emf = Persistence.createEntityManagerFactory("unitName"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); TestDataRow t = em.find(TestDataRow.class, 1); System.out.println(t.getFoo()); tx.commit(); em.close(); emf.close(); }` Also throws the same errors – BRNTZN Dec 14 '15 at 15:18
  • That sounds really weird. If you don't want to inject this and bypass JNDI (which most people would do), and you would rather "hack" it, then this little lib seems to work for many people: http://stackoverflow.com/a/12569727/821786 . My advise would still be to do it via dependency injection though. – Gergely Bacso Dec 14 '15 at 15:22
0

I think you need some initialisation or its a lack of configuration

jndi.java.naming.provider.url=jnp://localhost:1099/
jndi.java.naming.factory.url=org.jboss.naming:org.jnp.interfaces
jndi.java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
Lhoussaine
  • 59
  • 1
  • 11