Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member

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 :wink:

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 :smile:

3 Comments