This is part 2 of this blog and it assumes you have read Part 1.
In part 1 of this blog we have achieved a basic "ping" service that responds to a get request with just some static answer - "pong".
Normally you want to access a database and do some nice stuff. The best way to achieve a nice service layer is (in my opinion) to use EJB. You can control access rights, transactions etc. right by annotating your EJB in a nice and simple way. And you get your EntityManager or Datasource for JPA or JDBC directly injected without so much "boiler plate" code. So I want to show how to incopreate EJB in our setup. So the task I want to solve is adding an EJB with an entity manager injected and returning the result as a JSON object.
So first turn your project to a JPA project by adding this project facet in Eclipse.
Then we need a simple EJB:
/**
* EJB
*/
package com.sap.myapp;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
* Simple EJB
*/
@LocalBean
@Stateless
public class MyEJB {
@PersistenceContext EntityManager em;
public MyJSONResult doSomething() {
MyJSONResult result = new MyJSONResult();
result.setState(em != null ? "em is injected :-)" : " em not inject :-(");
return result;
}
}
It does nothing else as to give me the state of the injected entity manager. For the sake of completeness I have to add the MyJSONResult class, which is just a simple POJO:
/**
* JSON bean
*/
package com.sap.myapp;
/**
* Simple Bean as result of EJB call
*/
public class MyJSONResult {
private String state;
/**
* @return the state
*/
public String getState() {
return state;
}
/**
* @param state the state to set
*/
public void setState(String state) {
this.state = state;
}
}
If we would have the Java Web Profile level 7 not 6 on HCP this would be very easy (and I could not write this blog) all you would have to do is add your EJB to your new service. So my service would look like:
/**
* REST
*/
package com.sap.myapp;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* Simple REST Service
*/
@Path("/service")
public class MyService {
@EJB MyEJB myEjb;
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public Response myService() throws ServletException {
return Response.ok().entity(myEjb.doSomething()).build();
}
}
This would result in a Nullpointer Exception as the EJB is not injected. So there is some more magic needed as long as we stay with Jave Web Profile 6. We have to do a JNDI lookup of the bean before we can use it. By doing JNDI we get a fully working container managed EJB and we have to do that in every service method that wants to use EJB.
So the extended service will look like the following:
/**
* REST
*/
package com.sap.myapp;
import javax.ejb.EJB;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* Simple REST Service
*/
@Path("/service")
public class MyService {
@EJB MyEJB myEjb;
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
public Response ping() throws ServletException {
lookupEJBs();
return Response.ok().entity(myEjb.doSomething()).build();
}
private void lookupEJBs() throws ServletException {
if (myEjb == null) {
try {
InitialContext ic = new InitialContext();
myEjb = (MyEJB) ic.lookup("java:comp/env/ejb/MyEJB");
}
catch (NamingException e) {
throw new ServletException(e);
}
catch (Exception e) {
throw new ServletException(e);
}
}
}
}
For the JNDI lookup to work you have to add your EJB to the web.xml:
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJB</ejb-ref-name>
<local>com.sap.myapp.MyEJB</local>
</ejb-local-ref>
So you tried it all out and your ping-pong service works but your new service gives a 404? Then you forgot to add your new service class to "MyApplication" as we did with the PingService in Part 1
Thats it, if you call now your application with the relative path "/rest/service" you get a JSON response.
{"state":"em is injected :-)"}
Explore the power of Jersey, even stuff as file upload can be done with a few simple annotations. If someone is interested in that I may add a third part to this small blog series