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

Reply via email to