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

本文介绍了如何通过配置ServletADFFilter、定义自定义拦截器或手动初始化ADFContext来解决非web客户端调用EJB时出现的ClassCastException问题。提供了示例代码帮助开发者实现解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 :)

 

当您尝试通过Java Web服务调用SOAP(Simple Object Access Protocol)时,遇到`java.util.ConcurrentModificationException`通常意味着在并发修改一个集合(如ArrayList或LinkedList)时,集合内部的结构被其他线程意外地更改了。在处理Web服务请求时,如果代码中存在这样的异常,可能是以下几个原因: 1. **并发安全问题**:如果在遍历或操作集合的同时,集合本身正在被其他线程更新(比如添加或删除元素),这会导致并发修改异常。 2. **未正确同步**:可能是在多线程环境中,对集合的操作没有使用适当的同步机制,如synchronized块或`java.util.concurrent`包下的工具。 3. **循环引用**:在处理复杂的数据结构时,如果没有正确管理引用,可能导致死锁或内存泄漏,从而间接引发此异常。 4. **代码逻辑错误**:可能在编写处理Web服务响应的代码时,无意中对集合进行了修改。 为了解决这个问题,您可以采取以下措施: - **检查并修复并发代码**:确保在修改集合时,其他线程不会同时访问它。 - **使用`Collections.synchronizedList`或`CopyOnWriteArrayList`**:这些集合类可以提供线程安全的遍历或操作。 - **确保资源清理**:在结束对集合的操作之前,确保所有的引用都被适当地释放。 - **审查日志和堆栈跟踪**:找出引发异常的具体代码位置,以便定位和修复问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值