users@glassfish.java.net

Re: How to invoke Client Callback Handler from EJB3 Session Bean

From: Miroslav Nachev <miro_at_space-comm.com>
Date: Fri, 23 May 2008 00:20:47 +0300
Hi,

Because this is very critical for me and the project I am thinking about another solutions. What if I replace RMI-IIOP with WebServices? In HTTP World (AJAX, JavaScript) we have more solutions with not so much restrictions comparing pure Java and RMI-IIOP. My idea is follow:

Server (GlassFish)
Transport
Swing Client (JWS/JNLP)
WebServices server
HTTPS
WebServices client
WebServices client
WebServices server

Then I will be able to create client-side callback, maybe?


Regards,
Miro.


Miroslav Nachev wrote:
Hi,

As you recommend me I am trying to implement Client side Callback. Unfortunately I have the following exception:

javax.ejb.ConcurrentAccessException: SessionBean is executing another request. [session-key: d0905b3100571f-120d8859-0]
       at com.sun.ejb.containers.StatefulSessionContainer.handleConcurrentInvocation(StatefulSessionContainer.java:2624)
       at com.sun.ejb.containers.StatefulSessionContainer._getContext(StatefulSessionContainer.java:2462)
       at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:1675)
       at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1229)
       at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:202)
       at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:117)
       at $Proxy80.assemble(Unknown Source)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:597)
       at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:154)
       at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:687)
       at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:227)
       at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1846)
       at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1706)
       at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:1088)
       at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:223)
       at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:806)
       at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:563)
       at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2567)
       at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)

Do you have another ideas how to create Client side Callback mechanism?

Here is the code:
@Stateful
public class ProductAssemblerBean
    implements ProductAssemblerRemote
{
    private final static Logger logger = Logger.getLogger(ProductAssemblerBean.class.getName());

    private boolean newCallbackRequest;
    private Callback[] newCallbacks;

    private boolean hasCallbacksResult;
    private CallbackResult callbackResult;

    public Object assemble() {
        return "miro";
    }
   
    public Callback[] clientHandle(CallbackResult callbackResult)
    {
        if(callbackResult != null)
        {
            this.callbackResult = callbackResult;
            hasCallbacksResult = true;
            return null;
        }

        if(newCallbackRequest)
        {
            newCallbackRequest = false;
            this.callbackResult = null;
            hasCallbacksResult = false;

            return newCallbacks;
        }

        return null;
    }

    public void handle(Callback[] callbacks)
        throws IOException, UnsupportedCallbackException
    {
        newCallbacks = callbacks;
        newCallbackRequest = true;

        while(!hasCallbacksResult)
        {
            Thread.yield();
        }
        hasCallbacksResult = false;

        Exception ex = callbackResult.getException();
        if(ex != null)
        {
            if(ex instanceof IOException)
                throw ((IOException)ex);

            if(ex instanceof UnsupportedCallbackException)
                throw ((UnsupportedCallbackException)ex);

            throw new RuntimeException(ex);
        }

        Callback[] resultCallbacks = callbackResult.getCallbacks();
        for(int i = 0; i < callbacks.length; i++)
        {
            callbacks[i] = resultCallbacks[i];
        }
    }

}

Client side:

    public static Object getData()
        throws Exception
    {
        ProductAssemblerRemote productAssembler = InitialContext.doLookup(ProductAssemblerRemote.class.getName());
        ClientCallback clientCallback = new ClientCallback(productAssembler);
        Object result;
        try
        {
            clientCallback.start();
            result = productAssembler.assemble();
        }
        finally
        {
            clientCallback.setWorks(false);
            clientCallback = null;
        }

        System.out.println("result: " + result);
        return result;
    }

    public static class ClientCallback
        extends Thread
    {
        private boolean works;
        private ProductAssemblerRemote productAssembler;

        public ClientCallback(ProductAssemblerRemote productAssembler)
        {
            this.productAssembler = productAssembler;
        }

        @Override
        public void run()
        {
            works = true;
            Callback[] callbacks = null;
            CallbackResult callbackResult = null;

            while(works)
            {
                Thread.yield();
                callbacks = productAssembler.clientHandle(callbackResult);
                callbackResult = null;
                if(callbacks != null && callbacks.length > 0)
                {
                    try
                    {
                        if(false)
                            throw new IOException();
                        if(false)
                            throw new UnsupportedCallbackException(null);
                        // Do something
                        ((ChoiceCallback)callbacks[0]).setSelectedIndex(7);

                        callbackResult = new CallbackResult(callbacks);
                    }
                    catch(IOException ex)
                    {
                        callbackResult = new CallbackResult(ex);
                    }
                    catch(UnsupportedCallbackException ex)
                    {
                        callbackResult = new CallbackResult(ex);
                    }
                    catch(Exception ex)
                    {
                        callbackResult = new CallbackResult(ex);
                    }
                }
            }

            System.out.println("ClientCallback stoped.");
        }

        public boolean isWorks() {
            return works;
        }

        public void setWorks(boolean works) {
            this.works = works;
        }
    }


Regards,
Miro.




glassfish@javadesktop.org wrote:
Miro,

Everyone who has replied to you is trying to help, although you seem to be frustrated with what we are saying.  Let me try to explain once again.

As several of us have written, the Java EE programming model does not support what you want to do using a simple method invocation model.  

You have mentioned the client authentication callback several times, repeatedly asking for what classes and methods in that implementation you can use to do what you want.  You have assumed that the ORB server calls back to the ORB client.  It does not.  

In fact the naming and ORB implementation internally follows exactly the approach ljnelson and I have suggested that you use in your application.  The fact that authentication is required is returned to the ORB client as part of a remote method [i]return value[/i]. The ORB on the client side uses that return value to prompt the user for additional information using the authentication callback.  (Note that this method callback occurs locally, from one object on the client to another.  It does NOT occur from the server to the client.)  Then the ORB sends another remote method call to the server with the new information collected from the user.  Always the ORB client makes the method call and responds to the return value.

ljnelson and I have suggested one way you can solve your problem using a similar approach.  Markus suggested another. I understand that neither of these approaches is what you were thinking about initially, and neither is as simple as the remote method callback you first talked about.  But your approach is not supported.  No one will be able to tell you what class and method in the ORB implementation you can use to do this because no such method exists that will do what you want the way you want to do it.  Plus it would not be supported and I would think you want to avoid an unsupported solution. 

I believe that the technique ljnelson and I have suggested would be only slightly more complicated then your original idea in which the server calls back to the client.  In your approach the server might be able to invoke one of several different client-side methods, depending on what additional information might be needed.  In ljnelson's and my approach, the server needs to return that information as part of a return value object from the EJB method so the client can figure out what information to request of the user.  

I understand you are frustrated that you cannot solve the problem in the way you first thought would work.  People have tried to be helpful, suggesting several different ways you can implement your application that will meet the business need using what Java EE offers.  I hope you will be able to choose one of those that meets the business need - even if it is not the technical approach you first had in mind - and be successful with your application.

- Tim
[Message sent by forum member 'tjquinn' (tjquinn)]

http://forums.java.net/jive/thread.jspa?messageID=275054

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@glassfish.dev.java.net
For additional commands, e-mail: users-help@glassfish.dev.java.net