1 2 Previous Next 20 Replies Latest reply on Jul 23, 2003 6:09 PM by vashistvishal

    EJB local refs and links

    mkerry

      I have two jar files deployed in the same server (JBoss 3.0.6, RedHat 7.3, jdk1.4). One has some CMP entity beans that I reference locally from other beans within that jar. In the DD, the referencing bean elements contain ejb-local-ref tags pointing to the referenced entities, along with ejb-link tags. This works fine.

      However, I also need to reference those same beans from the other jarfile. My questions are:

      1. Can I reference these beans locally from the other jar file, as well?
      2. Do I need to have <ejb-local-ref> tags in the referencing DD?
      3. Do these tags need to have the ejb-link element as well?

      What I am seeing is, I can sometimes reference the entities without any ejb-local-ref tags at all, however sooner or later I get lookup errors (perhaps this is unrelated?). When I add the ejb-local-ref tags, if I do not have the ejb-link tags, JBoss complains that I need them. When I add them, it complains that the beans are not local (or co-located, or something like that). I have tried packaging both jars into a single ear file, with no success.

      What is the correct way for me to reference these other beans? Do I just need to combine the jars into one?

      Thanks!

        • 1. Re: EJB local refs and links

          My understanding is you will need this tag to refer to other jar in same JVM.

          @ejb.ejb-external-ref (0..*)

          Please have a look at the the following lonk on Xdoclet as this will generate DD for you.
          http://xdoclet.sourceforge.net/tags/ejb-tags.html#@ejb.ejb-external-ref%20(0..*)
          Also on Xdoclet you might want to look at @jboss tags as well.
          But this should solve yr problem of referencing in two jars.

          Cheers.........
          Vishal

          • 2. Re: EJB local refs and links
            jonlee

            If you are not using XDoclet, or just need to understand the referencing, try this as an example where we have a stateless session bean trying to access another EJB for logging:

            <display-name>Cards</display-name>
            Cards
            <ejb-name>Cards</ejb-name>
            com.amity.cards.CardsHome
            com.amity.cards.Cards
            <local-home>com.amity.cards.CardsLocalHome</local-home>
            com.amity.cards.CardsLocal
            <ejb-class>com.amity.cards.CardsBean</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Bean</transaction-type>
            <ejb-local-ref>
            <ejb-ref-name>LocalEventLogger</ejb-ref-name>
            <ejb-ref-type>Session</ejb-ref-type>
            <local-home>com.amity.eventlogger.EventLoggerLocalHome</local-home>
            com.amity.eventlogger.EventLoggerLocal
            <ejb-link>EventLogger</ejb-link>
            </ejb-local-ref>


            Your corresponding jboss.xml would contain the resource definition and the res-name map back to the ejb-link.

            <?xml version="1.0"?>
            <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS//EN" "http://www.jboss.org/j2ee/dtd/jboss.dtd">

            <resource-managers>
            <resource-manager>
            <res-name>EventLogger</res-name>
            <res-jndi-name>EventLogger</res-jndi-name>
            </resource-manager>
            </resource-managers>
            <enterprise-beans>

            <ejb-name>Cards</ejb-name>
            <jndi-name>Cards</jndi-name>
            <local-jndi-name>CardsLocal</local-jndi-name>
            <configuration-name>Standard Stateless SessionBean</configuration-name>
            <ejb-local-ref>
            <ejb-ref-name>EventLogger</ejb-ref-name>
            <local-jndi-name>EventLoggerLocal</local-jndi-name>
            </ejb-local-ref>

            false
            </enterprise-beans>

            You can use the local-jndi-name as your lookup point. You should be able to follow the XDoclet generation from this I hope.

            • 3. Re: EJB local refs and links
              mkerry

              Thanks for the replies.

              Unfortunately, I am no longer using XDoclet (I was originally, but changed to JBuilder to conform to the dev environment...).

              Here are some followup questions:

              For Vishal's response (using the @ejb-external-ref XDoclet tag), the XDoclet docs explicitly say that this tag will work for referencing beans across jar files. Will it work if the bean that is being referenced only has local interfaces? Will it generate a DD similar to jonlee's?

              For jonlee's response, were your two beans in different jar files (Cards in one, LocalEventLogger in the other)?

              If so, then I can conclude that I need to have these tags in order to make the reference work; however, it works (somewhat) when I don't have them. Am I "getting lucky" somehow? Why would it sometimes work and sometimes not? (Mostly, I just want to understand what is happening here...)

              Finally, does anyone know JBuilder9 well enough to tell me how to generate the <ejb-local-ref> with the <ejb-link> tags when the beans are in different jars? (it works fine to check the isLink box when they are in the same jar, but I don't see a way to point it to look for beans in other jars that will be deployed in the same App Server). I have asked the question on a JBuilder newsgroup but have yet to get a response.

              Thanks again for the help!

              • 4. Re: EJB local refs and links

                Yes you can get thta both for local and remote interfaces, as it specifies in tag options.

                @ejb.ejb-external-ref
                view-type="local"
                link="XXXXXXXXXXXX"
                type="XXXX/Session/Entity/"
                ref-name="XXXXXXXXXXXXXX"
                home="XXXXXX"
                local="XXXXXXXXXX"

                thes are the options specified under this tag at Xdoclet doc's.
                This will work and this is a class level tag.
                I hope this clarifies it.


                • 5. Re: EJB local refs and links
                  jonlee

                  Yes they are separately packaged jars. You are probably getting lucky with the calls. However, being explicit with the definition allows the container to easily determine the reference to the local interface - particularly if you have a remote interface available as well on the EJB.

                  We build this way as single EJBs during development as it gives us a bit more flexibility to chop and change individual EJBs. We repackage for production when the sub-systems are stable.

                  Hope that answers my part.

                  • 6. Re: EJB local refs and links
                    mkerry

                    OK, thanks again. But I fear I am still struggling...

                    I wrote a little toy to try this out, using XDoclet so that we can speak the same language; and it didn't work.

                    I have three beans, all stateless session beans. One (CallerBean) has methods that call the other two beans (Bean1 and Bean2). Both Bean1 and Bean2 are written with only local interfaces. Bean1 is packaged in the same jarfile as CallerBean (jar1), whereas Bean2 is packaged in a different jar by itself (jar2). I should also note that Bean2 is in a different java package from Bean1 and CallerBean. Does that matter? (Bean1 and CallerBean are in testLocal.ejb, whereas Bean2 is in testLocal2.ejb).

                    When I try to deploy jar1 (containing CallerBean's attempted local-refs to Bean1 and Bean2) I get a deployment error from JBoss:

                    org.jboss.deployment.DeploymentException: Bean Bean2 not found within this application.

                    When I comment out all references to Bean2 in CallerBean (leaving in the local refs and calls to Bean1), it deploys and runs fine.

                    The XDoclet I used in the CallerBean is as follows:

                    /**
                    * @ejb.bean
                    * name="CallerBean"
                    * type="Stateless"
                    * jndi-name="ejb/CallerBean"
                    * display-name="CallerBean"
                    *
                    * @ejb.interface
                    * remote-class="testLocal.interfaces.CallerBean"
                    *
                    * @ejb.home
                    * remote-class="testLocal.interfaces.CallerBeanHome"
                    *
                    * @ejb.ejb-external-ref
                    * view-type="local"
                    * link="Bean1"
                    * ref-name="ejb/Bean1Local"
                    * type="Stateless"
                    * home="testLocal.Bean1LocalHome"
                    * business="testLocal.Bean1Local"
                    *
                    * @ejb.ejb-external-ref
                    * view-type="local"
                    * link="Bean2"
                    * ref-name="ejb/Bean2Local"
                    * type="Stateless"
                    * home="testLocal2.Bean2LocalHome"
                    * business="testLocal2.Bean2Local"
                    */

                    What am I missing?

                    • 7. Re: EJB local refs and links

                      First of all what i understand is this

                      Yr CallerBean and Bean1 are in same jar file say jar-1.
                      And Bena2 is in different jar file say jar-2.

                      Now @ejb. @ejb.ejb-external-ref is used to look for beans in different jars.
                      That means in order to invoke methods on Bean2 (which is in jar-2) by CallerBean you use this tag.

                      Now in case of CallerBean invoking methods on Bean 1 which are in same jar that is jar-1 you dont use this tag.
                      You have to use this tag.

                      @ejb.ejb-ref ejb-name="Bean1"
                      view-type="local"
                      ref-name="Bean1Local"

                      Assuming yr lookup string bean is
                      "java:comp/env/ejb/Bean1Local"

                      Now in addition to that you need tags for jboss.

                      @jboss.ejb-ref-jndi ref-name="Bean1Local"
                      jndi-name="Bean1Local"

                      And in case of bean 2.
                      @jboss.ejb-ref-jndi
                      ref-name="Bean2Local"
                      jndi-name="Bean2Local"

                      Now, This tag for bean2, (I am not sure about that, but my understanding is you need that as in case of Bean1), but do check Xdoclet doc for this tag.

                      Now, a tricky bit, which I am glad somebody raised it, when you use
                      @jboss.ejb-ref-jndi, it raises
                      wrong descriptors in jboss.xml file in case of bean with local interface not with remote one.



                      <ejb-name>CallrBean</ejb-name>
                      <jndi-name>CallerBean</jndi-name>
                      <local-jndi-name>CallerBeanLocal</local-jndi-name>
                      <ejb-ref> --------------------------
                      <ejb-ref-name>ejb/Bean1Local</ejb-ref-name>
                      <jndi-name>Bean1Local</jndi-name>
                      </ejb-ref>-------------------------------


                      this is where it gets wrong.
                      it should be

                      <ejb-local-ref> -------
                      <ejb-ref-name>ejb/Bean1Local</ejb-ref-name>
                      <jndi-name>Bean1Local</jndi-name>
                      </ejb-local-ref> -------------------

                      So you have to change it manually.

                      I hope all this will help you, if you still cant' do that just post yr whole project I wil have a look at it.

                      • 8. Re: EJB local refs and links
                        mkerry

                        OK, I have attached my code, since I am still unable to make your suggestion work.

                        A couple of things:

                        1) Thanks for pointing out the @ejb-ref vs @ejb-external-ref problem; although, I noticed that they in fact seem to generate the same deployment descriptor in this case.

                        2) Also, thanks for the @jboss tags point; I had missed that. Oddly, it was working even without those tags in the Bean1 case, and it is still failing for me in the Bean2 case with them.

                        3) I never would have noticed that XDoclet was not creating the @jboss tags correctly...thanks.

                        I have cut-n-pasted (Attach Files didn't work for me) 4 java files (CallerBean.java, Bean1.java, Bean2.java and Driver.java) and the resulting deployment descriptors for jar1.jar.

                        As noted before, CallerBean and Bean1 are packaged into one jar file (jar1.jar), whereas Bean2 is packaged separately (jar2.jar). Driver is the main program that excercises the beans.

                        The problem is, jar1.jar fails to deploy. If I comment out all references to Bean2 in CallerBean, it deploys and runs fine. I have tried this on RedHat 7.3 with jboss 3.0.6 (tomcat bundle) as well as on Win2000 with jboss 3.0.7 (also tomcat bundle), and jdk1.4 in both cases.

                        Thanks for taking the time to have a look!

                        CallerBean.java
                        --------------------
                        package testLocal.ejb;

                        import javax.ejb.*;
                        import javax.naming.*;
                        import java.rmi.*;
                        import javax.rmi.*;

                        import testLocal.interfaces.*;

                        /**
                        * CallerBean.java
                        *
                        * @ejb.bean
                        * name="CallerBean"
                        * type="Stateless"
                        * jndi-name="ejb/CallerBean"
                        * display-name="CallerBean"
                        *
                        * @ejb.interface
                        * remote-class="testLocal.interfaces.CallerBean"
                        *
                        * @ejb.home
                        * remote-class="testLocal.interfaces.CallerBeanHome"
                        *
                        * @ejb.ejb-ref
                        * view-type="local"
                        * ejb-name="Bean1"
                        * ref-name="Bean1Local"
                        *
                        * @jboss.ejb-ref-jndi
                        * ref-name="Bean1Local"
                        * jndi-name="Bean1Local"
                        *
                        * @ejb.ejb-external-ref
                        * view-type="local"
                        * link="Bean2"
                        * ref-name="Bean2Local"
                        * type="Session"
                        * home="testLocal2.interfaces.Bean2LocalHome"
                        * local="testLocal2.interfaces.Bean2Local"
                        *
                        * @jboss.ejb-ref-jndi
                        * ref-name="Bean2Local"
                        * jndi-name="Bean2Local"
                        *
                        * @version 1.0
                        */

                        public class CallerBean implements SessionBean {

                        private SessionContext ctx;
                        private Bean1LocalHome bean1LocalHome;

                        public void setSessionContext(SessionContext ctx) {
                        this.ctx = ctx;
                        }

                        public void ejbActivate() throws RemoteException {
                        }
                        public void ejbPassivate() throws RemoteException {
                        }
                        public void ejbRemove() throws RemoteException {
                        }

                        /**
                        * @ejb.create-method
                        */
                        public void ejbCreate() {
                        System.out.println("CallerBean.ejbCreat()");

                        try {
                        InitialContext initCtx = new InitialContext();
                        Object o = initCtx.lookup("java:comp/env/ejb/Bean1Local");
                        this.bean1LocalHome =
                        (Bean1LocalHome)PortableRemoteObject.narrow(o, Bean1LocalHome.class);
                        } catch (Exception ex) {
                        ex.printStackTrace();
                        }
                        }

                        /**
                        * @ejb.interface-method view-type="remote"
                        */
                        public void callBean1() {
                        System.out.println("CallerBean.callBean1");

                        try {
                        Bean1Local bean1 = this.bean1LocalHome.create();
                        bean1.showMessage("Local call to Bean1 from CallerBean...");
                        bean1.remove();
                        } catch (Exception ex) {
                        ex.printStackTrace();
                        }
                        }
                        }

                        Bean1.java
                        --------------
                        package testLocal.ejb;

                        import javax.ejb.*;
                        import javax.naming.*;
                        import java.rmi.*;

                        /**
                        * Bean1.java
                        *
                        * @ejb.bean
                        * name="Bean1"
                        * type="Stateless"
                        * view-type="local"
                        * local-jndi-name="Bean1Local"
                        * display-name="Test Bean 1"
                        *
                        * @ejb.interface
                        * local-class="testLocal.interfaces.Bean1Local"
                        *
                        * @ejb.home
                        * local-class="testLocal.interfaces.Bean1LocalHome"
                        *
                        * @version 1.0
                        */

                        public class Bean1 implements SessionBean {

                        private SessionContext ctx;

                        public void setSessionContext(SessionContext ctx) {
                        this.ctx = ctx;
                        }

                        public void ejbActivate() throws RemoteException {
                        }
                        public void ejbPassivate() throws RemoteException {
                        }
                        public void ejbRemove() throws RemoteException {
                        }

                        /**
                        * @ejb.create-method
                        */
                        public void ejbCreate() {
                        System.out.println("Bean1.ejbCreat()");
                        }

                        /**
                        * @ejb.interface-method view-type="local"
                        */
                        public void showMessage(String msg) {
                        System.out.println("Bean1.showMessage: msg = " + msg);
                        }
                        }

                        Bean2.java
                        --------------
                        package testLocal2.ejb;

                        import javax.ejb.*;
                        import javax.naming.*;
                        import java.rmi.*;

                        /**
                        * Bean2.java
                        *
                        * @ejb.bean
                        * name="Bean2"
                        * type="Stateless"
                        * view-type="local"
                        * local-jndi-name="Bean2Local"
                        * display-name="Test Bean 1"
                        *
                        * @ejb.interface
                        * local-class="testLocal2.interfaces.Bean2Local"
                        *
                        * @ejb.home
                        * local-class="testLocal2.interfaces.Bean2LocalHome"
                        *
                        * @version 1.0
                        */

                        public class Bean2 implements SessionBean {

                        private SessionContext ctx;

                        public void setSessionContext(SessionContext ctx) {
                        this.ctx = ctx;
                        }

                        public void ejbActivate() throws RemoteException {
                        }
                        public void ejbPassivate() throws RemoteException {
                        }
                        public void ejbRemove() throws RemoteException {
                        }

                        /**
                        * @ejb.create-method
                        */
                        public void ejbCreate() {
                        System.out.println("Bean2.ejbCreat()");
                        }

                        /**
                        * @ejb.interface-method view-type="local"
                        */
                        public void showMessage(String msg) {
                        System.out.println("Bean2.showMessage: msg = " + msg);
                        }
                        }

                        Driver.java
                        --------------
                        package testLocal;

                        import javax.naming.*;
                        import javax.ejb.*;
                        import javax.rmi.*;

                        import testLocal.interfaces.*;

                        public class Driver {

                        public Driver() {
                        }

                        public static void main(String [] args) {
                        InitialContext ctx;

                        try {
                        ctx = new InitialContext();

                        CallerBeanHome callerHome = (CallerBeanHome)PortableRemoteObject.narrow(ctx.lookup("ejb/CallerBean"), CallerBeanHome.class);

                        CallerBean callerBean = callerHome.create();

                        System.out.println("Calling bean1 method...");
                        callerBean.callBean1();

                        callerBean.remove();
                        } catch (Exception ex) {
                        ex.printStackTrace();
                        }
                        }
                        }

                        ejb-jar.xml
                        ------------
                        <?xml version="1.0" encoding="UTF-8"?>
                        <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">

                        <ejb-jar >

                        <![CDATA[No Description.]]>
                        <display-name>Generated by XDoclet</display-name>

                        <enterprise-beans>

                        <!-- Session Beans -->

                        <![CDATA[Bean1.java]]>
                        <display-name>Test Bean 1</display-name>

                        <ejb-name>Bean1</ejb-name>

                        <local-home>testLocal.interfaces.Bean1LocalHome</local-home>
                        testLocal.interfaces.Bean1Local
                        <ejb-class>testLocal.ejb.Bean1</ejb-class>
                        <session-type>Stateless</session-type>
                        <transaction-type>Container</transaction-type>




                        <![CDATA[CallerBean.java]]>
                        <display-name>CallerBean</display-name>

                        <ejb-name>CallerBean</ejb-name>

                        testLocal.interfaces.CallerBeanHome
                        testLocal.interfaces.CallerBean
                        <local-home>testLocal.interfaces.CallerBeanLocalHome</local-home>
                        testLocal.interfaces.CallerBeanLocal
                        <ejb-class>testLocal.ejb.CallerBean</ejb-class>
                        <session-type>Stateless</session-type>
                        <transaction-type>Container</transaction-type>

                        <ejb-local-ref >
                        <ejb-ref-name>ejb/Bean2Local</ejb-ref-name>
                        <ejb-ref-type>Session</ejb-ref-type>
                        <local-home>testLocal2.interfaces.Bean2LocalHome</local-home>

                        <ejb-link>Bean2</ejb-link>
                        </ejb-local-ref>

                        <ejb-local-ref >
                        <ejb-ref-name>ejb/Bean1Local</ejb-ref-name>
                        <ejb-ref-type>Session</ejb-ref-type>
                        <local-home>testLocal.interfaces.Bean1LocalHome</local-home>
                        testLocal.interfaces.Bean1Local
                        <ejb-link>Bean1</ejb-link>
                        </ejb-local-ref>



                        <!--
                        To add session beans that you have deployment descriptor info for, add
                        a file to your XDoclet merge directory called session-beans.xml that contains
                        the markup for those beans.
                        -->

                        <!-- Entity Beans -->
                        <!--
                        To add entity beans that you have deployment descriptor info for, add
                        a file to your XDoclet merge directory called entity-beans.xml that contains
                        the markup for those beans.
                        -->

                        <!-- Message Driven Beans -->
                        <!--
                        To add message driven beans that you have deployment descriptor info for, add
                        a file to your XDoclet merge directory called message-driven-beans.xml that contains
                        the <message-driven></message-driven> markup for those beans.
                        -->

                        </enterprise-beans>

                        <!-- Relationships -->

                        <!-- Assembly Descriptor -->
                        <assembly-descriptor >
                        <!--
                        To add additional assembly descriptor info here, add a file to your
                        XDoclet merge directory called assembly-descriptor.xml that contains
                        the <assembly-descriptor></assembly-descriptor> markup.
                        -->

                        <!-- finder permissions -->

                        <!-- finder permissions -->

                        <!-- transactions -->

                        <!-- finder transactions -->
                        </assembly-descriptor>

                        <ejb-client-jar>blah.jar</ejb-client-jar>

                        </ejb-jar>

                        jboss.xml
                        ---------

                        <?xml version="1.0" encoding="UTF-8"?>
                        <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd">



                        <unauthenticated-principal>nobody</unauthenticated-principal>

                        <enterprise-beans>

                        <!--
                        To add beans that you have deployment descriptor info for, add
                        a file to your XDoclet merge directory called jboss-beans.xml that contains
                        the , and <message-driven></message-driven>
                        markup for those beans.
                        -->


                        <ejb-name>Bean1</ejb-name>
                        <local-jndi-name>Bean1Local</local-jndi-name>


                        <ejb-name>CallerBean</ejb-name>
                        <jndi-name>ejb/CallerBean</jndi-name>
                        <local-jndi-name>CallerBeanLocal</local-jndi-name>
                        <ejb-local-ref>
                        <ejb-ref-name>ejb/Bean1Local</ejb-ref-name>
                        <jndi-name>Bean1Local</jndi-name>
                        </ejb-local-ref>
                        <ejb-local-ref>
                        <ejb-ref-name>ejb/Bean2Local</ejb-ref-name>
                        <jndi-name>Bean2Local</jndi-name>
                        </ejb-local-ref>


                        </enterprise-beans>

                        <resource-managers>
                        </resource-managers>


                        • 9. Re: EJB local refs and links
                          mkerry

                          I just noticed that the version of CallerBean and Driver that I posted don't actually have any java code refering to Bean2; I have another method called callBean2(), analagous to callBean1(), that is used to excercise it (from Driver, just like for Bean1). And, I am doing the Home lookup for Bean2 in the same place as I do for Bean1 (in ejbCreate()).

                          I can post the real version if you want, but it still has the same deployment error. As long as that @ejb.ejb-external-ref XDoclet is present, the jar file won't deploy for me, whether or not the java code uses Bean2.

                          • 10. Re: EJB local refs and links
                            imdkidd

                            My understanding is that when you are referencing beans across different jars they must be packaged together in a EAR in order for it to work. Otherwise, you have to include copies of the stubs of the bean you are referencing.

                            • 11. Re: EJB local refs and links
                              mkerry

                              Yes, indeed, I just discovered that...you beat me to the answer by 30 minutes!

                              Thanks for replying, though!

                              My problem, then, is with JBuilder, I think, because it won't generate the same deployment descriptor that XDoclet does (it leaves out the <ejb-link> tag for the bean in the "other" jar file). The strange thing is, the JBuilder descriptor works fine for Weblogic. That is, you don't need the <ejb-link> element for the second bean.

                              I think I am going to open a new thread to ask about this.

                              • 12. Re: EJB local refs and links
                                mkerry

                                Just to be clear, even though I stated in the original question that I had tried packaging the two jars into a single ear, at that time I did not have the correct XDoclet that the others pointed out to me (ejb-external-ref, etc.) to make it all work. The solution was in the combination.

                                Thanks again for all of the help!

                                • 13. Re: EJB local refs and links
                                  pauster007

                                  can i take a look at the final composition of your ejb-jar.xml and jboss.xml?

                                  • 14. Re: EJB local refs and links
                                    mkerry

                                    I believe the xml files I posted above were in fact the final versions, just that the two jar files were packaged into a single ear file. I'll check though and re-post if I am wrong.

                                    1 2 Previous Next