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

Martin Grigorov commented on WICKET-3737:
-----------------------------------------

Yes, trunk is 1.5.

I hope you know about the OSGi related problem in Wicket 1.5: wicket.jar has 
been split in wicket-util.jar, wicket-request.jar and wicket-core.jar. These 
jars have packages with the same names and OSGi containers don't like this. 
Thus 
https://github.com/wicketstuff/core/tree/master/jdk-1.5-parent/wicket-bundle-parent
 has been created by Eike Kettner. Its purpose it to merge these three jars 
back into one with proper OSGi MANIFEST.MF.

> Remove DynamicImport-Package header from Wicket bundles
> -------------------------------------------------------
>
>                 Key: WICKET-3737
>                 URL: https://issues.apache.org/jira/browse/WICKET-3737
>             Project: Wicket
>          Issue Type: Improvement
>          Components: wicket-core
>    Affects Versions: 1.4.17
>            Reporter: Daniël van 't Ooster
>            Assignee: Igor Vaynberg
>              Labels: osgi
>         Attachments: classloading.patch
>
>
> Hi,
> Wicket can be used in an OSGi container, out of the box it seems to work 
> quite well. However, we experience some problems because of having multiple 
> bundles which depend on Wicket.
> Problem: bundle refreshes caused by DynamicImport-Package
> All Wicket bundles have a DynamicImport-Package: * entry in their manifests. 
> This makes class loading easy, because the class loaders of the Wicket 
> bundles have access to any exported packages from all bundles. This approach 
> has one drawback; the Wicket bundles become implicitly dependent of all 
> bundles which are used at least one time by a Wicket class loader. According 
> to the OSGi specification, when a bundle is refreshed, all bundles which 
> (explicitly or implicitly) depend on that bundle will also be refreshed. 
> Example case: there is an OSGi container with some Wicket bundles loaded, and 
> 2 bundles (bundleA and bundleB), both contain some Wicket components, so they 
> import Wicket packages, they do not import packages from each other. Now we 
> refresh BundleA, we expect only a refresh of only bundleA. In practice all 
> Wicket bundles, bundleA and bundleB are refreshed. This is caused by the 
> DynamicImport-Package, which makes the Wicket bundles implicitly import 
> exported packages from bundleA and bundleB. When bundleA is refreshed, it 
> will refresh also the Wicket bundles. Because of bundleB depends on Wicket, 
> bundleB will also be refreshed. In a small project with a few bundles, this 
> may not be a problem, but it can become a problem when the projects gets 
> larger and you refresh bundles frequently (e.g. when using an OSGi container 
> during development).
> Solution: delegate class loading to another bundle
> While deserializing components, Wicket uses its IClassResolver implementation 
> to load the classes. The DefaultClassResolver uses the thread's context class 
> loader (TCCL) and the classloader of the wicket core bundle (with the 
> DynamicImport-Package). My idea is to remove the DynamicImport-Package header 
> from all Wicket bundles and delegate class loading to another bundle. This 
> bundle exports its OsgiClassResolver (implements IClassResolver) via the OSGi 
> service registry (or a service and reference of Spring DM / Blueprint). This 
> bundle will refresh when bundleA or bundleB is refreshed. Because of there 
> are no bundles which depend on classes from the classResolver bundle, a 
> refresh will not refresh other bundles and will be fast.
> Issues: A few class loading issues
> There are a few spots where we experienced class loading issues. One of the 
> problems is a missing implementation of resolveProxyClass in 
> ObjectInputStream subclasses. Some work is done to solve class loading 
> issues, e.g. by overriding the resolveClass method, but this works for normal 
> classes, proxy classes are handled differently. This is a problem on 2 
> locations in org.apache.wicket.util.lang.Objects and in 
> org.apache.wicket.util.io.IObjectStreamFactory. Last known issue is in 
> org.apache.wicket.proxy.LazyInitProxyFactory (wicket-ioc), but this one is 
> more complicated. To be able to create a new proxy instance, it needs a 
> classLoader, which can access all interfaces used for the proxy. In a bundle 
> with a DynamicImport, it is safe to pass the classloader of any class in that 
> bundle, but when the DynamicImport-Package is removed, not all classes are 
> visible, and it will throw an exception when one of the classes is not 
> visible. To solve this, I had to extend the IClassResolver interface with one 
> method: getClassLoader(); this classLoader is used when generating the proxy.
> So summarized, the complete solution (based on Spring Dynamic Modules) looks 
> like:
> // applicationContext.xml:
> ...
> <osgi:reference id="classResolver" 
> interface="org.apache.wicket.application.IClassResolver" />
> ...
> <bean id="wicketApplication" class="com.company.WicketApplication"
>       p:classResolver-ref="classResolver"
>       ...
> />
> ...
> // set up application
> public class WicketApplication extends Application {
>   private IClassResolver classResolver;
>   public void setClassResolver(IClassResolver classResolver) {
>     this.classResolver = classResolver;
>   }
>   @Override
>   public void init() {
>     super.init();
>     IApplicationSettings settings = getApplicationSettings();
>     settings.setClassResolver(this.classResolver);
>   }
> }
> // ClassResolver bundle:
> <bean id="classResolver" class="com.company.osgi.OSGiClassResolver" />
> <osgi:service ref="classResolver">
>   <osgi:interfaces>
>     <value>org.apache.wicket.application.IClassResolver</value>
>   </osgi:interfaces>
> </osgi:service>
> public class OSGiClassResolver extends 
> org.apache.wicket.application.DefaultClassResolver {
>   @Override
>   public ClassLoader getClassLoader() {
>     return OSGiClassResolver.class.getClassLoader();
>   }
> }
> What do you think about this approach? Attached patch is created based on 
> 1.4.10, seems to be compatible with versions up to 1.4.16. 
> best regards,
> Daniël

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to