9 Replies Latest reply on Nov 7, 2005 3:17 AM by heinrich

    Remote client : which library ?

    mustaghattack

      This is a transfert from the "Design EJB 3" forum ...

      "mustaghattack" wrote:
      Hi,

      I have a problem with creating a remote client :

      I put in my build path the following library :
      - jbossall-client.jar
      - myejb.jar (which is my ejb interface)

      When I launch my client (JBoss 4.0.2 with EJB 3.0 RC1 is running and my ejb are well deployed) I get this :

      javax.naming.CommunicationException [Root exception is java.lang.ClassNotFoundException: org.jboss.ejb3.JBossProxy (no security manager: RMI class loader disabled)]
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:713)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:572)
      at javax.naming.InitialContext.lookup(InitialContext.java:351)
      at Client.main(Client.java:17)


      My ejb are pretty simple :

      package org.wiskee.bd;

      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.GeneratorType;
      import javax.persistence.Id;

      @Entity
      public class Massif {
      private int massifId;
      private String nom;

      @Id(generate = GeneratorType.AUTO)
      @Column(name = "MASSIF_ID")
      public int getMassifId() {
      return massifId;
      }
      public void setMassifId(int id) {
      this.massifId = id;
      }

      public String getNom() {
      return nom;
      }
      public void setNom(String nom) {
      this.nom = nom;
      }

      }


      And the stateless session bean which manage this entity bean is :


      package org.wiskee.bd;

      import java.util.ArrayList;
      import java.util.List;

      import javax.ejb.Stateless;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      import javax.persistence.Query;

      public @Stateless class MassifsBean implements Massifs {
      @PersistenceContext
      private EntityManager manager;

      public List<Massif> getAllMassif() {
      ArrayList< Massif > massifs = new ArrayList< Massif>();

      Query q = manager.createQuery( "from Massif");

      for( Object o : q.getResultList()) {
      massifs.add( (Massif)o);
      }

      return massifs;
      }

      public Massif addMassif(String nom) {
      Massif massif = new Massif();
      massif.setNom( nom );
      manager.persist( massif );
      return massif;
      }
      }


      My client look like this :


      import javax.naming.Context;
      import javax.naming.InitialContext;
      import javax.naming.NamingException;

      import org.wiskee.bd.Massifs;
      import org.wiskee.bd.Massif;

      public class Client {

      /**
      * @param args
      */
      public static void main(String[] args) {
      try {
      System.out.println( "CLIENT" );
      Context context = new InitialContext();
      Massifs massifs = (Massifs) context.lookup(Massifs.class.getName());
      massifs.addMassif( "Pyrenees" );
      for( Massif m : massifs.getAllMassif() ) {
      System.out.println( m.getMassifId() + " : " + m.getNom() );
      }
      } catch (NamingException e) {
      e.printStackTrace();
      }
      }
      }


      I would like to know which library I have to put on my client build path ?
      Is there something wrong with my EJB or my client ?

      Thank you


        • 1. Re: Remote client : which library ?
          mustaghattack

          triathlon98 told me to add these files :

          jnp-server.jar (from your configuration lib directory)
          all jars from ejb3.deployer (in deploy)
          all jars from aop (in deploy)

          But in ejb3.deployer I found 22 jar (more than 4 MB) ...
          Is there a lighter solution ?

          • 2. Re: Remote client : which library ?
            gamac

            I noticed this too, (adding all libraries to my client adds up to 4MB). Here's one idea that might help (or not :)...

            What I'm planning to do is declare an interface (with all the getters/setters) to each of my entity beans, make my entity beans implement these interfaces and then put all these entities interfaces in a jar file that I deploy with my client and keep all the actual entity bean classes in the server.

            The plan is that my interfaces won't have any dependencies on javax.pesistence or any other EJB3 packages to I don't need to care about having those in the client side (i.e. I'll probably need less EJB3/JBoss jars on the client).

            To handle the entities on the client side I'll change my session beans methods return types to use the interfaces instead of the actual classes. The only libraries I'll need on the client side will be the ones need by session beans, but not any needed exclusively by entity beans.

            For instance, I'll have a Customer interface like this

            package client;
            
            interface Customer {
             public String getName();
             public void setName(String name);
            }
            


            and a CustomerBean class that implements the interface and is defined as the entity bean:

            package server;
            
            import javax.persistence.*;
            import client.Customer;
            
            @Entity
            @Table(name=?CUSTOMER?)
            class CustomerBean implements Customer {
             ...
             @Id
             public String getName() {..}
            
             public void setName(String name) {...}
             ...
            }
            


            Then I?ll have the session bean methods return objects of type Customer and not CustomerBean, for instance to get a customer by name, I?ll have something like:

            ?
            Customer getCustomerByName(String name) {
             CustomerBean cust = (CustomerBean) em.find(CustomerBean.class, name);
             return cust;
            }
            ?
            


            Well this is my plan anyway, I still have to try it myself, but I hope it does reduce the dependencies on at least a couple of EJB3 jar?s. Plus, another thing I?m trying to avoid with this is having my annotations (like @Entity, @Table, etc.) visible trough reflection to the clients (i.e. I don?t necessarily want my clients to know all the details of my underlying data model, like table names, etc.).

            Hope this help you guys as well.

            Cheers!


            • 3. Re: Remote client : which library ?
              mustaghattack

              Thanks gamac, I try it ... maybe it could avoid some error !

              Bruno

              • 4. Re: Remote client : which library ?
                gamac

                mustaghattack,
                just a quick note (regarding your reply on my other thread), I'm using JBoss 4.0.3RC2 (checked out from CVS) not 4.0.2, so things may work somehow differently for you.

                I recommend you upgrade to 4.0.3x if you can.

                Now, I remember having some exceptions similar to the one you're experiencing, and I remember that I was able to see the actual exception only when I set up the classpath correctly! I can't remember the exact libs I used, but try everything in the client, ejb3. deployer and hibernate.deployer dirs.

                I also remember that I had to download a library called ehcache that is used by hibernate/jboss-ejb3 but it's not bundled with JBoss (?!), so I had to download it and copy it to the JBoss server lib directory myself! The ehcache-1.1.jar file is inside the downloadable ehcache-1.1.tgz file (from http://ehcache.sourceforge.net/), in my case the Exception class that was being thrown was actually defined in this ehcache-1.1.jar file.

                Hope this helps!


                • 5. Re: Remote client : which library ?
                  mustaghattack

                  gamac,

                  Thanks for your quick reply.

                  I tried with JBoss 4.0.3 RC2 but I get the same error :


                  CLIENT
                  Ajout du massif pyrenees

                  java.lang.reflect.UndeclaredThrowableException
                  at $Proxy0.addMassif(Unknown Source)
                  at Client.main(Client.java:20)

                  Caused by: java.rmi.ConnectException: Failed to communicate. Problem during marshalling/unmarshalling; nested exception is:
                  java.io.EOFException
                  at org.jboss.remoting.transport.socket.SocketClientInvoker.transport(SocketClientInvoker.java:264)
                  at org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInvoker.java:112)
                  at org.jboss.remoting.Client.invoke(Client.java:226)
                  at org.jboss.remoting.Client.invoke(Client.java:189)
                  at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:41)
                  at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
                  at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:46)
                  at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
                  at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:40)
                  at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
                  at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:41)
                  at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:88)
                  at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:88)
                  ... 2 more

                  Caused by: java.io.EOFException
                  at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2502)
                  at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1267)
                  at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339)
                  at org.jboss.remoting.marshal.serializable.SerializableUnMarshaller.read(SerializableUnMarshaller.java:73)
                  at org.jboss.remoting.transport.socket.SocketClientInvoker.transport(SocketClientInvoker.java:242)
                  ... 14 more


                  I didn't change my client code :

                  import javax.naming.Context;
                  import javax.naming.InitialContext;
                  import javax.naming.NamingException;

                  import org.wiskee.bd.Massifs;
                  import org.wiskee.bd.Massif;

                  public class Client {

                  public static void main(String[] args) {
                  try {
                  System.out.println( "CLIENT" );
                  Context context = new InitialContext();
                  Massifs massifs = (Massifs) context.lookup(Massifs.class.getName());

                  System.out.println( "Ajout du massif pyrenees" );
                  massifs.addMassif( "Pyrenees" );

                  System.out.println( "Liste des massifs : ");
                  for( Massif m : massifs.getAllMassif() ) {
                  System.out.println( m.getMassifId() + " : " + m.getNom() );
                  }
                  } catch (NamingException e) {
                  e.printStackTrace();
                  } catch(Exception e) {
                  e.printStackTrace();
                  }
                  }
                  }


                  • 6. Re: Remote client : which library ?
                    mustaghattack

                    I understood the problem !
                    In fact my session bean (Massifs) return an entity bean reference (Massif) when I call the addMassif method. Since my client is outside, I need to serialize this entity (I thought, like the session bean, that the entity bean could be remotly accessed). I added an update method to my session bean which call the merge method from the manager.

                    Finally the libraries (needed by the remote client) are :
                    - jbossall-client.jar
                    - jboss-ejb3.jar
                    - jboss-aop-jdk50.jar
                    - jboss-aspect-library-jdk50.jar
                    - jboss-remoting.jar
                    - javax.servlet.jar

                    • 7. Re: Remote client : which library ?

                      The number of libraries for a remote client looks like a small overhead, huh?

                      • 8. Re: Remote client : which library ?
                        ajwhitney

                         

                        "mustaghattack" wrote:
                        This is a transfert from the "Design EJB 3" forum ...

                        "mustaghattack" wrote:
                        Hi,

                        I have a problem with creating a remote client :

                        I put in my build path the following library :
                        - jbossall-client.jar
                        - myejb.jar (which is my ejb interface)

                        When I launch my client (JBoss 4.0.2 with EJB 3.0 RC1 is running and my ejb are well deployed) I get this :

                        javax.naming.CommunicationException [Root exception is java.lang.ClassNotFoundException: org.jboss.ejb3.JBossProxy (no security manager: RMI class loader disabled)]
                        at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:713)
                        at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:572)
                        at javax.naming.InitialContext.lookup(InitialContext.java:351)
                        at Client.main(Client.java:17)


                        My ejb are pretty simple :

                        package org.wiskee.bd;

                        import javax.persistence.Column;
                        import javax.persistence.Entity;
                        import javax.persistence.GeneratorType;
                        import javax.persistence.Id;

                        @Entity
                        public class Massif {
                        private int massifId;
                        private String nom;

                        @Id(generate = GeneratorType.AUTO)
                        @Column(name = "MASSIF_ID")
                        public int getMassifId() {
                        return massifId;
                        }
                        public void setMassifId(int id) {
                        this.massifId = id;
                        }

                        public String getNom() {
                        return nom;
                        }
                        public void setNom(String nom) {
                        this.nom = nom;
                        }

                        }


                        And the stateless session bean which manage this entity bean is :


                        package org.wiskee.bd;

                        import java.util.ArrayList;
                        import java.util.List;

                        import javax.ejb.Stateless;
                        import javax.persistence.EntityManager;
                        import javax.persistence.PersistenceContext;
                        import javax.persistence.Query;

                        public @Stateless class MassifsBean implements Massifs {
                        @PersistenceContext
                        private EntityManager manager;

                        public List<Massif> getAllMassif() {
                        ArrayList< Massif > massifs = new ArrayList< Massif>();

                        Query q = manager.createQuery( "from Massif");

                        for( Object o : q.getResultList()) {
                        massifs.add( (Massif)o);
                        }

                        return massifs;
                        }

                        public Massif addMassif(String nom) {
                        Massif massif = new Massif();
                        massif.setNom( nom );
                        manager.persist( massif );
                        return massif;
                        }
                        }


                        My client look like this :


                        import javax.naming.Context;
                        import javax.naming.InitialContext;
                        import javax.naming.NamingException;

                        import org.wiskee.bd.Massifs;
                        import org.wiskee.bd.Massif;

                        public class Client {

                        /**
                        * @param args
                        */
                        public static void main(String[] args) {
                        try {
                        System.out.println( "CLIENT" );
                        Context context = new InitialContext();
                        Massifs massifs = (Massifs) context.lookup(Massifs.class.getName());
                        massifs.addMassif( "Pyrenees" );
                        for( Massif m : massifs.getAllMassif() ) {
                        System.out.println( m.getMassifId() + " : " + m.getNom() );
                        }
                        } catch (NamingException e) {
                        e.printStackTrace();
                        }
                        }
                        }


                        I would like to know which library I have to put on my client build path ?
                        Is there something wrong with my EJB or my client ?

                        Thank you


                        • 9. Re: Remote client : which library ?
                          heinrich

                          Hi,
                          first some words to your entity.
                          It looks nearly perfect except one thing.
                          The method

                          public String getNom() {
                          return nom;
                          }

                          needs the @Column annotaion which maps the field to the database.
                          This should be the reason for your unmarshaling exception
                          @Column(name="MASSIV_NOM")
                          public String getNom() {
                          return nom;
                          }



                          And, if you want to transfer some entity objects to a remote client, your entity must implement the "Serializable" interface.
                          I think this should fix your problems.


                          About the postings concerning the dependencies of the javax.persistence.*.
                          All Entities, SessionBeans are just POJOs. If you are using them on a remote client there is no dependency from javax.persistence.