11 Replies Latest reply on Oct 19, 2005 1:36 PM by yxw84

    JNDI Problem

    yxw84

      I've been stuck on this for a few days now and would really appreciate any feedback or assistance from the JBoss community.

      I have written a very simple EJB3 POJO entity bean which is part of a package mycompany.MyBean. It deploys fine on JBoss 4.0.2 with EJB3 support. However, in a servlet which I wrote to access the bean, the following lookup code throws a NamingException:

      // problem code
      Context ctx = new InitialContext();
      mybean = (MyBean) ctx.lookup(MyBean.class.getName());

      and the error I get is:
      javax.naming.NameNotFoundException: mycompany.MyBean not bound

      As for the bean code, it has about 20 variables, plus getter and setter methods. The only annotation is "@Entity".

      I've had some experience with EJB 2.1 but am very new to EJB 3.0, so I would appreciate any feedback. Specifically, how is the JNDI name determined from a simple POJO entity bean with minimal annotation? Is there any configuration file for JBoss that I may have missed?

      Thanks!

        • 1. Re: JNDI Problem
          elkner
          • 2. Re: JNDI Problem
            yxw84

            Thank you. Turns out that I do not need to use the entity bean home to do a lookup. However, I have another question. It seems that in order to use entity beans to write to the database, I have to go from Servlet -> Session Bean -> EntityManager -> Entity Bean. Is there a way I can skip creating a session bean for every entity bean I write?

            In EJB 2.1, you could do this by performing a lookup on the entity home. Is there a comparable way to do it in EJB3? The reason I ask is because I'm porting an application from 2.1 to 3.0, and most of the entity beans are standalone and it would be time consuming to code matching session beans for each ones.

            Once again, thank you for your time.

            • 3. Re: JNDI Problem
              skitching

              In the early days of J2EE people were encouraged to expose entity beans to client applications directly. It has now been realised that this is a *very bad* idea, both for performance and for long-term code maintenance.

              I suspect that the EJB3 spec now defaults to *not* exposing entity beans via jndi which is why you can't get to them via a lookup. Maybe there's an annotation to force it to be registered in jndi...[only guessing].

              If you wish to do direct database access from a servlet, then why are you bothering with using an EJB container at all? If you're writing a J2EE app, then only session beans should access entities.

              Anyway, if you are determined to perform database access from your servlet layer then you should be able to get access to the PersistenceManager via JNDI, then create an EntityManager from it, and perform database updates via that EntityManager instance. I think you want "EntityManagerFactories/{name}" but I could be wrong.

              If you go to the jboss jmx console and select the "service=JNDIView" link then click the invoke button for "list" you will see a dump of all the objects registered in JNDI.

              • 4. Re: JNDI Problem
                yxw84

                Thank you for the helpful advice. We're now seriously considering redesigning our legacy app to match the session facade design pattern. However, because we've run into more difficulties concerning the v2.1 to v3.0 EJB upgrade, I was hoping I could get a bit more feedback concerning a related issue.

                One of the key functionality in our application is the capability to switch datasource on the fly in a custom getConnection method. What this means is, if I call getConnection(db1), the entity bean will connect to a database named "db1". If I call getConnection(db2), the entity bean will connect to a database named "db2". This method is in every one of the entity beans and is called everytime the bean is instantiated.

                I can achieve a lesser functionality of having different entity beans access different databases by giving each entity bean its own persistence.xml. However, how can I configure a single entity bean to have access to multiple databases? Note that these databases all share the same schema, and are hence representable by the same entity bean, they just have different tuples.

                Thank you for your helpful comments and please keep them coming.

                • 5. Re: JNDI Problem
                  yxw84

                  Actually, I found the answer to this question.

                  http://www.jboss.org/index.html?module=bb&op=viewtopic&t=65869&postdays=0&postorder=asc&start=20

                  I'm guessing that the only way to implement the desired functionality is to deploy "x" copies of the same entity EJB if we want to have access to "x" databases?

                  • 6. Re: JNDI Problem
                    bill.burke

                    I don't think copies is the write word.

                    What you need is multiple persistence.xml files that use jar-file and/or class elements to define the persistence unit and look these guys up in JNDI.

                    • 7. Re: JNDI Problem
                      yxw84

                      I see what you mean. I was able to implement the desired behaviour by creating "dummy" ejb3 archives with only a persistence.xml inside them, with a <jar-file> entry pointing to the real ejb3 archive which contains the classes. The only downside to this approach was having to copy each real ejb3 file into the JBOSS/bin directory.

                      So the way I have it working is separate entity managers for different databases. I have yet another question though. Say I have two entity managers accessing two different databases, how will I enforce transactional behavior over a series of updates which accesses both EMs?

                      Will the following code achieve the desired functionality?

                      // entity managers are em1, em2
                      em1.getTransaction().begin();
                      em2.getTransaction().begin();

                      em1.persist(someObject);
                      em2.persist(anotherObject);

                      em2.getTransaction().commit();
                      em1.getTransaction.commit();

                      If I remember correctly from the spec, transactions cannot be nested. While the above code compiles and runs as expected, is it behaving as expected behind the scenes?

                      Once again thank you for your comments and feedback.

                      • 8. Re: JNDI Problem
                        bill.burke

                        use JTA transactions. Also, currently, EM transactions don't work inside app server in the current implementation.

                        • 9. Re: JNDI Problem
                          yxw84

                          Sorry, I have yet another question now that I'm trying to implement session facade.

                          The following code in a Servlet:
                          // some code to initialize myobject, which is a pojo entity
                          InitialContext ctx = new InitialContext();

                          SessionTest st = (SessionTest) ctx.lookup(SessionTest.class.getName());
                          st.createMyObject(myobject);

                          Throws the following exception at runtime:
                          java.lang.IllegalArgumentException: argument type mismatch

                          However, when I change the createMyObject function to pass a non-object such as an integer, it works fine. Since "myobject" is a POJO entity bean, am I missing something such as an annotation that allows me to pass it around just like any other java object?

                          Thank you again for your help.

                          • 10. Re: JNDI Problem
                            yxw84

                            Oh nevermind, I figured it out. Was missing a @Remote annotation in my session bean interface, and my entity bean also needs to implement the serializable interface.. I think.

                            • 11. Re: JNDI Problem
                              yxw84

                              Oh nevermind, I figured it out. I was missing a @Remote annotation in my session bean interface, and I think my entity bean needs to implement Serializable.