JPA EntityManager Nullpointer Exception when splitting functionality in multiple classes (Glassfish, EclipseLink) - rest

i know there are masses of questions concerning a similar problem, but i didn't manage to extract a solution for my problem.
I'm trying to build a RESTful webapplication that serves data, which is provided using JPA (EclipseLink 2.4) and runs on Glassfish 3.1.2.2.
For testing i set up a guestbook database in mysql and created this all-in-one solution:
// imports etc...
// Guestbook class has #Entity
#Stateless
#Path("guestbook")
public class GuestService {
#PersistenceContext
private EntityManager em;
#GET
public Response entry() {
Guestbook entry = em.find(Guestbook.class, someid);
return Response.ok(entry.getMsg()).build();
}
}
This works perfectly well, but i want to split it in to several layers like so: REST -> DAO -> Entity
Which would transform to:
#Stateless
#Path("guestbook")
public class GuestService {
private DAO dao;
#GET
public Response entry() {
Guestbook entry = dao.getEntry(someid);
return Response.ok(entry.getMsg()).build();
}
}
// ...
public class DAO {
#PersistenceContext
private EntityManager em;
public Guestbook getEntry(int someid) {
return em.find(Guestbook.class, someid);
}
}
So this would produce a nullpointer exception when accessing the em in getEntry() because it is null.
My persistence.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="..." xmlns:xsi="..." xsi:schemaLocation="...">
<persistence-unit name="guestbook" transaction-type="JTA">
<jta-data-source>jdbc/mysqldatasource</jta-data-source>
<class>model.Guestbook</class>
</persistence-unit>
</persistence>
Thanks in advance, i'm looking forward for your suggestions!

You've abstracted the DAO from GuestService just fine, but it seems that you forgot to make the DAO a #Stateless EJB and inject it in your GuestService using #EJB annotation.
#Stateless
public class DAO {
#PersistenceContext
private EntityManager em;
...
}
#Stateless
#Path("guestbook")
public class GuestService {
#EJB
private DAO dao;
...
}
I hope it helps!

Related

#ManyToOne(fetch=FetchType.LAZY) lazy loading not working

I am working with JPA 2.1 (EclipseLink 2.5.1) and JBoss 7.1.
I've define very simple JPA entities:
#Entity
#Table(name="APLICACIONES_TB")
public class Aplicacion implements Serializable {
#Id
#Column(name="COD_APLICACION_V")
private long codAplicacionV;
#Column(name="APLICACION_V")
private String aplicacionV;
#OneToMany(mappedBy="aplicacion")
private Collection<Prestacion> prestaciones;
... getters and setters
}
#Entity
#Table(name="PRESTACIONES_TB")
public class Prestacion implements Serializable {
#Id
#Column(name="COD_PRESTACIONES_V")
private String codPrestacionesV;
#Column(name="DESCRIPCION_V")
private String descripcionV;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name = "COD_APLICACION_V")
private Aplicacion aplicacion;
... getters and setters ...
}
I have developed a staless EJB that executes a query to obtain some "Aplicacion" entities.
#Stateless
#LocalBean
public class DocuEJB implements DocuEJBLocal
{
#PersistenceContext(name="DocuEjb", type=PersistenceContextType.TRANSACTION)
private EntityManager em;
public Prestacion getResult(String name)
{
return em.createNamedQuery("ExampleQueryName", Prestacion.class).getSingleResult();
}
}
Because I'm working with JSF 2.1 the EJB is being injected in a managed bean:
#ManagedBean(name = "ManagedBean")
#RequestScoped
public class ManagedBean
{
#EJB DocuEJB docuEjb;
public String doSomething()
{
Prestacion entity = docuEjb.getResult("egesr");
if (entity != null)
{
// It should return null because 'entity' should be detached
Aplicacion app = entity.getAplicacion();
// but 'app' entity is not null, ¿why not?
System.out.println (app.getCodAplicacionV());
}
}
}
Lazy loading is not working even when lazy loading has been defined for 'aplicacion' field on 'Prestacion' entity. The code posted before should return a NullPointerException in the next line:
System.out.println (app.getCodAplicacionV());
because 'app' entity is detached and lazy loading has been configured.
Why is not working lazy loading?
Thanks
Try to add #Transactional on doSomething(), I think that your transaction manager is not well configured.
You can see here the official spring documentation. In any case, can you add your spring configurations, so that we can better help you. :)
I don't think the behavior your encounter is abnormal or your question should state it clearly:
EJB are by default transactional
Your JSF inject an EJB, with #EJB, and I guess JBoss can create a java reference and not a proxy
The entity is being managed because the transaction is not done, it will finish when doSomething ends.
Your entity is then loaded into the EntityManager, and lazy loading works because there is a context to it.
You would call em.evict(entity) with the result your are getting, this would probably fails because the entity would not be managed any more.

PersistanceContext on NonServlet class

I have the following...
public class TestServlet extends HttpServlet {
#PersistenceContext
private EntityManager em;
...
}
#Stateless
#LocalBean
public class DeviceRegistrationPersister {
#PersistenceContext(unitName="deviceReg")
private EntityManager em;
...
}
The first one gets the entity manager just fine, however, the second the entity manager is null. Can someone help with what is going on?

How to inject service to hibernate.ejb.interceptor with google guice?

I have an issue with injecting a service to predefined interceptor using google guice.
What i'm trying to do is to use emptyinterceptor to intercept changes with entities. Interceptor itself works fine, the problem is that I can't figure out how to inject a service to it. Injections themselves work fine throughout the whole application.
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/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">
<persistence-unit name="db-manager">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>test.Address</class>
<properties>
<property name="hibernate.ejb.interceptor" value="customInterceptor"/>
</properties>
</persistence-unit>
how im trying to inject
public class CustomInterceptor extends EmptyInterceptor {
private static final Logger LOG = Logger.getLogger(CustomInterceptor.class);
#Inject
private Provider<UploadedFileService> uploadedFileService;
...
}
how JpaPersistModule is initiated
public class GuiceListener extends GuiceServletContextListener {
private static final Logger LOG = Logger.getLogger(GuiceListener.class);
#Override
protected Injector getInjector() {
final ServicesModule servicesModule = new ServicesModule();
return Guice.createInjector(new JerseyServletModule() {
protected void configureServlets() {
// db-manager is the persistence-unit name in persistence.xml
JpaPersistModule jpa = new JpaPersistModule("db-manager");
...
}
}, new ServicesModule());
}
}
how services are initiated
public class ServicesModule extends AbstractModule {
#Override
protected void configure() {
bind(GenericService.class).to(GenericServiceImpl.class);
bind(AddressService.class).to(AddressServiceImpl.class);
}
}
I searched for hours and have find no real solution, so the ugly workaround I am using is to create 2 interceptors.
The first one is bound correctly by hibernate but does not have anything injected. It calls the second interceptor via some other mechanism - in the example below via a static reference to the InjectorFactory. The second interceptor is not bound to Hibernate, but like any other class, it can happily have stuff injected into it.
//The first ineterceptor has methods like this...
#Override
public synchronized void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
InjectorFactory.getInjector().getInstance(MyOtherInterceptor.class).onDelete(entity, id, state, propertyNames, types);
}
d
//The second one has the real implementation
#Inject
public MyOtherInterceptor() {
}
#Override
public synchronized void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
//Full implementation
}
//etc

Entity states between EJB and Jersey

I'm a novice.
Does Jersey and EJB hold the same EntityManager scope?
Should I have to pass the EntityManager to EJB for same persistence context?
The primary target usage is JTA.
#Stateless
class MyEJB {
public MyEntity find(Long id) {
...
}
#PersistenceContext;
EntityManager entityManager;
}
class MyResource {
#GET
#Path("/myentity/{id}");
public MyEntity get(#PathParam("id") final long id) {
final MyEntity found = myEjb.find(id);
// is found's state detached?
// should I have to reattach?
found.setDate(new Date());
return found;
}
#EJB
private MyEjb myEjb;
#PersistenceContext;
EntityManager entityManager;
}
Does Jersey and EJB hold the same EntityManager scope?
Should I have to pass the EntityManager to EJB for same persistence context?
I don't think that your wording is correct, but they can share the same EntityManager instance, and you have chosen the right way (through injection). Have a look at this chapter of the Java EE 6 Tutorial:
To obtain an EntityManager instance, inject the entity manager into the application component:
#PersistenceContext
EntityManager em;
So, once again, your approach is correct. With regards to the questions in the code comments: the fact that MyEntity is attached or detached, it depends on the implementation of the find method in your EJB. If you do the following, it will be attached:
public MyEntity find(Long id) {
return entityManager.find(MyEntity.class, id);
}
Finally, doing this way, if you have chosen JTA to use container managed transactions, the transactions will be automatically bounded with the natural boundaries of MyBean's methods. In order to have JTA transactions, you have to use this line in persistence.xml file:
<persistence-unit name="em" transaction-type="JTA">

Testing an EJB with JUnit

How should I test an EJB 3.1 which gets an instance of EntityManager injected?
A possible EJB:
#Stateless
#LocalBean
public class CommentService {
#PersistenceContext
private EntityManager em;
public List<Comment> findAll() {
TypedQuery<Comment> query = em.createNamedQuery(
Comment.FIND_ALL, Comment.class
);
return query.getResultList();
}
}
A possible test:
#Test
public void testFindAll() {
List<Comment> all = service.findAll();
Assert.assertEquals(8, all.size());
}
I am only using GlassFish 3.1 and Eclipse Indigo for Java EE Developers. I already tried things like that:
#Before
public void setUp() throws Exception {
ejbContainer = EJBContainer.createEJBContainer();
service = (CommentService) ejbContainer.getContext()
.lookup("java:global/classes/CommentService");
}
But all I got was:
javax.ejb.EJBException:
No EJBContainer provider available: no provider names had been found.
The accepted answer requires mocking a lot of code, including the persistence layer. Use an embedded container to test the actual beans, instead; otherwise, mocking the persistence layer results in code that barely tests anything useful.
Use a session bean with an entity manager that references a persistence unit:
#Stateless
public class CommentService {
#PersistenceContext(unitName = "pu")
private EntityManager em;
public void create(Comment t) {
em.merge(t);
}
public Collection<Comment> getAll() {
Query q = em.createNamedQuery("Comment.findAll");
Collection<Comment> entities = q.getResultList();
return entities;
}
}
The entity bean:
#Entity
#NamedQueries({#NamedQuery(name = "Comment.findAll", query = "select e from Comment e")})
public class Comment implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
This persistence unit is defined in the persistence.xml file as follows:
<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="pu" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>org.glassfish.embedded.tempconverter.Comment</class>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
The transaction type must be JTA.
Then write a test that creates and destroys the EJB container (GlassFish embedded container):
public class CommentTest extends TestCase {
private Context ctx;
private EJBContainer ejbContainer;
#BeforeClass
public void setUp() {
ejbContainer = EJBContainer.createEJBContainer();
System.out.println("Opening the container" );
ctx = ejbContainer.getContext();
}
#AfterClass
public void tearDown() {
ejbContainer.close();
System.out.println("Closing the container" );
}
public void testApp() throws NamingException {
CommentService converter = (CommentService) ctx.lookup("java:global/classes/CommentService");
assertNotNull(converter);
Comment t = new Comment();
converter.create(t);
t = new Comment();
converter.create(t);
t = new Comment();
converter.create(t);
t = new Comment();
converter.create(t);
Collection<Comment> ts = converter.getAll();
assertEquals(4, ts.size());
}
}
Next, add two dependencies (such as to a Maven POM):
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.glassfish.main.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.1.2</version>
<scope>compile</scope>
</dependency>
Having the dependencies, session and entity bean, persistence file, test files implemented exactly as shown, then the test(s) should pass. (The examples on the Internet are woefully inadequate.)
First of all, make sure you distinguish between unit tests and integration tests. JUnit is just a framework that helps you organize and run the tests, but you have to determine the scope of your tests.
I assume you're interested in defining a unit test of CommentService.findAll(). What does that mean? That means I'll verify that calling the findAll() method results in CommentService invoking the named query named by the FIND_ALL string constant.
Thanks to dependency injection and stubbing, you can easily achieve that using e.g. Mockito to stub out the EntityManager. For the unit test, we're only focusing on the business logic in findAll(), so I won't bother testing lookup of the Comment service either--testing that the Comment service can be looked up and is wired to a proper entity manager instance is in the scope of an integration test, not a unit test.
public class MyCommentServiceUnitTest {
CommentService commentService;
EntityManager entityManager;
#Before
public void setUp() {
commentService = new CommentService();
entityManager = mock(EntityManager.class);
commentService.setEm(entityManager); // inject our stubbed entity manager
}
#Test
public void testFindAll() {
// stub the entity manager to return a meaningful result when somebody asks
// for the FIND_ALL named query
Query query = mock(Query.class);
when(entityManager.createNamedQuery(Comment.FIND_ALL, Comment.class)).thenReturn(query);
// stub the query returned above to return a meaningful result when somebody
// asks for the result list
List<Comment> dummyResult = new LinkedList<Comment>();
when(query.getResultList()).thenReturn(dummyResult);
// let's call findAll() and see what it does
List<Comment> result = commentService.findAll();
// did it request the named query?
verify(entityManager).createNamedQuery(Comment.FIND_ALL, Comment.class);
// did it ask for the result list of the named query?
verify(query).getResultList();
// did it return the result list of the named query?
assertSame(dummyResult, result);
// success, it did all of the above!
}
}
With the unit test above, I tested the behavior of the findAll() implementation. The unit test verified that the correct named query is obtained and that the result returned by the named query was returned to the callee.
What's more, the unit test above verifies that the implementation of findAll() is correct independently of the underlying JPA provider and the underlying data. I don't want to test JPA and the JPA provider unless I suspect there are bugs in the 3rd party code, so stubbing out these dependencies lets me focus the test entirely on the business logic of the Comment service.
It can take a little while to adjust to the mindset of testing behavior using stubs, but it is a very powerful technique for testing the business logic of your EJB 3.1 beans because it lets you isolate and narrow the scope of each test to exclude external dependencies.
Why not using Arquillian to write even unit tests and run them in a real container!?
No more mocks. No more container lifecycle and deployment hassles. Just real tests!
Mocks can be tactical, but more often than not, they are used to make code work outside of a real environment. Arquillian let's you ditch the mocks and write real tests. That's because Arquillian brings your test to the runtime, giving you access to container resources, meaningful feedback and insight about how the code really works.
More about Arquillian features.
It's possible to write unit tests that run against a container, but the caveat is that the container/appserver has to be up. Since that's not really practical, the general approach is to use a "mock" container to run your unit tests against. For that, check out JUnitEE or ejb3unit:
junitee
ejb3unit