3 Replies Latest reply on Jun 13, 2006 3:16 PM by hallorant

    Hooking up a servlet to Chap4 example

    hallorant

      I've tried to build a servlet that talks to the TravelAgentBean described in Chapter 4

      I've packaged the EJB into a "jar," the Servlet into a "war," and created a "ear" that contains them both with a "application.xml" description

      I added jndi to the bean as shown below

      @Stateless
      @RemoteBinding(jndiBinding = "TravelAgentRemote")
      public class TravelAgentBean implements TravelAgentRemote {

      all the rest of the code is as in the book. Both the Bean and the client described in Chapter 4 work great!

      My problem, however, is I can't get a Servlet to talk to this Bean. I created a simple servlet:

      package com.titan.presentation;

      import java.io.IOException;

      import javax.naming.Context;
      import javax.naming.InitialContext;
      import javax.rmi.PortableRemoteObject;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      import com.titan.domain.Cabin;
      import com.titan.travelagent.TravelAgentRemote;

      public class CabinQueryServlet extends HttpServlet {

      private static final long serialVersionUID = 875301256543193160L;

      TravelAgentRemote agent;

      @Override
      public void init() throws ServletException {
      try {
      Context context = new InitialContext();
      Object ref = context.lookup("java:comp/env/ejb/TravelAgentRemote");
      //Object ref = context.lookup("TravelAgentBean/remote");
      agent = (TravelAgentRemote) PortableRemoteObject.narrow(ref,
      TravelAgentRemote.class);
      } catch (Exception e) {
      throw new ServletException(e.getMessage(),e);
      }
      }

      @Override
      protected void doGet(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
      String cabinNumberRaw = request.getParameter("cabinNumber");

      if (cabinNumberRaw == null)
      response.getWriter().write("Please specify an cabin number");
      else {
      int cabinNumber = Integer.parseInt(cabinNumberRaw);
      Cabin cabin = agent.findCabin(cabinNumber);
      if (cabin == null) {
      response.getWriter().write(
      "Cabin no. " + cabinNumber + " does not exist");
      } else {
      response.getWriter().write(
      "You requested cabin no. " + cabin.getId() + "");
      response.getWriter().write(
      "Its name is " + cabin.getName() + "");
      response.getWriter().write(
      "Its on ship no. " + cabin.getShipId() + "");
      response.getWriter().write(
      "Its on deck " + cabin.getDeckLevel() + "");
      response.getWriter().write(
      "Its bed count is " + cabin.getBedCount() + "");

      }
      }
      }
      }

      With a web.xml containing:

      <?xml version="1.0" encoding="ISO-8859-1"?>
      <!DOCTYPE web-app
      PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
      "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
      <web-app>

      <servlet-name>CabinQuery</servlet-name>
      <servlet-class>
      com.titan.presentation.CabinQueryServlet
      </servlet-class>


      <servlet-mapping>
      <servlet-name>CabinQuery</servlet-name>
      <url-pattern>/CabinQuery.html</url-pattern>
      </servlet-mapping>
      </web-app>

      When I deploy this to the server and query the page I get the following exception:

      14:33:58,017 INFO [EARDeployer] Started J2EE application: file:/D:/jboss-4.0.4.GA/server/default/deploy/Titan.ear
      14:34:04,210 ERROR [[CabinQuery]] Allocate exception for servlet CabinQuery
      javax.naming.NameNotFoundException: ejb not bound
      at org.jnp.server.NamingServer.getBinding(NamingServer.java:529)
      at org.jnp.server.NamingServer.getBinding(NamingServer.java:537)
      at org.jnp.server.NamingServer.getObject(NamingServer.java:543)
      at org.jnp.server.NamingServer.lookup(NamingServer.java:267)
      at org.jnp.server.NamingServer.lookup(NamingServer.java:270)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:625)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:716)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:587)
      at javax.naming.InitialContext.lookup(InitialContext.java:351)
      at com.titan.presentation.CabinQueryServlet.init(CabinQueryServlet.java:26)
      at javax.servlet.GenericServlet.init(GenericServlet.java:211)
      at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1105)
      at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:757)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:130)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
      at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
      at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
      at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
      at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
      at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
      at java.lang.Thread.run(Thread.java:595)
      14:34:08,589 ERROR [[CabinQuery]] Allocate exception for servlet CabinQuery
      javax.naming.NameNotFoundException: ejb not bound
      at org.jnp.server.NamingServer.getBinding(NamingServer.java:529)
      at org.jnp.server.NamingServer.getBinding(NamingServer.java:537)
      at org.jnp.server.NamingServer.getObject(NamingServer.java:543)
      at org.jnp.server.NamingServer.lookup(NamingServer.java:267)
      at org.jnp.server.NamingServer.lookup(NamingServer.java:270)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:625)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:716)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:587)
      at javax.naming.InitialContext.lookup(InitialContext.java:351)
      at com.titan.presentation.CabinQueryServlet.init(CabinQueryServlet.java:26)
      at javax.servlet.GenericServlet.init(GenericServlet.java:211)
      at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1105)
      at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:757)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:130)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
      at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
      at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
      at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
      at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
      at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
      at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
      at java.lang.Thread.run(Thread.java:595)

      I think I have two problems:

      (1) I have no idea what should be in the web application (I dumped all the classes from the bean jar) in? Just the remote interface class? In EJB prior to this version the container created a remote JAR for me. How is this working in EJB 3.0? Do I include the Bean class and the remote interface?

      (2) I got something wrong in the JNDI naming, the book implied (on page 60) my above approach would work...but some salent detail escapes me :-)

        • 1. Re: Hooking up a servlet to Chap4 example
          bill.burke

          you have not bound the EJB reference into your WAR's ENC.

          • 2. Re: Hooking up a servlet to Chap4 example
            hallorant

            Thanks (still not working) but this pointed me in the right direction. My web.xml is now augmented (from above) with


            <ejb-ref>
            <ejb-ref-name>ejb/TravelAgentRemote</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>

            com.titan.travelagent.TravelAgentRemote
            </ejb-ref>


            (not rendering properly the home tag is empty and the remote has the class reference...they are there:-)

            and my jboss-web.xml is


            <jboss-web>
            <ejb-ref>
            <ejb-ref-name>ejb/TravelAgentRemote</ejb-ref-name>
            <jndi-name>TravelAgentRemote</jndi-name>
            </ejb-ref>
            </jboss-web>


            Now when I invoke the servlet I get:


            HTTP Status 405 - HTTP method POST is not supported by this URL

            type Status report

            message HTTP method POST is not supported by this URL

            description The specified HTTP method is not allowed for the requested resource (HTTP method POST is not supported by this URL).
            Apache Tomcat/5.5.17


            and nothing at the console...which is odd since up until the ejb-ref was added the servlet was invoked just fine (with "fine" resulting in the exception trace posted in my first message way up top). I think I still have this muddled (for example, I have no idea what to put in the home tag.). Any ideas? Lots of searching failed to turn up a good description of how to do this configuration with EJB 3.0.

            • 3. Re: Hooking up a servlet to Chap4 example
              hallorant

              One detail I've figured out is that packaging up the Chapter 4 example as a EAR file causes the JNDI name to change. Given the code for the TravelAgentBean DOES NOT change the default remote binding (I deleted the @RemoteBinding annotation shown in the TravelAgentBean class shown way up above). The Java client code in Chapter 4 has to be changed from


              Context jndiContext = getInitialContext();
              Object ref = jndiContext.lookup("TravelAgentBean/remote");
              TravelAgent dao = (TravelAgent) PortableRemoteObject.narrow(ref,
              TravelAgent.class);


              to


              Context jndiContext = getInitialContext();
              Object ref = jndiContext.lookup("Titan/TravelAgentBean/remote");
              TravelAgent dao = (TravelAgent) PortableRemoteObject.narrow(ref,
              TravelAgent.class);


              where the name of my EAR file is "Titan.ear" Thus, the default name of the bean is changed by packaging in an EAR versus a EJB JAR. This makes perfect sense, but is a bit subtle. I'm now going back to try to get the Servlet to know about the bean.

              One other thing I did is make the interface both the local and the remote the same interface (I removed "Remote" from the code on page 54).


              @Remote
              @Local
              public interface TravelAgent {
              public void createCabin(Cabin cabin);
              public Cabin findCabin(int id);
              }


              Is this going to cause me grief? It seems to work OK.