Context :
Eclipse RCP project, divided into plugins, each one devoted to a task (eg : HMI management, communications, ...)
Necessity to persist some data in a database
- ORM : hibernate's JPA (JPA 2.1, Hibernate 5.2.1 used throught an org.hibernate.core plugin as constructed [here (page 8)][1]
- database : in mysql
- constraint : Java SE environment, so the only way to obtain an EntityManager (for the persistence operations) is to create it through an EntityManagerFactory
First step (that works!) :
Plugin that manages the database operations, its structure :
com.plugin.name
JRE System Library
Plug-in Dependencies
Referenced Libraries (contains the mysql connector jar)
src/
com.plugin.name (package containing the plugin activator)
com.plugin.name.entities (package containing all my entities)
com.plugin.name.utils (package containing my access functions and a main)
META-INF/
persistence.xml
META-INF/
MANIFEST.MF
In com.plugin.name.utils I have my classes performing all the persistence functions.
In these classes, I create an EntityManagerFactory this way :
private static final EntityManagerFactory ENTITY_MANAGER_FACTORY = Persistence.createEntityManagerFactory("com.plugin.name");
where "com.plugin.name" is the persistence unit name defined in my persistence.xml
In one of those classes, I have a main running some database-related functions.
When I run this main as java application, everything works fine.
(to prevent future questions : my persistence.xml file was originally generated in the MANIFEST.MF META-INF folder but when running this main, it couldn't be found, so I moved it. I checked both configurations when calling the persistence functions from another plugin)
The problem :
I need to access my persistence functions from another plugin, let's call him com.plugin.other
So I added com.plugin.name as a dependency of this plugin.
But when I try to run the application, I get the following error :
javax.persistence.PersistenceException: No Persistence provider for EntityManager named com.plugin.name
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
When i run the main as standalone application, if there's any problem with the persistence.xml file (not found, incomplete, etc) it gets at least mentionned... Here I'm really stuck with no clue to understand where the problem comes from.
I finally made it without the persistence.xml by using the createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) method in the PersistenceProvider.
Code :
Activator a = Activator.getDefault();
Bundle b = a.getBundle();
URL url = b.getResource("META-INF/persistence.xml");
List<PersistenceProvider> providers = PersistenceProviderResolverHolder.getPersistenceProviderResolver().getPersistenceProviders();
for (PersistenceProvider pp : providers) {
PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl();
pui.setPersistenceUnitName("persistenceUnitName");
pui.setTransactionType(PersistenceUnitTransactionType.RESOURCE_LOCAL);
pui.setPersistenceUnitRootUrl(url);
Properties prop = pui.getProperties();
if (prop == null) {
prop = new Properties();
}
prop.setProperty("javax.persistence.jdbc.url", "jdbc:mysql://ip:port/dbName");
prop.setProperty("javax.persistence.jdbc.user", "dbUser");
prop.setProperty("javax.persistence.jdbc.password", "dbPass");
prop.setProperty("javax.persistence.jdbc.driver", "com.mysql.jdbc.Driver");
pui.setProperties(prop);
pui.setClassLoader(com.mysql.jdbc.Driver.class.getClassLoader());
emFactory = pp.createContainerEntityManagerFactory(pui, null);
}
}
Related
I fail to configure a project based on Spring Boot, extended with OSGI, and using Jackson in a bundle
by using import/export package system (I would like to avoid to embed the lib).
I started from this project.
Maven modules:
a Spring Boot module, the main app, initialized with Felix, like the referenced project above
a bundle module, where I want to use ObjectMapper on activation like this
#Activate
public void activate() {
ObjectMapper objectMapper = new ObjectMapper();
}
But on activation I got the following error:
NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper
Yet, I had exported this package from the main app bundle (Spring Boot) and imported it in the bundle module.
This bundle module use maven-bundle-plugin (while the main app use nothing specific):
<instructions>
<_dsannotations>*</_dsannotations>
<_metatypeannotations>*</_metatypeannotations>
<Bundle-Vendor>Foo</Bundle-Vendor>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Service>
com.foo.bar.plugin.RestTaskPlugin
</Export-Service>
<Export-Package>
com.foo.bar.plugin.rest,
com.foo.bar.plugin.rest.web,
com.foo.bar.plugin.rest.config
</Export-Package>
<Import-Package>*;resolution:=optional</Import-Package>
<Embed-Dependency>*;scope=compile|runtime; type=!pom; inline=true</Embed-Dependency>
<Embed-Transitive>false</Embed-Transitive>
</instructions>
I only embed logback-classic and logback-core in this bundle (this could be another story...). In other words, I only have these 2 dependencies declared in the module. I also tried to add databind in provided scope but it changes nothing.
I don't get it since I have exported all "com.fasterxml.jackson" packages and sub-packages. To do so, the Spring boot initialize the Felix framework with a custom configuration, with the config key org.osgi.framework.system.packages.extra containing all packages to export automatically according to
the documention.
When I log them we can see around 100 exported packages including these ones :
....
com.fasterxml.jackson.databind.deser.impl,
com.fasterxml.jackson.databind,
com.fasterxml.jackson.core.sym,
....
The module bundle using databind MANIFEST.MF :
Export-Package: com.foooooooo.baaaar.plugin.rest;uses:="com.foooooooo.d
atagen.api.plugins,com.foooooooo.baaaaar.api.plugins.properties,com.baa
aaaaar.datagen.api.plugins.web,com.foooooooo.baaaaar.plugin.rest.config
,com.foooooooo.baaaaar.plugin.rest.web,com.foooooooo.baaaaar.task,com.d
atanumia.baaaaar.task.config,com.foooooooo.baaaaar.task.environment,com
.foooooooo.baaaaar.task.template,org.springframework.http,org.springfra
mework.web.client";version="0.1.0.SNAPSHOT",com.foooooooo.baaaaar.plugi
n.rest.web;uses:="com.foooooooo.baaaaar.api.plugins,com.foooooooo.baaaa
ar.api.plugins.web";version="0.1.0.SNAPSHOT",com.foooooooo.baaaaar.plug
in.rest.config;uses:="com.foooooooo.baaaaar.task.config,com.fasterxml.j
ackson.annotation,com.fasterxml.jackson.databind.annotation,org.springf
ramework.http";version="0.1.0.SNAPSHOT"
Export-Service: com.foooooooo.baaaaar.plugin.RestTaskPlugin
Import-Package: com.foooooooo.baaaar.api.plugins;resolution:=optional,c
om.foooooooo.baaaaar.api.plugins.properties;resolution:=optional,com.da
tanumia.baaaaar.api.plugins.web;resolution:=optional,com.foooooooo.baaa
aar.task;resolution:=optional,com.foooooooo.baaaaar.task.config;resolut
ion:=optional,com.foooooooo.baaaaar.task.environment;resolution:=option
al,com.foooooooo.baaaaar.task.template;resolution:=optional,com.foooooo
al,com.foooooooo.baaaaar.task.template;resolution:=optional,com.foooooo
oo.baaaaar.tools.file;resolution:=optional,com.fasterxml.jackson.annota
tion;resolution:=optional;version="[2.13,3)",com.fasterxml.jackson.data
bind;resolution:=optional;version="[2.13,3)",com.fasterxml.jackson.data
bind.annotation;resolution:=optional;version="[2.13,3)",com.jayway.json
path;resolution:=optional;version="[2.7,3)",java.io;resolution:=optiona
l,java.lang;resolution:=optional,java.lang.annotation;resolution:=optio
nal,java.lang.invoke;resolution:=optional,java.lang.management;resoluti
on:=optional,java.lang.reflect;resolution:=optional,java.net;resolution
:=optional,java.nio.channels;resolution:=optional,java.nio.charset;reso
lution:=optional,java.nio.file;resolution:=optional,java.security;resol
ution:=optional,java.security.cert;resolution:=optional,java.text;resol
ution:=optional,java.util;resolution:=optional,java.util.concurrent;res
olution:=optional,java.util.concurrent.atomic;resolution:=optional,java
.util.concurrent.locks;resolution:=optional,java.util.function;resoluti
on:=optional,java.util.logging;resolution:=optional,java.util.regex;res
olution:=optional,java.util.stream;resolution:=optional,java.util.zip;r
esolution:=optional,javax.mail;resolution:=optional,javax.mail.internet
;resolution:=optional,javax.management;resolution:=optional,javax.namin
g;resolution:=optional,javax.net;resolution:=optional,javax.net.ssl;res
olution:=optional,javax.servlet;resolution:=optional,javax.servlet.http
;resolution:=optional,javax.xml.namespace;resolution:=optional,javax.xm
l.parsers;resolution:=optional,javax.xml.stream;resolution:=optional,ja
vax.xml.stream.events;resolution:=optional,lombok;resolution:=optional,
org.apache.commons.lang3;resolution:=optional;version="[3.12,4)",org.co
dehaus.commons.compiler;resolution:=optional,org.codehaus.janino;resolu
tion:=optional,org.springframework.http;resolution:=optional,org.spring
framework.http.converter.json;resolution:=optional,org.springframework.
util;resolution:=optional,org.springframework.web.client;resolution:=op
tional,org.springframework.web.util;resolution:=optional,org.xml.sax;re
solution:=optional,org.xml.sax.helpers;resolution:=optional,sun.reflect
;resolution:=optional
It is difficult to see but we have the expected import-package:
com.fasterxml.jackson.databind;resolution:=optional;version="[2.13,3)"
I do not have any other loaded bundle excepted the framework bundles:
org.apache.felix.fileinstall-3.7.4.jar
org.apache.felix.scr-2.2.0.jar
org.osgi.service.cm-1.6.1.jar
org.osgi.util.function-1.2.0.jar
org.osgi.util.promise-1.2.0.jar
I spend days to understand what is happening but each new tests bring me new unresolved challenges.
I can have a working project if I change strategy and embed everything, but then in some particular situations I have a linkage problem since I use the same lib in different class loaders.
How to use import/export package system correctly ?
Any idea about the problem here ?
UPDATE: the export-import seems to work with other packages. For example I can use spring-web in provided scope, it is not in the final bundle module, and I can use some methods of spring-web, exported from main app. The problem seems to be the Jackson Databind or something in related to it.
UPDATE
If I use bnd-maven-plugin I do not have the problem, I will post it unless someone give a better answer.
I have created a java program that uses Eclipse UML2 to load a .uml file and perform a model translation that (amongst other things) applies Papyrus Designer stereotypes (Codegen and C_Cpp profiles). Papyrus Designer can then be used to load the resulting model and generate cpp. I have successfully used the plugin jars as libraries in a standard java project, but I'm having problems transitioning to an Eclipse plugin project. The pertinent code is:
Profile codegenProfile = loadProfile(codegenProfileUri); // loads the profile resource from its plugin jar and returns the org.eclipse.uml2.uml.Profile
codegenProfile.define();
...
model.applyProfile(codegenProfile);
...
final Stereotype listHint = codegenProfile.getOwnedStereotype("ListHint");
model.applyStereotype(listHint);
// etc
I have to define() the profile to avoid an exception when applying the profile:
java.lang.IllegalArgumentException: profile "C_Cpp" has no Ecore definition
In my plugin version of the project I load the profile ok but get an exception when applying the stereotype:
java.lang.IllegalArgumentException: org.eclipse.uml2.uml.internal.impl.StereotypeImpl#540dcfba (name: ListHint, visibility: <unset>) (isLeaf: false, isAbstract: false, isFinalSpecialization: false) (isActive: false)
at org.eclipse.uml2.uml.internal.operations.ElementOperations.setValue(ElementOperations.java:667)
at org.eclipse.uml2.uml.internal.impl.ElementImpl.setValue(ElementImpl.java:307)
Looking at ElementOperations, the problem is in:
EObject eObject = element.getStereotypeApplication(stereotype);
if (eObject == null) {
throw new IllegalArgumentException(String.valueOf(stereotype));
}
which suggests the profile has not been properly initialised
I have been trying to understand a strange OSGI behavior. Hoping someone can shed some light on it. Here is my setup
1) Using eclipse\plugins\org.eclipse.osgi_3.7.0.v20110613.jar
2) I have a Bundle that exports a service (HelloworldService)
It registers the service in the activator as such
public void start(BundleContext context) throws Exception {
IHelloService helloService = new HelloServiceImpl();
helloServiceRegistration =context.registerService(
IHelloService.class.getName(), helloService, null
);
}
3) I have a 'consumer' bundle that uses the service via a ServiceTracker
ServiceReference externalServiceReference = Activator.getContext().getServiceReference(IHelloService.class.getName());
IHelloService externalService = (IHelloService) Activator.getContext().getService(externalServiceReference);
Now when I deploy both these jars to OSGI (helloworld.jar and helloworldservice.jar); it works fine. I am able to get a 'IHelloService' impl object and make calls on it. I can start/stop the bundles and when they come back; it works just fine
The problem happens when I 'uninstall' and then 'install' the HelloWorldservice bundle.
In that case; the 'Helloworld' consumer externalServiceReference is NULL.
If I view the bundle info; I see this
osgi> bundle 1
mypackage.helloworld_1.0.0.qualifier [1]
Id=1, Status=RESOLVED Data Root=C:\Users\\dev\eclipse\plugins\configuration\org.eclipse.obundles\1\data
No registered services.
No services in use.
No exported packages
Imported packages
mypackage.helloworldservice; version="0.0.0" **stale**
org.osgi.framework; version="1.6.0"
org.osgi.util.tracker; version="1.5.0"
No fragment bundles
Named class space
mypackage.helloworld; bundle-version="1.0.0.qualifier"[provided]
No required bundles
Notice that its 'imported packages' has GONE STALE. Here is the line in question
Imported packages
mypackage.helloworldservice; version="0.0.0"<stale>
Now I can fix this by issuing an 'update' command from the console.
Here is my question
1) How do I programatically do this from within my 'consumer' bundle..
2) If I am on a production system and I deploy a new 'copy' of the helloworlservice.jar (replacing the existing version); Do I have to update all its users.. I thought the ServiceTracker would give me the service on the fly
Thanks
The consumer bundle imports the mypackage.helloworldservice package from the service jar. When you uninstall the service jar, the consumer jar is still wired to the now stale package from the uninstalled service jar. When you install a new service jar, it exports a new "copy" of the mypackage.helloworldservice package (I suspect the service jar does not also import the mypackage.helloworldservice package). So you need to refresh the consumer jar to get it to wire to the new mypackage.helloworldservice package.
I have an existing "Example Webapp" that references "Example Library" using Maven. I'm running Tomcat 7 inside Eclipse 4.3RC3 with the m2e plugin. When I launch Example Webapp on Tomcat inside Eclipse, I have verified that the example-library.jar is probably getting deployed in the Tomcat instance's WEB-INF/lib folder.
The Example Webapp has code that compiles certain classes on the fly using JavaCompiler.CompilationTask. These dynamically generated classes reference classes in example-library.jar. Unfortunately the compile task is failing because the referenced classes cannot be found.
I understand that I can set the JavaCompiler classpath, but System.getProperty("java.class.path") only returns me the Tomcat classpath, not the webapp classpath:
C:\bin\tomcat\bin\bootstrap.jar;C:\bin\tomcat\bin\tomcat-juli.jar;C:\bin\jdk6\lib\tools.jar
Other have said that I need to get the real path of WEB-INF/lib from the servlet context, but the class generation code doesn't know anything about a servlet context --- it is written to be agnostic of whether it is used on the client or on the server.
In another question, one answer indicated I could enumerate the classloader URLs, and sure enough this provides me with the jars in WEB-INF/lib, but when I provide this as a -classpath option to compiler.getTask(), the task still fails because it can't find the referenced classes.
How can I simply provide the classpath of the currently executing code to the JavaCompiler instance so that it will find the classes from the libraries in WEB-INF/lib? (A similar question was raised but never answered regarding referencing jars within ear files using JavaCompiler.)
Example: In an attempt to get things working at any cost, I even tried to hard-code the classpath. For example, I have foobar.lib in my webapp lib directory, so I used the following code, modified from the answers I indicated above:
List<String> options = new ArrayList<String>();
options.add("-classpath");
options.add("C:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp0\\wtpwebapps\\FooBar\\WEB-INF\\lib\\foobar.jar");
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
boolean success = task.call();
In the end success is false, and my diaognostics indicates package com.example.foo.bar does not exist..., even though that package is in foobar.jar.
Put example-library.jar somewhere in your file system and pass that location to the code that runs JavaCompiler (the -classpath option). If you use an exploded WAR file to deploy, you can of course point it to the physical location within the WEB-INF/lib folder. The point is that you only need one configurable parameter in your webapp to do this, which can be a properties file entry, -D system property, database row or something else entirely.
Sample code (tested in Tomcat 7 and OpenJDK 1.7 on Fedora 18 x64):
private File compile(File javaFile, String classpath) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnit = fileManager.getJavaFileObjects(javaFile);
List<String> options = classpath != null ? Arrays.asList("-classpath", classpath) : null;
StringWriter output = new StringWriter();
try {
boolean successful = compiler.getTask(output, fileManager, null, options, null, compilationUnit).call();
if (!successful) {
throw new CompilationException("Failed to compile: " + javaFile, output.toString());
}
return firstClassFileFrom(javaFile.getParentFile());
} finally {
fileManager.close();
}
}
private File firstClassFileFrom(File directory) {
return directory.listFiles(new FilenameFilter() {
#Override
public boolean accept(File dir, String name) {
return name.endsWith(".class");
}
})[0];
}
See https://github.com/jpalomaki/compiler for a runnable sample webapp.
i met the same question. The reason is not "-classpath" .
my code :
String classpath ="xx/WEB-INF/clases ";
List<String> options = classpath != null ? Arrays.asList("-d", classpath,"-cp",classpath) : null;
CompilationTask task = compiler.getTask(null, javaDinamicoManager, diagnostics,
options, null, Arrays.asList(sourceObj));
boolean result = task.call();
the “result” will return true .
You could follow the answer provided for the even more specific question of how to load dependencies of compiled code from within a web app running directly from an unexpanded WAR file (there are no JAR files to reference - only the container's class loder knows how to access the classes): https://stackoverflow.com/a/45038007/2546679
enter code herewe are using c3p0 jar for databse pooling. Now from c3p0 code, the following exception is comming
Caused by: java.lang.IllegalAccessError: tried to access class com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource$1 from class com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.setUpPropertyEvents(AbstractPoolBackedDataSource.java:74)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.(AbstractPoolBackedDataSource.java:63)
at com.mchange.v2.c3p0.ComboPooledDataSource.(ComboPooledDataSource.java:109)
at com.mchange.v2.c3p0.ComboPooledDataSource.(ComboPooledDataSource.java:105)
Now in AbstractPoolBackedDataSource.java (line 74)
PropertyChangeListener l = new PropertyChangeListener()
PropertyChangeListener l = new PropertyChangeListener()
{
public void propertyChange( PropertyChangeEvent evt )
{ resetPoolManager(); }
};
So, PropertyChangeListener is the inner class here .. AbstractPoolBackedDataSource$1
PropertyChangeListener is a java class java.beans.PropertyChangeListener !!
What can be the reason ? This is only happening in linux(suse 10). In Windows it is working fine(jdk 1.6_10 and jre 1.6_20). I have tried with different jdk,jre combinations ( jdk 1.6_25 etc )
I have resolved the problem using some trial and error.
Also I found, this is not os dependable as I have suspected earlier. This is easily reproducible and looks like an potential class loading bug.( though I am not sure whether it is in equinox implementation or in java !!).
Before explaining the solution, let me describe the scenario more elaborately.
We have our code deployed in a osgi(equinox) framework. There are two bundles which uses the c3p0 jar for database pooling and one of them exports the c3p0 packages. This bundle starts before the other one.
Now, according to osgi specification, osgi class loader should maintain separate class loader instances for separate bundles. Now when the second bundle tries to load classes from the c3p0 jar, its class-loader may find (from parent delegation) that the classes are already loaded !! But they are loaded from different context, which is causing the access violation.
This is initial findings, I will try to debug with the eclipse code and may be dig more into it. After changing the bundle start order, this is resolved.