[ 
https://issues.apache.org/jira/browse/AXIS2-5792?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15349525#comment-15349525
 ] 

Andreas Veithen commented on AXIS2-5792:
----------------------------------------

Can you provide a test project to reproduce the problem?

> Add a more strict service first class loader?
> ---------------------------------------------
>
>                 Key: AXIS2-5792
>                 URL: https://issues.apache.org/jira/browse/AXIS2-5792
>             Project: Axis2
>          Issue Type: Improvement
>          Components: deployment
>    Affects Versions: 1.6.3, 1.7.3
>         Environment: Windows 8.1 x64 Prof., Tomcat 7.0.68, JDK 1.8.0_92 x64
>            Reporter: Thorsten Schöning
>
> I have a web service based on Axis2 1.6.3 currently and Axis2 provides 
> httpcore-4.0. In my service I want to use HttpCore 4.4.5 and HttpClient 4.5.2 
> and both core packages provide the class BasicLineFormatter, but some classes 
> new in HttpCore 4.4.5 need a newer version of that class than HttpCore 4.0 
> can provide. This leads to exceptions like the following:
> {CODE}
> Caused by: java.lang.NoSuchFieldError: INSTANCE
>       at 
> org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:53)
>       at 
> org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:57)
>       at 
> org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(DefaultHttpRequestWriterFactory.java:47)
>       at 
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:82)
>       at 
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:95)
>       at 
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:104)
>       at 
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<clinit>(ManagedHttpClientConnectionFactory.java:62)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:572)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:174)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:158)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:149)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:125)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:116)
> {CODE}
> {CODE}
> Caused by: java.lang.NoClassDefFoundError: Could not initialize class 
> org.apache.http.impl.conn.ManagedHttpClientConnectionFactory
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:572)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:174)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:158)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:149)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:125)
>       at 
> org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:116)
> {CODE}
> The problem is that when my service is about to be started, Axis2 used the 
> BasicLineFormatter (indirectly) on its own already, loaded it and 
> DeploymentClassLoader.loadClass finds that class in its own cache afterwards. 
> This way the newer version of that class bundled with my service will never 
> be used by default. Because the class is in the cache, using 
> "EnableChildFirstClassLoading" doesn't change a thing here because the cache 
> is always queried first.
> I could work around that problem by changing the class loader of my service 
> in ServiceLifeCycle.startUp: The new class loader is just another instance of 
> DeploymentClassLoader which I put all the URLs needed for Jars and classes 
> and such into, use "EnableChildFirstClassLoading" by default and provide the 
> already available class loader as the new parent:
> {CODE}
> class WsAxis2SvcCl extends DeploymentClassLoader
> [...]
>       private static boolean shouldWrap(AxisService service)
>       {
>               String  paramValue = (String) 
> service.getParameterValue("EnableSvcFirstClassLoading");
>                               paramValue = 
> StringUtils.defaultIfBlank(paramValue, "false");
>               if (!JavaUtils.isTrueExplicitly(paramValue.trim()))
>               {
>                       return false;
>               }
>               return true;
>       }
> [...]
>       protected WsAxis2SvcCl( Set<URL>        urls,
>                                                       ClassLoader     parent)
>       {
>               super(urls.toArray(new URL[urls.size()]), null, parent, true);
>       }
> [...]
>       static void wrapIf(AxisService service)
>       {
>               if (!WsAxis2SvcCl.shouldWrap(service))
>               {
>                       return;
>               }
>               ClassLoader     origCl  = service.getClassLoader();
>               Path            svcDir  = Axis2ServiceConf.getSvcDir(service);
>               Set<URL>        clUrls  = 
> ClNdClassLoaderUrlsProv.getUrlsRe(svcDir.toFile());
>               ClassLoader     newCl   = new WsAxis2SvcCl(clUrls, origCl);
>               service.setClassLoader(newCl);
>       }
> {CODE}
> This way the classes and jars of my service are always considered first and 
> only things not found in there are forwarded to the default Axis2 class 
> loader used before. In the end, my classes using HttpCore 4.4.5 get their 
> BasicLineFormatter and Axis2 keeps using its own. The "trick" is that 
> DeploymentClassLoader.findLoadedClass only searches the current instance, no 
> parent or such, and by providing a new instance I get a clean start for 
> loading the service classes without interfering with the former already 
> present Axis2 loader.
> As I understand DeploymentClassLoader, such problems can't be addressed 
> without another classloader like mine, so I woudl like to suggest exactly 
> such an approach like I implemented now to be added. As I did already, one 
> could configure the use of that class loader on a per service level and would 
> therefore don't introduce any problems with backwards compatibility. If 
> interested, I could provide more of my implementation.
> Or is there any other approach I have missed to deal with same classes in 
> incompatible versions like in my case?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to