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 about Calling 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 unexpected ClassCastException  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 other result in 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 configureServletADFFilter in web.xml to intercept all the requests that access EJB using ADF BC. The ServletADFFilter sets up
 ServletADFContext properly 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 on initializing ADFContext. 

<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 some batch program. 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 the interceptor class.

An example of using interceptor with 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 method invocations will 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 the interceptor approach 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 :)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值