0 Replies Latest reply on Feb 14, 2018 5:52 PM by spacegoat

    Client config for HA EJB RMI

    spacegoat

      I have an application deployed to an environment using the HA profile for two host controllers. I created a client application that uses EJB RMI to invoke business logic that transacts with two data sources. So, the environment is:

       

      1x Domain Controller on a VM

      2x Host Controllers on separate VMs

      2x Datasources/Databases on separate VMs

      1x Client application running on a separate device

       

      I've had success with the client using programmatic configuration of the AuthenticationContext and InitialContext to connect to one host controller separately at a time. Given such a scenario everything functions as expected. However, now I'm trying to implement logic to shift calls from one host controller to another (all using stateless session beans) and any attempt to switch always fails with "EJBCLIENT000079: Unable to discover destination for request for EJB StatelessEJBLocator". I tested this twice, on one test host controller A started communications and B was attempted as the failover (the second test was B first then A) - either way, the first controller communicated fine while the shift to the second resulted in errors. This seems odd to me as I'm constructing separate AuthenticationContexts, InitalContexts and callables for both endpoints separately... but the failures suggest to me that (something) is retaining some context of my connection and doesn't appreciate the shift...

       

      Is there a special way I need to configure a clustered setup? Below is an example of how I would configure the connections and a method to run them:

       

      // Host Controller A
      AuthenticationConfiguration authcfgA = AuthenticationConfiguration
        .empty()
        .useName("username")
        .usePassword("password");
      Properties propA = new Properties();propA.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");propA.put(Context.PROVIDER_URL, "remote+https://host-controller-a:8443");
      AuthenticationContext authctxA = AuthenticationContext.empty().with(MatchRule.ALL.matchHost("host-controller-a"), authcfgA);
      InitialContext initCtxA = new InitialContext(propA);
      Callable callableA = () -> {
           TestBeanRemote bean = (TestBeanRemote)initCtxA.lookup("ejb:app-ear/app/" + TestBean.class.getSimpleName() + "!" + TestBeanRemote.class.getName());
           bean.doSomething();
           return null;
      };
      
      // Host Controller B
      AuthenticationConfiguration authcfgB = AuthenticationConfiguration
        .empty()
        .useName("username")
        .usePassword("password");
      Properties propB = new Properties();propB.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");propB.put(Context.PROVIDER_URL, "remote+https://host-controller-b:8443");
      AuthenticationContext authctxB = AuthenticationContext.empty().with(MatchRule.ALL.matchHost("host-controller-b"), authcfgB);
      InitialContext initCtxB = new InitialContext(propB);
      
      Callable callableB = () -> {
           TestBeanRemote bean = (TestBeanRemote)initCtxA.lookup("ejb:app-ear/app/" + TestBean.class.getSimpleName() + "!" + TestBeanRemote.class.getName());
           bean.doSomething();
           return null;
      };
      
      // Below is an example of how I would use the above (although I have another method that devices which arguments to call this with)
      // ideally, if this were called with Host Controller A args and they failed, this would be called again with Host Controller B args
      private boolean runEjbCallable(AuthenticationContext ctx, Callable callable) {
           try {
                ctx.runCallable(callable);
           } catch(Exception e) {
                return false;
           }
           return true;
      }