Cannot run two AbstractComponents simultaneously using the ExternalComponentController method

Based on the AbstractComponent examples provided in https://github.com/igniterealtime/Whack/tree/master/sample/weatherabstract/sourc e/java/org/jivesoftware/weather , I went forward and created an implementation of the ExternalComponentController as follows:

package test.xmpp; import org.apache.log4j.Logger; import java.lang.reflect.*; import org.jivesoftware.whack.ExternalComponentManager;
import org.xmpp.component.ComponentException;
import org.xmpp.component.Component; public class CommunicatorComponent {     public static final String XMPP_SERVER = "test.mycompany.com";
    public static final String XMPP_SERVICE_NAME = "test.mycompany.com";
    public static final String XMPP_SERVICE_NAME_COMPONENT = "component.test.mycompany.com";
    public static final int XMPP_PORT_COMPONENT = 5275;
    public static final String XMPP_KEY_COMPONENT = "xyzsecretkey";
      private static final Logger LOGGER = Logger.getLogger(CommunicatorComponent.class);     ExternalComponentManager manager = null;
        public static CommunicatorComponent getInstance(String componentname, String componentclass){
        CommunicatorComponent componentInstance = null;
        try {
            componentInstance = new CommunicatorComponent(componentname,componentclass);
        } catch (ComponentException e) {
            LOGGER.error("XMPP component "+componentname+" with class name "+componentclass+" could not get created ",e);
            e.printStackTrace();
        }
        return componentInstance;
    }     public CommunicatorComponent(String componentname, String componentclass) throws ComponentException {
            if(manager==null){
            manager = new ExternalComponentManager(XMPP_SERVER, XMPP_PORT_COMPONENT);
            manager.setSecretKey(componentname, XMPP_KEY_COMPONENT);
            manager.setMultipleAllowed(componentname, false);
        }
        if ((componentname!=null)&&(componentclass!=null)){
            addComponentToServer(componentname, componentclass);
        }
    }     private void addComponentToServer(String componentname, String componentclass){         Component componentclasscomponent = null;         try {
            try{
                // Load the Class. Must use fully qualified name here!
                Class clazz = Class.forName(componentclass);
                //I need an array as follows to describe the signature
                //Class[] parameters = new Class[] {String.class, String.class};
                // Now I can get a reference to the right constructor
                Constructor constructor = clazz.getConstructor(new Class[]{String.class,String.class});
                // And I can use that Constructor to instantiate the class
                componentclasscomponent = (Component) constructor.newInstance(new Object[] {componentname, manager.getServerName()});             } catch (Exception e) {
                LOGGER.error("XMPP component "+componentname+" with class name "+componentclass+" could not get started ",e);
            }             manager.addComponent(componentname, componentclasscomponent);
                        LOGGER.info("XMPP component "+componentname+" with class name "+componentclass+" was connected to the XMPP server");
                        while (true) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } catch (ComponentException e) {
            LOGGER.error("XMPP component "+componentname+" with class name "+componentclass+" could not connect to the XMPP server ",e);
            e.printStackTrace();
        }
    }
   }

Note that the componentclasscomponent class invocation was required as we need to use the above to invoke many different classes which require parameters.

In order to invoke the associated TestOneComponent class (External Component of type Abstract, as per the samples given in the code in GIT) which operates as a bot using the above from an initalization class file we have, we launch it as:

new CommunicatorComponent(“test1”,“test.xmpp.ssclient.TestOneComponent”);

It launches but it does not return control back to the application to invoke other classes/code after that. In other words, if we want to perform consecutively:

new CommunicatorComponent(“testone”,“test.xmpp.ssclient.TestOneComponent”);

new CommunicatorComponent(“testtwo”,“test.xmpp.ssclient.TestTwoComponent”);

to invoke two different external components, as soon as the first one is invoked the code stops and control is not returned back to the running code to invoke the second component.

Clearly, there is a mistake somewhere… however I cannot pinpoint it.

Any help?

This is actually pretty easy to spot:

while (true) {                 try {                     Thread.sleep(500);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }             }

Your first component blocks forever in that loop.

Of course that was the culprit…

Two quick related questions:

  • Instead of explicitly invoking a new class from a string parameter as in my code, how can I invoke myclass.getInstance() where myclass is a class string name variable and getInstance is a method within the class? I cannot seem to find a way

  • Can I add multiple external components using manager.addComponent with a single-initialized manager ExternalComponentManager variable or I should create new ExternalComponentManager instances when I want to perform something like:

manager.addComponent(componentname1, componentclasscomponent1);

manager.addComponent(componentname2, componentclasscomponent2);

At the moment, when I use the same ExternalComponentManager instance, I get an error from Whack indicating a “conflict”.

  • Instead of explicitly invoking a new class from a string parameter as in my code, how can I invoke myclass.getInstance() where myclass is a class string name variable and getInstance is a method within the class? I cannot seem to find a way

If you only have the class name as String, there’s no way around to first create an instance of that class via newInstance().

  • Can I add multiple external components using manager.addComponent with a single-initialized manager ExternalComponentManager variable or I should create new ExternalComponentManager instances when I want to perform something like:

manager.addComponent(componentname1, componentclasscomponent1);

manager.addComponent(componentname2, componentclasscomponent2);

At the moment, when I use the same ExternalComponentManager instance, I get an error from Whack indicating a “conflict”.

I am not familiar with Whack, but I think yes. addComponent implies, that you can add multiple.

“conflict” might mean, that the component does not exist on the server, according to XEP-0114.