10 Replies Latest reply on Jul 24, 2008 9:54 PM by Brian Stansberry

    JRMPProxyFactory equivalent for POJO Services

    Brian Stansberry Master

      Does AS 5 have any POJO equivalent to the JRMPProxyFactory? I.e. a service you can create where you inject some POJO service, an InvokerLocator, a JNDI name and an interface name, and it creates a Remoting proxy to your service and binds it in JNDI?

      Had a quick look at @JndiBinding but it seems that just does a simple binding.

      Looks like the needed stuff is there in org.jboss.aspects.remoting.Remoting, but wondered if there is work being done on /plan for a service or aspect that packages it all together.

      This is needed for JBC, which can no longer expose a Cache proxy via JNDI since no mbean service implements the Cache interface.

        • 1. Re: JRMPProxyFactory equivalent for POJO Services
          Scott Stark Master

          No, its a remoting integration aspect that needs to be supplied. Its simple enough to create one as this example does. The based aspects for the client should be externalized though, and the jndi binding should be done via an aspect on this bean. I have created a jbas issue for the replacement.

          http://jira.jboss.com/jira/browse/JBAS-4456

          package org.jboss.profileservice.remoting;
          
          import java.util.ArrayList;
          
          import javax.naming.InitialContext;
          
          import org.jboss.aop.Dispatcher;
          import org.jboss.aop.advice.Interceptor;
          import org.jboss.aop.proxy.Proxy;
          import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
          import org.jboss.aspects.remoting.MergeMetaDataInterceptor;
          import org.jboss.aspects.remoting.Remoting;
          import org.jboss.aspects.security.SecurityClientInterceptor;
          import org.jboss.deployers.spi.management.ManagementView;
          import org.jboss.logging.Logger;
          import org.jboss.profileservice.spi.ProfileService;
          import org.jboss.remoting.InvokerLocator;
          import org.jboss.util.naming.Util;
          
          /**
           * An aop/remoting proxy factory bean that exposes the ProfileService
           * interfaces.
           *
           * @author Scott.Stark@jboss.org
           * @version $Revision:$
           */
          public class ProxyFactory
          {
           private static final Logger log = Logger.getLogger(ProxyFactory.class);
           private String dispatchName = "ProfileService";
           private String jndiName = "ProfileService";
           private InvokerLocator locator;
           private ProfileService ps;
           private ManagementView mgtView;
           private Proxy psProxy;
           private Proxy mgtViewProxy;
          
           public String getDispatchName()
           {
           return dispatchName;
           }
          
           public void setDispatchName(String dispatchName)
           {
           this.dispatchName = dispatchName;
           }
          
           public String getJndiName()
           {
           return jndiName;
           }
          
           public void setJndiName(String jndiName)
           {
           this.jndiName = jndiName;
           }
          
           public InvokerLocator getLocator()
           {
           return locator;
           }
          
           public void setLocator(InvokerLocator locator)
           {
           this.locator = locator;
           }
          
           public ProfileService getProfileService()
           {
           return ps;
           }
          
           public void setProfileService(ProfileService ps)
           {
           this.ps = ps;
           }
          
           public Proxy getProfileServiceProxy()
           {
           return psProxy;
           }
          
           public ManagementView getViewManager()
           {
           return mgtView;
           }
           public void setViewManager(ManagementView mgtView)
           {
           this.mgtView = mgtView;
           }
          
           public Proxy getManagementViewProxy()
           {
           return mgtViewProxy;
           }
          
           public void start()
           throws Exception
           {
           ClassLoader loader = Thread.currentThread().getContextClassLoader();
           Class[] ifaces = {ProfileService.class};
          
           // Create the ProfileService proxy
           Dispatcher.singleton.registerTarget(dispatchName, ps);
          
           ArrayList<Interceptor> interceptors = new ArrayList<Interceptor>();
           interceptors.add(SecurityClientInterceptor.singleton);
           interceptors.add(MergeMetaDataInterceptor.singleton);
           interceptors.add(InvokeRemoteInterceptor.singleton);
          
           psProxy = Remoting.createRemoteProxy(dispatchName, loader, ifaces, locator,
           interceptors, "ProfileService");
           InitialContext ctx = new InitialContext();
           Util.bind(ctx, jndiName, psProxy);
          
           // Create the ManagementView proxy
           Class[] mvIfaces = {ManagementView.class};
           String mvDispatchName = dispatchName+".ManagementView";
           Dispatcher.singleton.registerTarget(mvDispatchName, mgtView);
           mgtViewProxy = Remoting.createRemoteProxy(mvDispatchName, loader, mvIfaces, locator,
           interceptors, "ProfileService");
           log.debug("Bound ProfileService proxy");
           }
          
           public void stop()
           throws Exception
           {
           ClassLoader loader = Thread.currentThread().getContextClassLoader();
           Dispatcher.singleton.unregisterTarget(dispatchName);
           String mvDispatchName = dispatchName+".ManagementView";
           Dispatcher.singleton.unregisterTarget(mvDispatchName);
           InitialContext ctx = new InitialContext();
           Util.unbind(ctx, jndiName);
           log.debug("Unbound ProfileService proxy");
           }
          }
          



          • 3. Re: JRMPProxyFactory equivalent for POJO Services
            Ron Sigal Master

            I'm finally getting around to JBAS-4456. I've written a RemotingProxyFactory, based on Scott's ProxyFactory, and I have some questions.

            1. Provisionally, I've put RemotingProxyFactory in jboss-aspects/remoting, since it uses facilities from there. Is there some other more appropriate home for it?

            2. Scott's example hard codes MergeMetaDataInterceptor and InvokeRemoteInterceptor. Obviously InvokeRemoteInterceptor is necessary, and my unit test fails without MergeMetaDataInterceptor. Is MergeMetaDataInterceptor necessary?

            3.

            "scott.stark" wrote:

            the jndi binding should be done via an aspect on this bean.


            I don't understand. Why not just do it in RemotingProxyFactory?

            • 4. Re: JRMPProxyFactory equivalent for POJO Services
              Andrew Rubinger Master

               

              "ron.sigal@jboss.com" wrote:
              1. Provisionally, I've put RemotingProxyFactory in jboss-aspects/remoting, since it uses facilities from there. Is there some other more appropriate home for it?


              RemotingProxyFactory does the following:

              1) Registers the target w/ the Dispatcher
              2) Constructs a POJI Proxy to the target
              3) Adds an interceptor chain to the proxy

              As it's not itself an aspect, I'd consider it a good candidate for a yet-to-exist project under jbossas/projects as opposed to jboss-aspects. What qualifies a candidate for an integration project (jbossas/projects/integration/remoting)?

              "ron.sigal@jboss.com" wrote:
              3.
              "scott.stark" wrote:

              the jndi binding should be done via an aspect on this bean.

              I don't understand. Why not just do it in RemotingProxyFactory?


              Who's to say that the returned remoting proxy will always be bound into JNDI? I'd view this as a separate concern. :)

              S,
              ALR

              • 5. Re: JRMPProxyFactory equivalent for POJO Services
                Ron Sigal Master

                 

                "ALRubinger" wrote:

                a yet-to-exist project under jbossas/projects


                I nominate Andrew Lee Rubinger as project lead. :)

                • 6. Re: JRMPProxyFactory equivalent for POJO Services
                  Andrew Rubinger Master

                  No, I prefer to have opinions without the burden of responsibility.

                  S,
                  ALR

                  • 7. Re: JRMPProxyFactory equivalent for POJO Services
                    Brian Stansberry Master

                    The JNDI binding could be done via an @JNDI annotation:

                     <bean name="SampleTarget" class="org.jboss.aspects.remoting.test.proxy.SampleTarget"/>
                    
                     <bean name="SampleTargetProxyFactory" class="org.jboss.aspects.remoting.RemotingProxyFactory">
                     <property name="target"><inject bean="SampleTarget"/></property>
                     <property name="interfaces">
                     <array elementClass="java.lang.Class">
                     <value>org.jboss.aspects.remoting.test.proxy.SampleInterface1</value>
                     <value>org.jboss.aspects.remoting.test.proxy.SampleInterface2</value>
                     </array>
                     </property>
                     <property name="dispatchName">proxyTest</property>
                     <property name="invokerLocator">socket://0.0.0.0:4873</property>
                     <property name="interceptors">
                     <list elementClass="java.lang.String">
                     <value>org.jboss.aspects.remoting.test.proxy.FactorInterceptor</value>
                     <value>org.jboss.aspects.remoting.test.proxy.AddendInterceptor</value>
                     </list>
                     </property>
                     </bean>
                    
                     <bean class="org.jboss.aspects.remoting.test.proxy.SampleInterface1">
                    
                     <annotation>
                    @org.jboss.aop.microcontainer.aspects.jndi.JndiBinding(name="proxyTestJNDI")
                     </annotation>
                    
                     <constructor factoryMethod="getProxy">
                     <factory bean="SampleTargetProxyFactory"/>
                     </constructor>
                    
                     </bean>
                    


                    If the "factory" element supported a nested "bean" element it would be a bit cleaner.

                    • 8. Re: JRMPProxyFactory equivalent for POJO Services
                      Andrew Rubinger Master

                      Further classes that can go from jboss-remoting-aspects into a new remoting (integration?) project:

                      PojiProxy
                      Remoting
                      AOPRemotingInvocationHandler

                      ...as these really have nothing to do with aspects. I'm in no rush to move these now, as it'll probably wreak havoc on existing users of this code (lord knows where this stuff is peppered; they used to be in AS). Only thing we get by moving it out is an organizational benefit.

                      S,
                      ALR

                      • 9. Re: JRMPProxyFactory equivalent for POJO Services
                        Ron Sigal Master

                         

                        "bstansberry@jboss.com" wrote:

                        The JNDI binding could be done via an @JNDI annotation:


                        That's pretty cool. So, it looks like there are three votes in favor of removing the JNDI binding step from RemotingProxyFactory. OK.

                        bstansberry@jboss.com" wrote:

                        If the "factory" element supported a nested "bean" element it would be a bit cleaner.


                        Just to be sure I understand, you're talking about a microcontainer feature, right, not something I should do with RemotingProxyFactory?

                        I think the use of the factory element here is also pretty cool. The one thing that strikes me is that the bean with the factory element is defined with a single interface class, even though the proxy will, in fact, implement two interfaces. I certainly don't know the microcontainer internals, but superficially it seems like a bean with a factory element could live without a class attribute, since it could be derived from the factory method's return type.

                        • 10. Re: JRMPProxyFactory equivalent for POJO Services
                          Brian Stansberry Master

                           

                          "ron.sigal@jboss.com" wrote:

                          bstansberry@jboss.com" wrote:

                          If the "factory" element supported a nested "bean" element it would be a bit cleaner.


                          Just to be sure I understand, you're talking about a microcontainer feature, right, not something I should do with RemotingProxyFactory?


                          Yep. Just a minor thing. Instead of this:

                          <bean name="SampleTargetProxyFactory" class="org.jboss.aspects.remoting.RemotingProxyFactory">
                          
                           ......
                          
                           </bean>
                          
                           <bean class="org.jboss.aspects.remoting.test.proxy.SampleInterface1">
                          
                           <annotation>
                          @org.jboss.aop.microcontainer.aspects.jndi.JndiBinding(name="proxyTestJNDI")
                           </annotation>
                          
                           <constructor factoryMethod="getProxy">
                           <factory bean="SampleTargetProxyFactory"/>
                           </constructor>
                          
                           </bean>
                          


                          You'd nest the factory bean:

                           <bean class="org.jboss.aspects.remoting.test.proxy.SampleInterface1">
                          
                           <annotation>
                          @org.jboss.aop.microcontainer.aspects.jndi.JndiBinding(name="proxyTestJNDI")
                           </annotation>
                          
                           <constructor factoryMethod="getProxy">
                           <factory>
                           <bean class="org.jboss.aspects.remoting.RemotingProxyFactory">
                          
                           ......
                          
                           </bean>
                           </factory>
                           </constructor>
                          
                           </bean>
                          


                          The nesting just reduces the visibility of the factory vs. the proxy, plus saves having to name the factory bean.

                          "ron.sigal@jboss.com" wrote:

                          I think the use of the factory element here is also pretty cool. The one thing that strikes me is that the bean with the factory element is defined with a single interface class, even though the proxy will, in fact, implement two interfaces. I certainly don't know the microcontainer internals, but superficially it seems like a bean with a factory element could live without a class attribute, since it could be derived from the factory method's return type.


                          The class attribute is optional in the schema; I don't know if omitting it would work. I believe in the past it was required, but the MC guys are improving stuff all the time.

                          You could also use org.jboss.aop.proxy.Proxy instead of the interface. In fact you might have to, since that's the return type from the factory method. I used the interface because that's the idiom I'd used previously with a factory bean for creating a JBoss Cache instance. But the return type on their factory was the interface org.jboss.cache.Cache.