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 <[email protected]> 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 <[email protected]>
> 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
_______________________________________________
Dev mailing list
[email protected]
http://wso2.org/cgi-bin/mailman/listinfo/dev

Reply via email to