[
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]