Anita Katakkar
Anita Katakkar

Reputation: 11

jboss-eap-quickstarts cluster-ha-singleton client JNDI Lookup Class Cast Exception

I'm using JBoss 6.2 and am attempting to call a singleton service from a webapp filter.

I've successfully installed and started a singleton service within a clustered environment as outlined by the following quickstart tutorial:

https://github.com/jboss-developer/jboss-eap-quickstarts/tree/44c8c90/cluster-ha-singleton

We can see that the singleton service has been successfully deployed in the admin console (I uploaded an image to my website as I don't have a high enough reputation on stack overflow to post images):

http://www.rakkatak.com/so/stackoverflow_question_singletonservice_img1.png

As a supplement to the quickstart tutorial, I would like an example of calling the singleton service from an external client. In my case this is a filter (LoginFilter) that is accessed via a service.jar placed in the JBoss modules directory. This jar contains the following:

/META-INF/jboss-ejb-client.properties /com/login/filter/LoginFilter.class

For the purposes of what I'm trying to do, I'm not using a clustered environment and only Node1 will be running.

jboss-ejb-client.properties contains:

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=node1
remote.connection.node1.host=localhost
remote.connection.node1.port = 9999
remote.connection.node1.connect.timeout = 500
remote.connection.node1.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

LoginFilter.java contains:

final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);

System.out.println(">>>>> JNDI LOOKUP >>>>>");
Object obj = context.lookup("global/jboss-cluster-ha-singleton-service/SchedulerBean!org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.Scheduler");
Scheduler scheduler = (Scheduler) obj;
System.out.println(">>>>> JNDI END >>>>>");

I copy service.jar into $JBOSS_HOME/modules/com/login/filter/main and then start up the node1 server.

Within the directory where service.jar is located we have the following dependencies defined in module.xml:

<module xmlns="urn:jboss:module:1.0" name="td.oca.spike.kernel">
    <resources>
        <resource-root path="service.jar"/>
    </resources>
    <dependencies>
        ...
        <module name="org.jboss.as.quickstarts" />
    </dependencies>
</module>

Where org.jboss.as.quickstarts is another module containing the SchedulerBean interface.

Next I bring up the Login webapp in my browser which is configured to use the above LoginFilter class. When I invoke it, we never see the System out ">>>>> JNDI END >>>>>" instead I get the following class cast exception:

java.lang.ClassCastException: org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.Scheduler$$$view1 cannot be cast to org.jboss.as.quickstarts.cluster.hasingleton.service.ejb.Scheduler

I think that I must be missing some sort of configuration to allow the singleton service to be called from the LoginFilter. Please make any suggestions that you think might help and thanks in advance!

Scheduler.java

package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;

/**
 * @author <a href="mailto:[email protected]">Wolf-Dieter Fink</a>
 */
public interface Scheduler {

    void count();

    void initialize(String info);

    void stop();

}

SchedulerBean.java

package org.jboss.as.quickstarts.cluster.hasingleton.service.ejb;

import javax.annotation.Resource;
import javax.ejb.ScheduleExpression;
import javax.ejb.Singleton;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;

import org.jboss.logging.Logger;


@Singleton
public class SchedulerBean implements Scheduler {
    private static Logger LOGGER = Logger.getLogger(SchedulerBean.class);
    @Resource
    private TimerService timerService;

    private int counter=0;

    @Timeout
    public void scheduler(Timer timer) {
        LOGGER.info("*** HASingletonTimer: Info=" + timer.getInfo());
    }

    @Override
    public void initialize(String info) {
        ScheduleExpression sexpr = new ScheduleExpression();
        // set schedule to every 10 seconds for demonstration
        sexpr.hour("*").minute("*").second("0/10");
        // persistent must be false because the timer is started by the HASingleton service
        timerService.createCalendarTimer(sexpr, new TimerConfig(info, false));
    }

    @Override
    public void stop() {
        LOGGER.info("Stop all existing HASingleton timers");
        for (Timer timer : timerService.getTimers()) {
            LOGGER.trace("Stop HASingleton timer: " + timer.getInfo());
            timer.cancel();
        }
    }


    @Override
    public void count() {
        counter++;
        LOGGER.info("***** HASingletonTimer: Counter=" + counter);
    }
}

Upvotes: 1

Views: 737

Answers (1)

hugh
hugh

Reputation: 2280

I think the problem is that you're trying to access Scheduler remotely, but it since it isn't annotated as a remote interface it defaults to being local: https://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html

Could you add a @Remote to Scheduler and see if that makes things better?

Upvotes: 0

Related Questions