1

I'm tinkering a Jersey Webservice that access the default JavaDB integrated into the Glassfish4 Application Server. The idea is to create new objects during the runtime of the application on the server and use the Java Persistence API (JPA) to access them even if the server is shut down or the application is being removed from the server.

The first question would be if this is a viable option?

The second question is regarding some a problem I have with injecting the EntityManagerFactory so I can access it while handling the HTTP requests.

My simple test case looks like this:

@Path("jpaResource/")
public class JpaResource {

    @PersistenceUnit
    private EntityManagerFactory emf;

    @GET
    @Path("html")
    @Produces(MediaType.TEXT_HTML)
    public String getHtml() {

        EntityManagerFactory factory = Persistence.createEntityManagerFactory("WebApp");    System.out.println(aThing);     }

        Thing thing = (Thing) factory.createEntityManager().createQuery("select u from Thing u").getResultList().get(1);

        return "<h1>Hey HTML! I'm: " + thing.getDescription() + "</h1>";        
    }

    @GET
    @Path("text")
    @Produces(MediaType.TEXT_PLAIN)
    public String getText() {

        Thing thing = (Thing) emf.createEntityManager().createQuery("select u from Thing u").getResultList().get(0);

        return "Hey text! I'm: " + thing.getDescription();
    }
}

The first GET method works fine. However the second one doesn't because the EntityManagerFactory emf is NULL.

The Thing object is a simple POJO and looks like:

@Entity
@NamedQuery(name="Thing.findAll", query="SELECT t FROM Thing t")
public class Thing  {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    private String description;
    private String summary;

    public Thing() {
    }

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getSummary() {
        return this.summary;
    }

    public void setSummary(String summary) {
        this.summary = summary;
    }
}

The persistence.xml file is stored in the .../src/main/resources/META-INF folder of my eclipse project and looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
    <persistence-unit name="WebApp" transaction-type="RESOURCE_LOCAL">
        <!--provider>org.eclipse.persistence.jpa.PersistenceProvider</provider-->
        <!--provider>org.hibernate.ejb.HibernatePersistence</provider-->
        <jta-data-source>jdbc/__default</jta-data-source>
        <class>com.test.webapp.objects.Thing</class>
        <properties>
            <property name="eclipselink.ddl-generation" value="create-tables"/>
            <property name="eclipselink.ddl-generation.output-mode" value="database"/>
        </properties>
    </persistence-unit>
</persistence>

The stacktrace looks like this:

StandardWrapperValve[Jersey Web Application]: Servlet.service() for servlet Jersey Web Application threw exception
java.lang.NullPointerException
    at com.test.webapp.resources.JpaResource.getText(JpaResource.java:66)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:125)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:91)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:346)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:341)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:101)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:224)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:198)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:946)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:323)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
    at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
    at java.lang.Thread.run(Thread.java:744)

If someone has any idea what I'm doing wrong please let me know.

Greetings

[edit: ] Ok I did some more testing and I have an implementation of the ServletContextListener interface in my project that handles initialization when the application is started for the first time.

public class ServletContextClass implements ServletContextListener {

    @PersistenceUnit(unitName="WebApp")
    private EntityManagerFactory emf;

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        System.out.println("##############################");

        System.out.println("ServletContextListener started");

        System.out.println("##############################");       
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

        System.out.println("###############################");

        System.out.println("SevletContextListener destroyed");

        System.out.println("###############################");      
    }
}

In this class the injection works without any problems and I'm able to access the JavaDB to retrieve the objects.

The tutorial I watched used a Glassfish3 server. Is it possible that this feature was removed from Java EE7 and thus is not working on a Glassfish4 Server? I found a similar question that suggests that my approach should work with Java EE 6 (PersistenceContext EntityManager injection NullPointerException). Now I'm really confused.

I will add my web.xml so if someone is interested in answering my question and needs the deployment descriptor.

<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
     see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
     <listener>
        <listener-class>com.test.webapp.startup.ServletContextClass</listener-class>
      </listener>
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.test.webapp.resources</param-value>
        </init-param>

        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>
Community
  • 1
  • 1
Scyla
  • 199
  • 3
  • 14
  • I guess the problem is that you create a new EntityManagerFactory and a new EntityManager on every request, change that to a single instance which is created on class init. Also I would recommend to switch to JTA. – unwichtich Mar 26 '14 at 22:14
  • I'm not sure that I understand that completely. What I want to to is use @PersistenceUnit to inject the EntityManagerFactory once. The way I understand it is that the framework then will initialize the EntotyManagerFactory for me and make it available to use in the class through injection (maybe my Idea of the concept is wrong). However the injection won't work because it is always NULL. I followed the youtube tutorials by Arun Gupta (Java EE 6 and GlassFish 3 with Eclipse) and he seems to have no problems using it that way. – Scyla Mar 27 '14 at 07:37
  • Why don't you make your service a Stateless EJB and inject the EntityManager directly? The application server will take care of creating and managing the EMF for you. – perissf Mar 28 '14 at 14:11
  • Yeah I thought about that solution too. However it seems like that you cannot do this because I have a dynamic web project and I cannot include the EJB Module into this one. – Scyla Mar 31 '14 at 11:22
  • Sure you can. I don't know how to do this in Eclipse, but I am sure you can. – perissf Mar 31 '14 at 13:55
  • Is there anything other to do than adding the @Stateless annotation to create a Stateless EJB that tells the application server to inject the EntityManagerFactory into this class? – Scyla Apr 01 '14 at 12:16

0 Answers0