Skip to main content

Using Java EE APIs for asynchronously invoking Application Module methods

The JDeveloper 12C release comes with WLS 12C version which is fully compatible with JavaEE 6 stack. In this post I'm talking about leveraging Java EE APIs for enhancing your ADF application.

Straight to the point: JavaEE 6 has simplified the asynchronous method invocation in EJBs to a great extent. You just need to annotate the target class or method as @Asynchronous to enable asynchronous invocations. More details can be seen here: http://docs.oracle.com/javaee/6/tutorial/doc/gkidz.html
Today's post talks about leveraging this feature for invoking application module methods asynchronously. This approach can be used when you need to invoke heavy operations such as some batch job or bulk data update from UI without caring the result of  the operation(which can be monitored using some other page). Implementation is simple, we are simply wrapping application method call in an asynchronous EJB method. Client calls asynchronous EJB method which in turn invokes application module method. The following is an example:

Please note the usage of ADFContextInterceptor which is required to set up the ADFContext object. Full implementation of this class can be seen in the sample work space attached at the end of this post. Also the ejb-jar.xml in the Model project contains the description for jdbc/HRDS data source

@Stateless(name = "HRSessionEJB", mappedName = "AsynchADFBC-Model-HRSessionEJB")
@Interceptors(value = ADFContextInterceptor.class)
public class HRSessionEJBBean {
    @Resource
    SessionContext sessionContext;

    public HRSessionEJBBean() {
    }

    @Asynchronous
    public Future executeAMOperationInAsynchMode() {
    String status = null;

    try {
            String amDef = "model.HRAppModule";
            String config = "HRAppModuleLocal";
            HRAppModuleImpl am = (HRAppModuleImpl) Configuration.createRootApplicationModule(amDef, config);
            status = am.processEmployees();
            Configuration.releaseRootApplicationModule(am, true);
  
        } catch (Exception e) {
            //Handles exception in better way
            e.printStackTrace();
        }

        
        return new AsyncResult<String>(status);
    }
}

Download 

You can download the sample workspace from here. [Runs with Oracle JDeveloper 12C 12.1.2.0.0 + Oracle XE].
Run asynch.jsf. Click on the button you may see that control comes back even before operation is finished on the server.  This button is bound to HRSessionEJBBean::executeAMOperationInAsynchMode() which in turn calls appropariate AM method. You may see that control returns right after invoking the method without waiting for the method to finish. See the console window to know when the method actually finishes.

Comments

Florin Marcus said…
Judging by the title, I was expected to see a asynchronous App module method call, but what we have is a asynchronous creation of an application module.

You can do a similar call using JMS or even simple threading.


Hi Jobinesh,

I have one question regarding this Async invocation.

ADF BC does not have this support by default ? I did look at the documentation and I can only find async invocation of ADF BC methods is possible only by exposing it as Web Service.

Please confirm.

Can I conclude it as 12c integration w/ EJB3.1 gives us way to call ADF BC apis asynchronously with OUT complex infrastructure such as Web Services & BPEL./
Hanumantha
Reg. asynchronous WS, its primarily designded when you use in the context of SOA. I'm not very sure whether it will work outside of this context out of the box.
Hi Jobinesh,

Which is the purpose of using an interceptor when the code related to the AdfContext handling could have been added directly in the EJB itself (before creating the AM instance and after releasing it)?

On our project we have tested the approach without the interceptor. It worked fine on the Integrated server, but failed to to so on a managed server and we could not figure out why.

Thank you in advance.

Best regards,
Ioana

Popular posts from this blog

Happy New Year 2018 !

We can't go back and change the beginning, but we always can start where we are and change the ending. Believe in yourself and you will be unstoppable!

Wishing you and your family a very happy new year 2018 !!!

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…