9 Replies Latest reply on May 29, 2007 4:52 PM by William Woodman

    can any one help me - having a bad day with ejb3 server and

    William Woodman Master

      folks i need some help - i must be going stupid but dont know where - advice greatfully received.

      I have created an EJB project for a simple hello world type stateless session bean that i publish to an 4.2 jboss container .

      I use eclipse as the editor - and have two projects setup, the first for the ejb project, the second project is a standalone application that uses the embedded jboss server (from the seam distro 1.2.1.ga).

      tried several scenarios and cant get the client to call the ejb successfuly.

      in my EJB project i declare a bean like this

      package app;
      
      import javax.ejb.Remote;
      import javax.ejb.Stateless;
      
      import app.client.HelloUser;
      
      // (see later comments on client lookup) @Remote (HelloUser.class)
      @Stateless
      public class HelloUserBean implements HelloUser
      {
       HelloUserBean()
       {};
      
       public String sayHello (String text)
       {
       String msg = "hello " + text + " /n";
       System.out.println(msg);
      
       return msg;
       }
      }
      


      I then have an 'app.client' dir for the bean interfaces. I have a default interface
      package app.client;
      
      import javax.ejb.*;
      
      
      public interface HelloUser
      {
       public String sayHello (String text);
      }
      


      and then extend various interfaces local, remote, WS etc from this e.g.

      package app.client;
      
      import javax.ejb.*;
      
      import app.client.HelloUser;
      
      @Remote
      public interface HelloUserRemote extends HelloUser
      {
      
      }
      


      so far so good. I create a jar file for all the interfaces that i make available to the second project (am i doing the right thing here. Without it i cant make a reference to the class i want when i do a jndi lookup or try DI)

      Then i start the 4.2 server and deploy the ejb project. This goes fine.

      I then have a second straight java project - this includes a /conf dir which is an exact copy of the /conf from the seam embedded dir which i include in my classpath, along with all the /lib jars from the seam /lib dir.

      I then write my main client app code

      /**
       *
       */
       import java.util.Hashtable;
      
      import javax.ejb.EJB;
      import javax.naming.InitialContext;
      
      
      import org.apache.log4j.Level;
      import org.apache.log4j.Logger;
      import org.jboss.ejb3.embedded.EJB3StandaloneBootstrap;
      
      import app.client.HelloUser;
      import app.client.HelloUserRemote;
      
      /**
       * @author Will
       *
       */
      public class ClientApp
      {
       @EJB
       public HelloUser tstHandler;
      
       public ClientApp () {}
      
       public static void main(String[] args) throws Exception
       {
      
       Logger log = Logger.getLogger(ClientApp.class);
       log.setLevel(Level.DEBUG);
       //log.debug("Welcome to Wills App");
      
       // Boot the JBoss Microcontainer with EJB3 settings, automatically
       // loads ejb3-interceptors-aop.xml and embedded-jboss-beans.xml
       EJB3StandaloneBootstrap.boot(null);
      
       // Deploy custom stateless beans (datasource, mostly)
       //EJB3StandaloneBootstrap.deployXmlResource("META-INF/NeilsApp-beans.xml");
      
       // Deploy all EJBs found on classpath (fast, scans build directory)
       // This is a relative location, matching the substring end of one
       // of java.class.path locations. Print out the value of
       // System.getProperty("java.class.path") to see all paths.
       EJB3StandaloneBootstrap.scanClasspath();
      
       InitialContext ctx = getInitialContext();
      
      
       // Look up the stateless TestHandler EJB
       //HelloUserRemote tstHandlerLoc = (HelloUserRemote) ctx.lookup("HelloUserBean/remote");
       // Call the stateless EJB
       //String message = tstHandlerLoc.sayHello("hello Will");
      
       //try dependency injection!
       String message = new ClientApp().tstHandler.sayHello("hello William");
      
      
      
      
       //Shut down EJB container
       EJB3StandaloneBootstrap.shutdown();
      
       }
      
       public static InitialContext getInitialContext() throws Exception
       {
       Hashtable props = getInitialContextProperties();
       return new InitialContext(props);
       }
      
       private static Hashtable getInitialContextProperties()
       {
       Hashtable props = new Hashtable();
       props.put("java.naming.factory.initial", "org.jnp.interfaces.LocalOnlyContextFactory");
       props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
       return props;
       }
      }
      


      as i am not using a Data Source at present so I comment out the

      // Deploy custom stateless beans (datasource, mostly)
      //EJB3StandaloneBootstrap.deployXmlResource("META-INF/NeilsApp-beans.xml");


      section, and have not defined a persistence.xml file for the container yet.


      If i run it like this - the Dependency Injection doesnt work and i get a null pointer exception when i hit the



      String message = new ClientApp().tstHandler.sayHello("hello William");


      If i comment this out and use a JNDI lookup call instead


      // Look up the stateless TestHandler EJB
      HelloUserRemote tstHandlerLoc = (HelloUserRemote) ctx.lookup("HelloUserBean/remote");
      // Call the stateless EJB
      String message = tstHandlerLoc.sayHello("hello Will");


      then i get the following error


      22:39:24,727 INFO [EJBContainer] STARTED EJB: app.HelloUserBean ejbName: HelloUserBean
      Exception in thread "main" javax.naming.NameNotFoundException: remote 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:296)
      at org.jnp.server.NamingServer.lookup(NamingServer.java:270)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:626)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:588)
      at javax.naming.InitialContext.lookup(Unknown Source)
      at ClientApp.main(ClientApp.java:52)


      if however - I uncomment the line in the HelloUserBean and set the @Remote(HelloUser.class), and then proceed to do the lookup in the client app as follows (note i have dropped the HelloUserRemote now)


      // Look up the stateless TestHandler EJB - dont use base interface def, and @Remote in defining bean class
      HelloUser tstHandlerLoc = (HelloUser) ctx.lookup("HelloUserBean/remote");
      // Call the stateless EJB
      String message = tstHandlerLoc.sayHello("hello Will");


      then i seems to work.


      I dont understand why I cant get this to work.

      first off i presume i should use remote as the 4.2 ejb server and the embedded server are running in different VM's (under my single eclipse edit session)

      second - whether its DI or jndi lookup - why cant i find/map the remote interface properly and make the client call?

      any help explaining this to a simpleton would be appreciated.

      regards Wiggy





        • 1. Re: can any one help me - having a bad day with ejb3 server
          fhh Expert

          You have to use @Remote(RemoteInferface.class) on the bean or @Remote on the remote inteface.

          Regards

          Felix

          • 2. Re: can any one help me - having a bad day with ejb3 server
            William Woodman Master

            felix - thanks but i think have -

            if i put the @Remote (RemoteInterface.class) on the bean then i can find it by JNDI lookup.

            if i comment that out and rely on the @Remote on the interface class itself then i dont see to see it.

            either way i cant seem to get Dep Inj to work - not even locally in the embeddable container.

            I have created a local bean in the emmbedded appliction client like this

            import javax.ejb.EJB;
            import javax.ejb.Local;
            import javax.ejb.Stateless;
            
            import app.client.HelloUser;
            import app.client.HelloUserRemote;
            
            @Stateless
            public class TestBean implements Test
            {
            
             @EJB (name="HelloUser")
             public HelloUser tstHandler;
            
             public void message (String msg)
             {
            
             String retmsg = tstHandler.sayHello(msg);
             }
            
            }
            


            with an interface like this

            import javax.ejb.Local;
            
            
            @Local
            public interface Test
            {
             public void message (String msg);
            }
            


            and then include the following in my main class

            public class ClientApp
            {
             @EJB (name="HelloUserRemote")
             public HelloUserRemote tstHandler;
            
             @EJB
             public Test test;
            
             public ClientApp () {}
            
             public static void main(String[] args) throws Exception
             {
            
            [all startup stuff]...
            
             //try dependency injection!
             new ClientApp().init ();
            
            
            
            
             //Shut down EJB container
             EJB3StandaloneBootstrap.shutdown();
            
             }
            
             public void init()
             {
             //trigger the DI for test
             test.message("try again");
             }
            


            TestBean is local and exposes the message method - this then calls my remote bean.

            in this example when i run it i get an null pointer ref like this


            Exception in thread "main" java.lang.NullPointerException
            at ClientApp.init(ClientApp.java:74)
            at ClientApp.main(ClientApp.java:61)


            this implies that the container isnt creating the required TestBean and injecting it. never mind my external bean DI - i cant even get the local bean to work

            i'm still being stupid somewhere i think

            Wiggy

            • 3. Re: can any one help me - having a bad day with ejb3 server
              fhh Expert

              You have to add jndi.proeprties to set the proper InitialContext() to get dependency injection working.

              Regards

              Felix

              • 4. Re: can any one help me - having a bad day with ejb3 server
                William Woodman Master

                could you be more specific please, I am not sure which properties and one which side -

                do I have to do soemthing in the annotation on the 4.2 server side of my bean, or is it something i have to do on the embedded container side.

                one thing though i've seen examples where they use a name atribute for the @Stateless(name=<...>) declaration on the bean - what relation does that have to the @Local or @Remote declariations on the business interfaces.

                its just not clear what gets registered to JNDI by any of these (presumably all three i guess) as a call on a proxy with the business interface, has to get to the right bean implementation.

                Why doesnt my simple DI example work in the embedded server. I declare a bean, declare its interface as local and then try use it from the main routine. I thought the injection would at least work locally in one application?

                regards wiggy



                • 5. Re: can any one help me - having a bad day with ejb3 server
                  Carlo de Wolf Master

                   

                  "wiggy" wrote:
                  <edited>
                  in my EJB project i declare a bean like this
                  package app;
                  
                  import javax.ejb.Remote;
                  import javax.ejb.Stateless;
                  
                  import app.client.HelloUser;
                  
                  // (see later comments on client lookup) @Remote (HelloUser.class)
                  @Stateless
                  public class HelloUserBean implements HelloUser
                  {
                   HelloUserBean()
                   {};
                  
                   public String sayHello (String text)
                   {
                   String msg = "hello " + text + " /n";
                   System.out.println(msg);
                  
                   return msg;
                   }
                  }


                  The bean does not implement a remote interface.

                  There is no EJB 3 application client deployer in AS 4.2, so injection won't work in main classes.

                  • 6. Re: can any one help me - having a bad day with ejb3 server
                    William Woodman Master

                    wolfgang,

                    I changed my 4.2 server ejb to

                    
                    @Stateless
                    public class HelloUserBean implements HelloUserRemote
                    {
                    

                    explicitly as the interface that has the @Remote annotation and deploy to the 4.2 server.

                    if i then do the basic jndi lookup from the embedded server then i get a valid reference and the test call works.

                    however if i try to use DI in the embedded server to get a reference to the ejb it doesnt work and i get



                    59,433 INFO [MCKernelAbstraction] installing bean: jboss.j2ee:jar=bin,name=TestBean,service=EJB3 with dependencies:
                    17:22:59,603 INFO [EJBContainer] STARTED EJB: TestBean ejbName: TestBean
                    17:22:59,623 INFO [MCKernelAbstraction] installing bean: jboss.j2ee:jar=classes,name=HelloUserBean,service=EJB3 with dependencies:
                    17:22:59,633 INFO [EJBContainer] STARTED EJB: app.HelloUserBean ejbName: HelloUserBean
                    Exception in thread "main" java.lang.NullPointerException
                    at ClientApp.init(ClientApp.java:75)
                    at ClientApp.main(ClientApp.java:61)


                    from test code now looking like

                    /**
                     *
                     */
                     import java.util.Hashtable;
                    
                    import javax.ejb.EJB;
                    import javax.naming.InitialContext;
                    
                    
                    import org.apache.log4j.Level;
                    import org.apache.log4j.Logger;
                    import org.jboss.ejb3.embedded.EJB3StandaloneBootstrap;
                    
                    import app.client.HelloUser;
                    import app.client.HelloUserRemote;
                    
                    /**
                     * @author Will
                     *
                     */
                    public class ClientApp
                    {
                     @EJB (name="HelloUserRemote")
                     public HelloUserRemote tstHandler;
                    
                     @EJB (name="Test")
                     public Test test;
                    
                     public ClientApp () {}
                    
                     public static void main(String[] args) throws Exception
                     {
                    
                     Logger log = Logger.getLogger(ClientApp.class);
                     log.setLevel(Level.DEBUG);
                     //log.debug("Welcome to Wills App");
                    
                     // Boot the JBoss Microcontainer with EJB3 settings, automatically
                     // loads ejb3-interceptors-aop.xml and embedded-jboss-beans.xml
                     EJB3StandaloneBootstrap.boot(null);
                    
                     // Deploy custom stateless beans (datasource, mostly)
                     //EJB3StandaloneBootstrap.deployXmlResource("META-INF/NeilsApp-beans.xml");
                    
                     // Deploy all EJBs found on classpath (fast, scans build directory)
                     // This is a relative location, matching the substring end of one
                     // of java.class.path locations. Print out the value of
                     // System.getProperty("java.class.path") to see all paths.
                     EJB3StandaloneBootstrap.scanClasspath();
                    
                     InitialContext ctx = getInitialContext();
                    
                    
                     // Look up the stateless TestHandler EJB
                     //HelloUserRemote tstHandlerLoc = (HelloUserRemote) ctx.lookup("HelloUserBean/remote");
                     // Call the stateless EJB
                     //String message = tstHandlerLoc.sayHello("hello Will");
                    
                     //try dependency injection!
                     //new TestBean().message("hi there");
                     new ClientApp().init ();
                    
                    
                    
                    
                     //Shut down EJB container
                     EJB3StandaloneBootstrap.shutdown();
                    
                     }
                    
                     public void init()
                     {
                     //trigger the DI for test
                     //test.message("try again");
                     tstHandler.sayHello("hello there via DI");
                     }
                     ...
                    
                    


                    my tstHandler is a DI injected reference in the top of the clientApp class.

                    This gets the null pointer ref - hence the embedded container DI isnt working - but my jndi hard work version does - why cant the DI pick up the remote reference in the embedded app version ? (I new i think that 4.2AS didnt have the application client loader - hence the use of the embedded container to run my client class.

                    Wiggy



                    • 7. Re: can any one help me - having a bad day with ejb3 server
                      William Woodman Master

                      in fact its worse than that i cant DI to work in the embedded server at all - never mind between it and the 4.2 AS.

                      i created a very simple test local EJB all in the embedded server project like this .

                      // test ejb business interface defintion
                      import javax.ejb.Local;
                      
                      
                      @Local
                      public interface Test
                      {
                       public void message (String msg);
                      }
                      
                      


                      with a bean implementation like this

                      import javax.ejb.Stateless;
                      
                      
                      @Stateless
                      public class TestBean implements Test
                      {
                      
                       public void message (String msg)
                       {
                       System.out.println ("test bean\n");
                       }
                      
                      }
                      


                      I then try and get the DI bit to trigger from the main client section with the main entry point
                      calling client : - all in the same project
                      ...
                      public class ClientApp
                      {
                       @EJB (name="Test")
                       public Test test;
                      
                       public ClientApp () {}
                      
                       public static void main(String[] args) throws Exception
                       {
                      ... up to
                      
                       //try dependency injection!
                      
                       new ClientApp().init ();
                      
                      
                      
                      
                       //Shut down EJB container
                       EJB3StandaloneBootstrap.shutdown();
                      
                       }
                      
                       public void init()
                       {
                       //trigger the DI for test
                       test.message("local DI test in embedded container");
                       }
                      
                      ...
                      
                      


                      this gets the same null pointer ref


                      17:42:37,707 INFO [MCKernelAbstraction] installing bean: jboss.j2ee:jar=bin,name=TestBean,service=EJB3 with dependencies:
                      17:42:38,638 INFO [EJBContainer] STARTED EJB: TestBean ejbName: TestBean
                      17:42:38,779 INFO [MCKernelAbstraction] installing bean: jboss.j2ee:jar=classes,name=HelloUserBean,service=EJB3 with dependencies:
                      17:42:38,809 INFO [EJBContainer] STARTED EJB: app.HelloUserBean ejbName: HelloUserBean
                      Exception in thread "main" java.lang.NullPointerException
                      at ClientApp.init(ClientApp.java:75)
                      at ClientApp.main(ClientApp.java:62)


                      all this code is running in the embedded as server

                      what am i doing wrong here ?


                      Wiggy


                      • 8. Re: can any one help me - having a bad day with ejb3 server
                        Alex Grönholm Novice

                        @Local only works if the calling end is running within the same VM as the server. Therefore you need to use @Remote instead if you want your beans to work with application clients.
                        Why are you still trying to get dependency injection to work? Last I heard it doesn't work with JBoss at all -- and it's awful in Glassfish too. Just give it up and use JNDI lookups just like everyone else does.

                        • 9. Re: can any one help me - having a bad day with ejb3 server
                          William Woodman Master

                          alex -

                          i just read the nice books that tell me how fab this would all be (if it works) and i'm a little nieve that i hoped that this sort of basic stuff (like i couldnt implement it - but these folks are clever right) just works so that numpties like me can get on and right straight forward applications and not lose hours of effort trying to implement what the books/best practice say should just work.

                          Am i wrong to wih this - how many other poor aspiring geeks are squandering hours in effort trying to disambiguate concept from reality on the ground.

                          if theres a bug here/missing whole - shouldnt the smart folks be filling it so idiots liek me can get on with building houses and not figuring out why the plumbing deoesnt work

                          How come nothing says what does and doesnt work and how to get started without falling into the abyss everytime - this is so frustrating

                          Wiggy