Hi Sagara, KasunG,

Will this approach work?

Lets have a parent classloader for WebAppClassLoader.

We will load the BlockingService using parent classloader.

*obj* will be loaded by WebAppClassLoader.

Since its parent knows about BlockingService, we will be able to cast.

Is this possible to have a meeting today to sort out this issue?

Thanks.


On Mon, Jun 2, 2014 at 7:29 PM, Rajkumar Rajaratnam <rajkum...@wso2.com>
wrote:

> Hi,
>
> According to our offline discussion, we are trying to achieve this
> casting.
>
> BlockingService blockingService= (BlockingService) *obj*;
>
> But, at the end of the day, we are going to call the following method
> which is defined in our BinaryServiceRegistry.
>
> registerService(BlockingService blockingService)
>
> Here, BlockingService is already loaded by a classloader (
> org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@31887be4
> [com.google.protobuf:2.5.0(id=30)])
>
> Hence, registerService() method will only accept a BlockingService
> instance which is loaded by the same classloader as above.
>
> So what we should do is to load the *obj* in the same classloader as
> above. Otherwise we will not be able to register this *obj* in our
> BinaryServiceRegistry.
>
> But we were not able to do so. Because, this *obj* is already loaded by
> the WebAppClassLoader.
>
> I tried casting with transloader[1]. Its Reflection cloning is failing.
> And we can't use its Serialization cloning because our auto-generated stubs
> are not serializable.
>
> Any ideas?
>
> 1. https://code.google.com/p/transloader/
>
> Thanks.
>
>
>
> On Sun, Jun 1, 2014 at 2:35 PM, Kasun Gajasinghe <kas...@wso2.com> wrote:
>
>> Hi Rajkumar,
>>
>> You can get the webapp classloader instance via ServletContext [1]. Then
>> you could temporarily set the current thread context classloader just for
>> the casting operation [2]. After that, set it back to the previous
>> classloader. There might be better ways to do this though!
>>
>>
>> [1]
>> http://docs.oracle.com/javaee/6/api/javax/servlet/ServletContext.html#getClassLoader()
>> [2]
>> http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#setContextClassLoader(java.lang.ClassLoader)
>>
>> Regards,
>> KasunG
>>
>>
>>
>> On Sun, Jun 1, 2014 at 11:37 AM, Rajkumar Rajaratnam <rajkum...@wso2.com>
>> wrote:
>>
>>> Hi all,
>>>
>>> We are writing our own Servlet Context Initializer for new
>>> ProtoBufServices (Binary Services). We have deployed a  ProtoBufService
>>> (HelloService). When ServletContainerInitializer finds the annotation
>>> "@ProtoBufService", the onStartup() method is triggered. Everything works
>>> fine except one thing which is explained here.
>>>
>>>
>>> @HandlesTypes({ ProtoBufService.class })
>>> public class ProtoBufServletContextInitializer implements
>>> ServletContainerInitializer {
>>>
>>>     @Override
>>>     public void onStartup(Set<Class<?>> classes, ServletContext
>>> servletContext)
>>>
>>>
>>> throws ServletException {
>>>
>>>         if (classes == null || classes.size() == 0) {
>>>             return;
>>>         }
>>>
>>>         for (Class<?> clazz : classes) {
>>>
>>>                 Method myMethod=null;
>>>                 try {
>>>                     myMethod =
>>> clazz.getInterfaces()[0].getDeclaringClass().getMethod("newReflectiveBlockingService",
>>> clazz.getInterfaces()[0]);
>>>                 } catch (NoSuchMethodException | SecurityException e) {
>>>                     e.printStackTrace();
>>>                 }
>>>
>>>
>>>                 // get newReflectiveBlockingService() will return a
>>> BlockingService object.
>>>                 Object blockingServiceObj=null;
>>>                 try {
>>>                     blockingServiceObj = myMethod.invoke(null,
>>> clazz.newInstance());
>>>                 } catch (IllegalAccessException |
>>> IllegalArgumentException
>>>                         | InvocationTargetException |
>>> InstantiationException e) {
>>>                     e.printStackTrace();
>>>                 }
>>>
>>>
>>>                 BlockingService blockingService = (BlockingService)
>>> blockingServiceObj;
>>>                 /*
>>>                  * Casting throws ClassCastException.
>>>                  */
>>>
>>>
>>>
>>> System.out.println(blockingServiceObj.getClass().getClassLoader());
>>>                 /*
>>>                  * Output :
>>>                  *
>>>                  * WebappClassLoader
>>>                           context: /org.wso2.carbon.binary.sample.hello
>>>                           delegate: false
>>>                           repositories:
>>>                             /WEB-INF/classes/
>>>                         ----------> Parent Classloader:
>>> org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@5db01ad1
>>>
>>>
>>> [org.wso2.carbon.tomcat.patch:4.3.0.SNAPSHOT(id=365)]
>>>                  */
>>>
>>>
>>>
>>>
>>> System.out.println(BlockingService.class.getClassLoader());
>>>
>>>                 /*
>>>                  * Output :
>>>                  *
>>>                  *
>>> org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@31887be4
>>> [com.google.protobuf:2.5.0(id=30)]
>>>                  */
>>>
>>>         }
>>>     }
>>>
>>> }
>>>
>>>
>>> Now,
>>>
>>> BlockingService blockingService= (BlockingService) obj;
>>>
>>> throws following ClassCastExecption,
>>>
>>> java.lang.ClassCastException:
>>> org.wso2.carbon.binary.sample.Hello$HelloService$2 cannot be cast to
>>> com.google.protobuf.BlockingService
>>>
>>>
>>> But, HelloService  is type of BlockingService.
>>>
>>> *Reason for this error.*
>>>
>>> BlockingService is coming from an OSGi bundle (protobuf) and it is
>>> loaded by a classloader,
>>> org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@31887be4
>>> [com.google.protobuf:2.5.0(id=30)]
>>>
>>> obj is obtained at run time within servlet context initializer and it is
>>> loaded by another classloader,
>>> WebappClassLoader
>>>                           context: /org.wso2.carbon.binary.sample.hello
>>>                           delegate: false
>>>                           repositories:
>>>                             /WEB-INF/classes/
>>>                         ----------> Parent Classloader:
>>> org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader@5db01ad1
>>>
>>>
>>> [org.wso2.carbon.tomcat.patch:4.3.0.SNAPSHOT(id=365)]
>>>
>>>
>>> Even though obj and BlockingService are of same type, they cannot be
>>> cast because they are loaded by different class loaders.
>>>
>>> How can I solve this problem?
>>>
>>> Is there any way we can load protobuf OSGi using the same classloader as
>>> servlet context initializer?
>>>
>>> Thanks.
>>>
>>>
>>> --
>>> Rajkumar Rajaratnam
>>> Software Engineer | WSO2, Inc.
>>> Mobile +94777568639 | +94783498120
>>>
>>
>>
>>
>> --
>>
>> *Kasun Gajasinghe*Senior Software Engineer, WSO2 Inc.
>> email: kasung AT spamfree wso2.com
>> linked-in: http://lk.linkedin.com/in/gajasinghe
>> blog: http://kasunbg.org
>>
>>
>>
>
>
>
> --
> Rajkumar Rajaratnam
> Software Engineer | WSO2, Inc.
> Mobile +94777568639 | +94783498120
>



-- 
Rajkumar Rajaratnam
Software Engineer | WSO2, Inc.
Mobile +94777568639 | +94783498120
_______________________________________________
Dev mailing list
Dev@wso2.org
http://wso2.org/cgi-bin/mailman/listinfo/dev

Reply via email to