13 Replies Latest reply on Jul 26, 2006 4:31 AM by dreyk

    Remoting using Http over a singel port

    marcreis

      The scenario, a (cluster of) JBoss 4.0.4RC2 running behind a Firewall/NAT, a client communicating via http with the Server and visa versa. So, all over http and just using a single port (e.g. 8080) and using EJB 3.0. (Something like client <=> Firewall <=> I-Net <=> Firewall<=>Apache<=>JBossCluster )

      We have read through the most of the forum and issue posts we could find concerning this topic (best of by searching for ?clientBindUrl? in the forum and continuing from there).
      So instead of asking the same questions again, I?ll try to keep it very general:
      - Which configurations can/have too be done to get this working, or to be more precisely which is the best method of doing so, as concerning the current state and the near changes (as I read, there could be a release of a Remoting package this month which could change some things ?).
      - Can the clientBindUrl, also be defined in an external file like the ejb-jar.xml rather than annotating each bean?

      Maybe someone could post a small ?guide? on how to do this properly (for one case or maybe distinct for different cases (Http/Servlet etc))
      And yes, I know there is a http://labs.jboss.com/portal/jbossremoting/docs/guide/ch04.html, and I have read through it.

      _____________________________________________________________

      Just in case this seems to general I?ll hang on some of what we encountered so far:
      First of, things we did were configure the ejb3.deployer\META-INF\jboss-service.xml, copy the tomcat libs missing, alter the jndi.properties for the client and adding the bean annotation for the clientBindUrl and played with these settings.
      - the various ways of configuring the \deploy\ejb3.deployer\META-INF\jboss-service.xml seem to enable a initial communication over lets say port 8080
      - after initial lookup of JNDI over 8080, when invoking an interfaces, it has its ?InvokationLocator? property set at its default ?0.0.0.0:3873? (as defined in RemoteProxyFactory.java.) unless
      - the annotation @RemoteBinding(clientBindUrl=?) is used.

      I read that the clientBindUrl should, since EJB 3.,0 RC2, be fetch from the MBean, but this seems to work only initially. Without the annotation, a method invocation of a remote bean interface will lead in a try to communicate over port 3873 (as for our config).
      When setting up all of this, it is still not working correctly.
      I guess we could/should try the version with the serverlet-invoker.war (would be nice to have easy access to it) and then configure the jboss-service.xml accordingly. But having a guide on how this is done best and what/how it is so far implemented and how/what will be changed would be create

      Sincerely
      Marc

        • 1. Re: Remoting using Http over a singel port

          Hi Marc. You have obviously done your home work (thanks). I think having a guide for what you mentioned would be good and will work on this.

          I need to setup a envrionment to reproduce the setup you mention, but my guess there is a bug in there somewhere (maybe where ejb3 is picking up the remote server locator url). I will let you know when I have made some progress on it.

          • 2. Re: Remoting using Http over a singel port
            marcreis

            Thanks a lot !
            I'll keep my eyes open on the forum, and just in case I figure something out, I'll post it. Thanks !

            Sincerely Marc

            • 3. Re: Remoting using Http over a singel port
              marcreis

              Hi Tom,
              I did some further testing, when I set up a cluster on a single machine, the Bindingmanager assigns port 3873 and 4073 for the Connector defined in "/EJB3Deployer/META-INF/jboss-service.xml". When I kill the first node, 3873 is of course gone and the app fails. Just running node 2 shows, the Interfaces InvokerLocator property still trys the 3873 port , even though it has never been set for that node. This also shows up when both servers are running, then the 2 InvokerLocator elements in the interfaces array are both the same (and not 3873 and 4073).

              I also have another question: after looking at the InvokerLocator's method "private static final String resolveHost(String host)", I think that the host name will always be looked up to the IP address of the current machine (I guess do too performance reasons) (or did I miss something?). Is it possible to avoid this? I thing in a scenario were each IP Addresses of the JBoss servers should or is not visible to the outside, is imaginable (e.g. Client goes over the I-Net to the Servers). Then this would lead to an invocation failure since the ip is not resolvable to the client. Please correct me if I am wrong, I am still missing quite a bit of over view over all this.

              Sincerely
              Marc

              • 4. Re: Remoting using Http over a singel port

                Hi Marc. I am still trying to get a full environment for testing this setup in our QA lab, so don't have the resolution to this yet.

                However, did want to comment on the resolveHost() method. You are right about this being for performance (so if making many calls from client to server, the server ip address is looked up once instead of having to do DNS lookup each time). Maybe the should be something that is configurable since may have the case where want to change the machine that the host name would point to if running your own DNS and have the clients just be routed to the new box. I am missing the point though where this would be a problem from the client side otherwise.

                • 5. Re: Remoting using Http over a singel port
                  bdecoste

                  Marc, the deployment descriptor override of clientBindUrl is not yet implemented, but will be by the next release of EJB3. There is a JIRA task for this task:

                  http://jira.jboss.com/jira/browse/EJBTHREE-571

                  • 6. Re: Remoting using Http over a singel port

                    My biggest concern is with how ejb3 is picking up the remoting locator url. It should be coming from the remoting server (Connector to be exact) and bound within the ejb3 client. This way, users can configure all the remoting info, including clientBindUrl in one place on the server, and know it will be picked up and used within the clients. I thought this was how it was being done currently?

                    • 7. Re: Remoting using Http over a singel port
                      marcreis

                      Hi, thanks for your answers!

                      I don?t know, but I would guess that the deployment descriptor override function will act like useing the corresponding annotation at the moment.(?)
                      When I use the annotation ?clientBindURL?, I can set the port and the host name. I then still have the problem that the host name is looked up towards the IP of the maschine.
                      I am not sure, but since I found the sources to this in the remoting package, (and not in the AS sources ejb3/../remoting) I thing this could be a problem which relates to all using/relaying on the ?InvokerLocator.java??s ?resolveHost(String host)? method.
                      So, as far as I would guess, when the deployment descriptor override function is fully implemented, it would pass the ?${jboss.bind.address}? for the attribute ?IvokerLocator? (as defined in the ejb3 deployers jboss-service.xml) on, as it has been set with the"--host? option at start up, just like using the annotation at the moment.
                      It then would pass the host name on as suspected by Tom. But then again at this point, the only place where this is keept in the InvokerLocator is the String ?originalURL?, since the actuall host name has been looked up to the IP and the IP is what is used. So again there is the problem of a client in a diffrent network, not beein abel to look up that IP of the server at all or correctly.

                      Thanks for taking your time on this!

                      Sincerely
                      Marc

                      ( Is a rough approximation for the time when the deployment descriptor override function is fully implemented possible? :-). At the moment we are thinging on altering the InvokerLocator?s ?resolveHost? method, so that the host name is used instead of the IP, any Tips that should be considert when doing this (other than the performance loss do to dns lookups, maybe concerning Clustering and HA) ? )


                      • 8. Re: Remoting using Http over a singel port
                        bdecoste

                        The clientBindUrl override has been completed and will be available in EJB3 RC8 (RC7 was completed Fri of last week). I will let you know when RC8 is planned for release asap. The jboss.xml override replaces or adds the RemoteBinding annotation.

                        I'm looking at your host/InvokerLocator issue.

                        • 9. Re: Remoting using Http over a singel port
                          marcreis

                          Thanks !, I'llkeep my eyes open for news !

                          • 10. Re: Remoting using Http over a singel port
                            hezimmer

                            Hi,
                            i also spent a lot of time to configure and work this thing (as Marc mentioned before) out. The Client should get the originalUrl (InvokerLocator) and not the ip-adress from server. So i think a good solution would be to set the hostname initially (at startup with --host=) which then will be used inside of jboss-service.xml from ejb3.deployer as an part of the attribute InvokerLocator (via ${jboss.bind.address}). Instead of ip adress resolving, this hostname should be used for the mbean and the default entry for clientBindUrl when registering (deploying) EJB3-Beans.
                            In addition to this default behaviour a developer should also have the chance to override this by using Annotation @RemoteBinding(...clientBindUrl...) or the much better way, as bdecoste and Marc mentioned before, via an entry in jboss.xml.

                            Should this be possible or are we running into problems when using Jboss Clustering?

                            Kind regards
                            Heiko

                            • 11. Re: Remoting using Http over a singel port

                              Have added a jira issue for using host name as is within InvokerLocator instead of automatically converting to an IP value - http://jira.jboss.com/jira/browse/JBREM-497.

                              However, this is an issue with the equals() method in that should an InvokerLocator with an initial uri of 'socket://localhost:1234' and another with 'socket://127.0.0.1:1234' evaluate to being equal? If so, how can this be done without a huge performance hit each time?

                              • 12. Re: Remoting using Http over a singel port
                                hezimmer

                                Hi Tom,
                                i created a new testcase to find out more about this issue. I've used 4.0.4GA from source and created an servlet-invoker.war from JBoss-Remoting 1.4.1. I've done several tests with socket and servlet (http) protocol and found the difference inside HttpClientInvoker and SocketClientInvoker. So in HttpClientInvoker the originalURL is used to connect from Client to Server (to call methods on an ejb3 bean clientBindUrl is used), as in SocketClientInvoker the host is used, which will always be resolved to ip-adress inside the InvokerLocator.
                                So i think that in an Client=>Firewall=>JBoss environment this behaviour is ok as far as you were using the http protocol which should be the favourite. So in my opinion the problem could only occure if someone is using socket - transport instead of http.
                                To quickly get an workaround about the @RemoteBinding clientBindUrl issue (EJB3-RC8 is not released yet), i defined an property named clientBindUrl.default where i can define an default URL for all EJB3-Bindings. This property is set at server-startup and is independent from InvokerLocator-URL (jboss-service.xml) as i thought about to use as default before. This because we use an Apache-Server for http and the ejb3.deployer is bound on port 8080, but clients must call ejb3's over port 80.

                                Kind regards,
                                Heiko


                                • 13. Re: Remoting using Http over a singel port
                                  dreyk

                                  While jboss server deploy ejb3 module,it properly find default ClientBindUrl
                                  from ejb3.deployer/META-INF/jboss-service.xml see Ejb3JmxDeployment.java :

                                  public String getDefaultClientBinding()
                                   {
                                  
                                   try
                                   {
                                   ObjectName on = new ObjectName("jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3");
                                   ConnectorMBean connector = (ConnectorMBean) MBeanProxyExt.create(ConnectorMBean.class, on, deploymentInfo.getServer());
                                   String uri = connector.getInvokerLocator();
                                   return connector.getInvokerLocator();
                                   }
                                   catch (Exception e)
                                   {
                                   throw new RuntimeException(e);
                                   }
                                   }


                                  This method always invoking during deployment, and aftter that deployer set property defaultClientBinding in class ProxyDeployer to correct value.
                                  But after that server invoke method initializeRemoteBindingMetadata() in ProxyDeployer class, and if it can't find RemoteBinding anntation it will be use defaultClientBinding from jboss-service.xml and default jndi binding, but if it find this annatation in deployed ejb it will be use RemoteBinding from whith ejb,where default value is socket://0.0.0.0:XXXX, that is why you can change this code for use defaultClientBinding from jboss-service.xml. But preffer is define in RemoteBinding annatotion default value for clientBindUrl to "" and in method initializeRemoteBindingMetadata() chek that this property not set to some value diferent from default and set it to property defaultClientBinding.
                                  see Original code:
                                  public void initializeRemoteBindingMetadata()
                                   {
                                  
                                   remoteBindings = (RemoteBindings) advisor.resolveAnnotation(RemoteBindings.class);
                                   if (remoteBindings == null)
                                   {
                                   RemoteBinding binding = (RemoteBinding) advisor.resolveAnnotation(RemoteBinding.class);
                                   if (binding == null)
                                   {
                                   log.debug("no declared remote bindings for : " + container.getEjbName());
                                   if (ProxyFactoryHelper.getRemoteInterfaces(container) != null)
                                   {
                                   log.debug("there is remote interfaces for " + container.getEjbName());
                                   String jndiName = ProxyFactoryHelper.getDefaultRemoteJndiName(container);
                                   log.debug("default remote binding has jndiName of " + jndiName);
                                   // todo we need to have a way to define default configuration
                                   String uri = defaultClientBinding;
                                   Class factory = null;
                                   factory = getDefaultRemoteProxyFactory();
                                   RemoteBinding[] list = {new RemoteBindingImpl(jndiName, "", uri, factory)};
                                   remoteBindings = new RemoteBindingsImpl(list);
                                   advisor.getAnnotations().addClassAnnotation(RemoteBindings.class, remoteBindings);
                                   }
                                   }
                                   else
                                   {
                                  
                                   RemoteBinding[] list = {binding};
                                   remoteBindings = new RemoteBindingsImpl(list);
                                   advisor.getAnnotations().addClassAnnotation(RemoteBindings.class, remoteBindings);
                                   }
                                   }
                                   }


                                  and changed code:
                                  public void initializeRemoteBindingMetadata()
                                   {
                                  
                                   remoteBindings = (RemoteBindings) advisor.resolveAnnotation(RemoteBindings.class);
                                   if (remoteBindings == null)
                                   {
                                   RemoteBinding binding = (RemoteBinding) advisor.resolveAnnotation(RemoteBinding.class);
                                   if (binding == null)
                                   {
                                   log.debug("no declared remote bindings for : " + container.getEjbName());
                                   if (ProxyFactoryHelper.getRemoteInterfaces(container) != null)
                                   {
                                   log.debug("there is remote interfaces for " + container.getEjbName());
                                   String jndiName = ProxyFactoryHelper.getDefaultRemoteJndiName(container);
                                   log.debug("default remote binding has jndiName of " + jndiName);
                                   // todo we need to have a way to define default configuration
                                   String uri = defaultClientBinding;
                                   Class factory = null;
                                   factory = getDefaultRemoteProxyFactory();
                                   RemoteBinding[] list = {new RemoteBindingImpl(jndiName, "", uri, factory)};
                                   remoteBindings = new RemoteBindingsImpl(list);
                                   advisor.getAnnotations().addClassAnnotation(RemoteBindings.class, remoteBindings);
                                   }
                                   }
                                   else
                                   {
                                   //if user define clientBindUrl than use binding.clientBindUrl()
                                   if(binding.clientBindUrl().equals("")){
                                   RemoteBinding[] list = {new RemoteBindingImpl(binding.jndiBinding(),binding.interceptorStack(),defaultClientBinding,binding.factory())};
                                   remoteBindings = new RemoteBindingsImpl(list);
                                   }
                                   else{
                                   RemoteBinding[] list = {binding};
                                   remoteBindings = new RemoteBindingsImpl(list);
                                   }
                                   advisor.getAnnotations().addClassAnnotation(RemoteBindings.class, remoteBindings);
                                   }
                                   }
                                   }


                                  String clientBindUrl() default ""; in org.jboss.annotation.ejb.RemoteBinding

                                  But I think preffer solution for this problem it's define new annatation for clientBindUrl and in this method check only existinse this annataton.