How to get classloader for a bundle in equinox? - eclipse

I have read a lot of equinox code for this, but still can't figure out a non-hacky way of getting the classloader for a osgi bundle in eclipse equinox setup. Is there one?

In OSGi 4.3 you can use:
bundle.adapt(BundleWiring.class).getClassLoader()

The short answer (certainly for OSGi 4.1, not sure of 4.2) is you can't get a bundle's classloader. However the Bundle interface exposes a loadClass() method and this would allow you to write a classloader that wraps the bundle API and delegates to that loadClass() method. Or you can save some time and use Spring DM's BundleDelegatingClassLoader class instead.

The class loader of a bundle can be obtained through the BundleWiring interface. Here a short example:
Bundle bundle = bundleContext.getBundle();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
ClassLoader classLoader = bundleWiring.getClassLoader();

In normal java code, you can get the class loader that loaded a given object with
object.getClass().getClassLoader();
Or even just
SomeType.class.getClassLoader();
The same applies to Equinox, just use an object or type that comes from the bundle you are interested in.

Related

Fragment bundle is not getting activated

I have Two osgi bundles Bundle A and Bundle B. Bundle B is a fragment bundle of bundle A. When both components are in the osgi environment, Bundle A is in ACTIVE state but Bundle B is in RESOLVED state and it is not getting activated. Bundle B gets activated if I remove the <Fragment-Host> header.
Is there any specific way I have to define the fragment bundle? (other than adding the <Fragment-Host>? maybe add any annotations, etc)? . If there any sample resource I could use, please let me know
I'm using org.eclipse.osgi_3.11.0.v20160603-1336. Sample bundle can be found in https://github.com/chamilaadhi/sample-bundles
Thanks
Seems like the fragment bundles do not get to ACTIVE state[1][2]. Also found similar discussion related to this in Component inside a fragment never activated
[1] https://osgi.org/specification/osgi.core/7.0.0/framework.module.html#framework.module.fragmentbundles
[2]https://dzone.com/articles/osgi-fragment-bundles-dont

Accessing E4PartWrapper's MPart in Eclipse 3.x RCP application

I am using the ability to add an Eclipse 4.x part to an Eclipse 3.x RCP application's perspective as described in the Vogella chapter on RCP migration. All is well, I can create an 4.x part and view it in a 3.x perspective.
I'd like to access the instantiated 4.x POJO (in my case it contains a Browser widget) and set some parameters for display (the browser URL). However when I try to probe the constructed ViewPart what I have to deal with is an E4PartWrapper object:
E4PartWrapper newPart =
window.getActivePage().
showView(ViewEclipse4x.ID,
String.valueOf(nextId),
IWorkbenchPage.VIEW_ACTIVATE);
I can see from the code that E4PartWrapper does contain the wrapped part, but I don't see a way to access this object.
Is there an alternative to accessing the 4.x POJO underlying the constructed 3.x ViewPart?
Thank you.
Carlos S. Zamudio
Sorry. I can see the MPart can be found using the PartService:
EPartService partService = (EPartService) viewSite.getService(EPartService.class);
MPart part = partService.findPart(partName);

How to open any eclipse Wizard from Intro Page in eclipse plugin development

I use HTML file for my welcome page. I want to open Eclipse Wizard from intro page using
href="http://org.eclipse.ui.intro/runAction?pluginId=MobileTalk&class=mobiletalk.intro.ShowPerspectiveIntroAction"
In the class ShowPerspectiveIntroAction, my code as follows:
Class c = Class.forName("tttt.ddt.plugin.project.NewTtttProjectWizard");
Wizard wizard = (Wizard) c.newInstance();
WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),wizard);
dialog.open();
But I get the error: classnotfound:tttt.ddt.plugin.project.NewTtttProjectWizard
how can I open any Eclipse Wizard from intro page correctly?
From looking at your code I suspect it is a class loader issue. Using Class.forName is not a safe practice in Eclipse/OSGI because each plugin/bundle uses their own class loader and as a result a lot of times Class Not Found Exceptions happen. A better approach is to get the Bundle/Plugin that contains your wizard class by doing this: Platform.getBundle("com.stackoverflow.myplugindId"), that returns an instance of Bundle. Then on the instance of bundle call the .loadClass("tttt.ddt.plugin.project.NewTtttProjectWizard") which will use the correct class loader and then once you have an instance of the Class you can call the newInstance() method which will resolve your Class not found issue. Hope that helps, class loading is more complex in an OSGI environment because every plugin has its own class loader for security reasons so I advise against using Class.forName in your code. - Duncan

How to resolve java.lang.ClassCastException :

I'm using some third party jar file, there are plenty of Jar files as well, and I have the code written by someone else.
While executing, I'm geting this error:
java.lang.ClassCastException : org.apache.axis.client.Service cannot be cast to org.apache.axis.client.Service
Can you suggest me what could be the problem?
Thanks for the reply.
But before getting this error, I was getting:
java.lang.LinkageError : loader constraint violation: when resolving method "org.onvif.www.ver10.device.wsdl.DeviceBindingStub.(Ljava/net/URL;Ljavax/xml/rpc/Service;)V" the class loader (instance of org/apache/catalina/loader/WebappClassLoader) of the current class, com/abcd/efgh/ijkl/device/onvif/DeviceHandlerClient, and the class loader (instance of org/apache/catalina/loader/StandardClassLoader) for resolved class, org/onvif/www/ver10/device/wsdl/DeviceBindingStub, have different Class objects for the type javax/xml/rpc/Service used in the signature.
The problem has not resolved yet. I'm not getting where the version mismatch of files/jar is happening from. I have included some Jars manually.
You likely have the Service class being sourced from two different class loaders. A classes identity is a combination of its name and the class loader that loaded the class.
As a contrived example, you could have two web apps deployed in something like Tomcat. They each have a copy of the same jar, and each loads their own instance of a class. Since they're in separate WARs, however, they each have different class loaders.
Next, lets say that you have something global, like a caching library or something. This caching module has its jar not within an individual WAR, but on the system class path for the container, that way it's visible to both WARs.
Web app 1 stores an instance of the class in to the cache, and then web app 2 tries to load that instance and cast it to its local version of the class. But since it's from the other web app, it has a different class loader than web app 2's. Thus when it's trying to cast the instance, it fails because it's not web app 2's version of that class.
So, basically, you have some kind of class loader confusion happening here. Make sure you have a clear understanding of what jars you're using, ensuring that there aren't any unnecessary duplications, and what context is loading what classes.

GWT with JPA

I'm trying to build database application using GWT 1.5.3. I use JPA annotations with my objects. It seems in hosted mode GWT's RPC works fine. But when I try to compile my app using GWT-compiler I get errors like: "The import javax.persistence cannot be resolved", "Entity cannot be resolved to a type". toplink-essentials.jar is already included in my project path. What settings else do I need to solve this problem?
You can use Gilead (http://sourceforge.net/projects/gilead/) library to seamlessly manage JPA entities with GWT.
Regards
You need to include the source code for the JPA annotations in the build path for your GWT project. See here for more details:
http://code.google.com/p/google-web-toolkit/issues/detail?id=1830&can=1&q=jpa
Specifically this jar file which will fix your problem:
http://google-web-toolkit.googlecode.com/issues/attachment?aid=1475633892125294312&name=jpa-annotations-source.jar
The general problem of the JPA and GWT is that GWT itself doesn't support fancy JPA classes, so you just do simple POJO persistent entities DTO that implements the java.io.Serializable and have simple JPA resource annotations. You need to create the entity classes in the scope of the GWT client either have it under the yourproject.client package or add them with
source path="client"
source path="folderOfYourEntities"
in the GWT project's YouProject.gwt.xml file. This will include the entity objects in the GWT client so they can used them on client side of the RPC as well. The DAO must be on the server side and can contain anything that you container supports.
The problem you have now is that when compiling, GWT compiler saids that it desn't know what those imports for JPA annonations are in the entity DTO classes. That is why you need the javax.persistence class and source codes. The jpa-annotation-source.jar reference by Rustmyself works. It is just the javax.persistence compiled class files and source codes files plus a Persistence.gwt.xml. It is a simple GWT module for the javax.persistence package. If you know how to make your own GWT module, you should have problem making all this work. By the way, the official source for the Java EE can be found on the glassfish dev site's build section wiki.glassfish.java.net
There are many other solutions that wrap your fancy PU entities to simple objects automatically using proxy or to lazy load them at run time. They work, but not optimal solutions. The best practice is to make things simple and robust from the start by having POJO JPA DTO entities on the GWT client context and full blown DAO on the server.
GWTPersistence Example
I have added an actual working example on how to make GWT and JPA work seamlessly. It is a NetBean project with source codes and deployment file. See GWTPersistence on NingZhang.info
Ok, I've found what I was missing. I needed to include jpa-annotations-source.jar in my GWT-compiler path in myapp-compile.cmd script (or in ant build file). By the way can anyone tell me the origin of this jpa-annotations-source.jar file?
I am also working with JPA <--> GWT data transformation etc.
In an effort to eliminate the DTO layer I used Gilead too.
My objection here is about translating javax.persistence. To avoid this I used XML JPA mapping declarations (orm.xml)
Simply, keep another version of your Entities but without the annotations!
Rebounding on synergetic's comment, you now (from GWT 1.5) only need to add
<source path='javax.persistence'/>
to your Module.gwt.xml