What you may need to know while calling Application Module methods from Java EE components such as E

A couple of years back I blogged aboutCalling Application Module Methods from EJB and MDB. Recently I learned that when a non web client invokes methods defined in EJB or MDB that uses Application Module, it may results in some unexpectedClassCastException for DefLocaleContext. The error stack may look like as listed below.
Caused by: java.lang.ClassCastException: oracle.jbo.common.DefLocaleContext cannot be cast to oracle.jbo.common.DefLocaleContext at oracle.jbo.common.DefLocaleContext.getInstance(DefLocaleContext.java:84)

The reason is that the current request gets the ADFContext cached by the previous thread. As these threads may have different class loaders, casting class loaded by one loader to the otherresultin weird ClassCastException. This post contains a solution for such cases. Here you go...

1. If you are accessing EJB(such as a SessionBean) from a web UI, then configureServletADFFilterin web.xml to intercept all the requests that access EJB using ADF BC. The ServletADFFilter sets up
ServletADFContextproperly at the start of the request so that ADF BC can access the right context object during execution. If you use ADF binding, then this step is not required because the ADFBindingFilter configured in web.xml does the same job oninitializingADFContext.

<filter>

<filter-name>ServletADFFilter</filter-name>

<filter-class>oracle.adf.share.http.ServletADFFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>ServletADFFilter</filter-name>

<url-pattern>/*</url-pattern>

<dispatcher>REQUEST</dispatcher>

<dispatcher>FORWARD</dispatcher>

</filter-mapping>


2. If you are invoking EJB in non web UI context, then you will not have the luxury of using Servlet filter for initializing the context. For example calling EJB methods from a desktop client or from somebatchprogram. In such cases you may need to manually initialize the ADF context. A possible solution is to define an interceptor class for the EJB session bean and add the ADFContext initialization code in the AroundInvoke method in theinterceptorclass.

An example of usinginterceptorwith EJB is here:
Define the interceptor as shown below:

publicclassADFContextInterceptor{

publicADFContextInterceptor(){

super();

}

@AroundInvoke

public Object manageADFContext(InvocationContext ctx)throws Exception {

ADFContext currentADFContext =null;

try{

System.out.println(" - manageADFContext - entry ");

currentADFContext =

ADFContext.initADFContext(null,null,null,null);

return ctx.proceed();

}finally{

System.out.println(" - manageADFContext - exit ");

ADFContext.resetADFContext(currentADFContext);

}

}

}

Now configure your Session Bean to use this interceptor as shown in the following example so that all methodinvocationswill be routed through your interceptor code.

@Stateless(name = "DemoSessionEJB",

mappedName = "EJBWithADFBCApp-EJBModel-DemoSessionEJB")

@Interceptors(value = ADFContextInterceptor.class)

publicclassDemoSessionEJBBeanimplements DemoSessionEJB,

DemoSessionEJBLocal {

//... implementation go here...

}


3. If the technology that you use do not support any interceptors around method invocation as discussed above, then you can try adding the ADFContext handling code before and after of your custom code that access AM method as listed below:

publicvoidsomeBusinessMethod()throws Exception {

ADFContext currentADFContext =null;

try{

currentADFContext =

ADFContext.initADFContext(null,null,null,null);

//Your code that access AM and doing business some

//actions go here

}finally{

ADFContext.resetADFContext(currentADFContext);

}

}


Note
In case if you see the following warning in the console while accessing application module from aclient bypassing ADF binding layer, the above solution will help you to get rid of it

WARNING: Automatically initializing a DefaultContext for getCurrent.
Caller should ensure that a DefaultContext is proper for this use.

Memory leaks and/or unexpected behaviour may occur if the automatic initialization is performed improperly.

Download


You can
download the sample workspace from here. [Runs with Oracle JDeveloper 11g R1 11.1.1.7.0 + Oracle XE].
See the EJBModel project which uses theinterceptorapproach discussed in this post in order to initialize ADFContext object.


A note of thanks

Many thanks to my colleague Ricky Frost (Oracle ADF Team) who pointed out a weird logical error in my code while resetting ADF context at the end of invocation. He mentioned that ADFContext.resetADFContext() should be called unconditionally at the end of the method. I corrected the same in my code without asking any questions as Ricky knows these things much better than me :)

你可能感兴趣的:(application)