title: SessionContext is always null in Session-Bean called from a Servlet
body: <p>My job is to write kind of a webservice adapter using a Servlet which then calls an adapter EJB (SOAP webservice) which in turn calls the existing service methods (also EJBs).
  The existing architecture is based on EJB 2.0, which I can't change for now.
  External customers are supposed to access the Servlet and not the webservice class directly.
  The reason for this is that some pre-processing needs to be done using information in the HTTPRequest (fetching and mapping user-id from certificate resp. the HTTP Header).
  So, the Servlet reacts on the doPost() method, performs a preprocessing like parsing and marshalling the SOAP XML data and then calls the adapter EJB (stateless Session Bean), 
  more precisely the webservice methods which will then trigger existing service methods in a different EJB.
  This works well so far until the EJBs require an existing Session resp. SessionContext, like in the following case where transaction rollback is handled:</p>
  
  <pre class="lang-java prettyprint-override"><code>protected void preventTransactionRolledBackException() {
      if (this.getSessionContext().getRollbackOnly()) {
          this.getSessionContext().setRollbackOnly();
      }
  }
  </code></pre>
  
  <p>In my setup, SessionContext is always null.
  As the whole application is already quite complex I try to post a simplified setup using only the Servlet and one EJB, hoping I'm not excluding something relevant.
  System: WebSphere Application Server 8.5</p>
  
  <p>Servlet:</p>
  
  <pre class="lang-java prettyprint-override"><code>public class NewZekEclsServiceServlet extends HttpServlet {
      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          String operation = null;
          response.setContentType("text/xml");
          try { 
              PrintWriter out = response.getWriter(); 
              // Get Header data
              // Get Attribute data
              // Get Body data:
              InputStream body = request.getInputStream();
              String xml = IOUtils.toString(body, "UTF-8");
  
              DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
              docBuilderFactory.setNamespaceAware(true); // required as several namespaces might be used
              DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
              Document doc = docBuilder.parse(new InputSource(new StringReader(xml)));
  
              operation = getOperation(doc); // method which scans the xml to retrieve the correct operation to use.
  
              if (operation.equalsIgnoreCase("Ping")) {
  
                  // Calling the Adapter Bean:
                  EclsTestBeanBean eclsTestBean = new EclsTestBeanBean();
                  eclsTestBean.ejbCreate();
  
                  PingIn pingIn = new PingIn();
                  PingOut pingOut = eclsTestBean.ping(pingIn);
  
                  String xmlString = convertEclsObjectToSOAPString(pingOut);
                  out.print(xmlString);
  
              }
          }
      }
  }
  </code></pre>
  
  <p>EJB (generated by Rational Application Developer 9.0):</p>
  
  <pre class="lang-java prettyprint-override"><code>/**
   * Bean implementation class for Session Bean: EclsTestBean
   *
   * @ejb.bean
   *  name="EclsTestBean"
   *  type="Stateless"
   *  jndi-name="ejb/ch/zek/ecls/EclsTestBeanHome"
   *  view-type="remote"
   *  transaction-type="Bean"
   *
   * @ejb.home
   *  remote-class="ch.zek.ecls.EclsTestBeanHome"
   *
   * @ejb.interface
   *  remote-class="ch.zek.ecls.EclsTestBean"
   *
   */
  public class EclsTestBeanBean implements javax.ejb.SessionBean {
  
      private Log log = LogFactory.getLog(EcodeAbfragenAction.class);
  
      private SessionContext mySessionCtx;
  
      public SessionContext getSessionContext() {
          return mySessionCtx;
      }
  
      public void setSessionContext(SessionContext ctx) {
          mySessionCtx = ctx;
      }
  
      public void ejbCreate() throws CreateException {}
      public void ejbActivate() {}
      public void ejbPassivate() {}
      public void ejbRemove() {}
  
      /**
       * Basic ping service for ECLS
       * @param parameters
       * @return
       * @throws PingEntityNotFoundException
       * @throws PingPermissionException
       * @throws PingSystemException
       */
      public ch.zek.ecls.PingOut ping(ch.zek.ecls.PingIn parameters) throws java.rmi.RemoteException, ch.zek.ecls.PingPermissionException, ch.zek.ecls.PingEntityNotFoundException, ch.zek.ecls.PingSystemException {
  
          PingOut pingOut = new PingOut();
          String pingAnswer = "Ping_ECLS_v1";
          String adapter = "";
          String operation = "";
  
          Parameter[] msgParams = new Parameter[1];
          String eclsEnvironment = "TEST";
          pingAnswer += "_" + eclsEnvironment;
  
          logAvailableEjbs();
  
          try {
              if (mySessionCtx != null) { // Why can it be null at all?
                  log.debug("mySessionCtx: " + mySessionCtx.getContextData());
              } else {
                  log.debug("mySessionCtx was null");
                  InitialContext ic = new InitialContext();
                  mySessionCtx = (SessionContext) ic.lookup("java:comp/env/sessionContext"); // gives error:  javax.naming.NameNotFoundException: Name "comp/env/sessionContext" not found in context "java:".
                  System.out.println("mySessionCtx: " + mySessionCtx);
              }
          } catch (Exception e) {
              e.printStackTrace();
          }
          // creating the SOAP data... not relevant for the problem.
          msgParams[0] = new Parameter();
          msgParams[0].setValue(pingAnswer);
          SystemMessage systemMessage = new SystemMessage();
          systemMessage.setCode("OK");
          systemMessage.setMessage("Ping");
          systemMessage.setParameter(msgParams);
          pingOut.setSystemMessage(systemMessage);
  
          return pingOut;
      }
  
      /**
       * ONLY USED DURING DEVELOPMENT:
       * Helper method to print "accessible" EJBs.
       */
      protected void logAvailableEjbs() {
          try {
              //Get the Initial Context for the JNDI lookup for a local EJB
              InitialContext ic = new InitialContext();
  
              NamingEnumeration&lt;NameClassPair&gt; list;
              String level = "";
              String name = "";
              list = ic.list(level);
              while (list.hasMore()) {
                  name = list.next().getName();
                  System.out.println(level + "/" + name);
              }
              level = "ejb";
              list = ic.list(level);
              while (list.hasMore()) {
                  name = list.next().getName();
                  System.out.println(level + "/" + name);
              }   
              level = "java:comp";
              list = ic.list(level);
              while (list.hasMore()) {
                  name = list.next().getName();
                  System.out.println(level + "/" + name);
              }
              level = "java:comp/env";
              list = ic.list(level);
              while (list.hasMore()) {
                  name = list.next().getName();
                  System.out.println(level + "/" + name);
              }
              /*
              level = "java:comp/env/ejb"; // Throws Error!
              list = ic.list(level);
              while (list.hasMore()) {
                  name = list.next().getName();
                  System.out.println(level + "/" + name);
              }
              */
              level = "java:global";
              list = ic.list(level);
              while (list.hasMore()) {
                  name = list.next().getName();
                  System.out.println(level + "/" + name);
              }
          } catch (NamingException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>We are testing the setup using the SoapUI tool (<a href="http://www.soapui.org" rel="nofollow noreferrer">http://www.soapui.org</a>). Again, we get proper results for a simple Ping() service, but as soon as session-related stuff is required it fails.</p>
  
  <p>Of course I did some research, especially interesting was this link:
  <a href="https://stackoverflow.com/questions/1938517/how-to-get-sessioncontext-in-jboss">How to get SessionContext in JBOSS</a>
  which also refers to:
  <a href="http://javahowto.blogspot.co.uk/2006/06/4-ways-to-get-ejbcontext-in-ejb-3.html" rel="nofollow noreferrer">http://javahowto.blogspot.co.uk/2006/06/4-ways-to-get-ejbcontext-in-ejb-3.html</a></p>
  
  <p>And regarding EJB lifecycle: docs.oracle.com/cd/E13224_01/wlw/docs100/guide/ejb/session/conSessionBeanLifeCycle.html
  J2EE-Tutorial: docs.oracle.com/javaee/6/tutorial/doc/gipss.html#gipsx
  (sorry, can't post more than 2 links...)</p>
  
  <p>But as commented in the code, I can't access java:comp/env/ejb/sessionContext. Well... not even java:comp/env/ejb.
  I wrote a dirty helper method to see what is actually accessible to the EJB and get the following output:</p>
  
  <pre><code>SystemOut     O /jta
  SystemOut     O /eis
  SystemOut     O /cell
  SystemOut     O /thisNode
  SystemOut     O /DefaultDatasource
  SystemOut     O /services
  SystemOut     O /jdbc
  SystemOut     O /servername
  SystemOut     O /com.ibm.websphere.ejbcontainer
  SystemOut     O /com
  SystemOut     O /zek
  SystemOut     O /wm
  SystemOut     O /ejb
  SystemOut     O /Increment
  SystemOut     O /tm
  SystemOut     O ejb/ivtEJBObject
  SystemOut     O ejb/ch
  SystemOut     O ejb/mgmt
  SystemOut     O java:comp/ValidatorFactory
  SystemOut     O java:comp/TransactionSynchronizationRegistry
  SystemOut     O java:comp/ORB
  SystemOut     O java:comp/Validator
  SystemOut     O java:comp/UserTransaction
  SystemOut     O java:comp/env
  SystemOut     O java:comp/BeanManager
  SystemOut     O java:comp/websphere
  SystemOut     O java:comp/HandleDelegate
  SystemOut     O java:global/com.ibm.ws.AppNameSpaces
  SystemOut     O java:global/NewZekEar
  SystemOut     O java:global/SchedulerCalendars
  SystemOut     O java:global/DefaultApplication
  SystemOut     O java:global/cell
  SystemOut     O java:global/query
  SystemOut     O java:global/ManagementEJB
  SystemOut     O java:global/ivtApp
  </code></pre>
  
  <p>I also tried to use annotation:
  </p>
  
  <pre><code>@Resource
  private SessionContext mySessionCtx;
  </code></pre>
  
  <p>or setting the transaction type differently:
  </p>
  
  <pre><code>transaction-type="Container"
  </code></pre>
  
  <p>Nothing helped.
  I understood that the SessionContext should be automatically created. But if not - which option does one have to create a new one?
  Further question:
  The servlet also "creates" a session which I can access (request.getSession() ), but this is something different (HTTPSession). I guess I can't share or "convert" this session object to the session Bean?</p>