Adding akka dependencies to osgi container - java

I use osgi container (virgo) [i'm not very good in that].
I added a dependency to my pom.xml
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-osgi_2.10</artifactId>
<version>2.2-M3</version>
</dependency>
I put akka-osgi_2.10-2.2-M3.jar to my lib/deploy folder to OSGI server (to myserver/repository/usr).
I added dummy actor to my code base:
import akka.actor.UntypedActor;
public class ManagerActor extends UntypedActor {
#Override
public void onReceive(Object o) throws Exception {
// ...
}
}
I build and start my application.
And as result I have the following exceptions in my log (it complains to version="0.0.0"):
.. failed. org.eclipse.virgo.kernel.osgi.framework.UnableToSatisfyBundleDependenciesException: Unable to satisfy dependencies of bundle 'com.
com.mycompnay.mything-security' at version '1.0.1.BUILD-SNAPSHOT': Cannot resolve: com.mycompany.mything-security
Resolver report:
An Import-Package could not be resolved. Resolver error data <Import-Package: akka.actor; version="0.0.0">. Caused by missing constrai
nt in bundle <com.mycompany.mything-security_1.0.1.BUILD-SNAPSHOT>
constraint: <Import-Package: akka.actor; version="0.0.0">
I go to my template.mf file, which is used to generate final MANIFEST.MF file. To specify the range of versions for AKKA lib I use. Putting there:
Import-Template:
akka.actor.*;version="[2.2.0.M3, 2.3)"
Import-Package:
akka.actor;version="[2.2.0.M3, 2.3)"
Then rebuild and start app.
But in console it complains to akka versions (complains to version="[2.2.0.M3,2.3.0)" now):
An Import-Package could not be resolved. Resolver error data <Import-Package: akka.actor; version="[2.2.0.M3,2.3.0)">. Caused by missi
ng constraint in bundle <com.mycompany.mything-security_1.0.1.BUILD-SNAPSHOT>
constraint: <Import-Package: akka.actor; version="[2.2.0.M3,2.3.0)">
Q: what's wrong?
Also I tried to add this line: to Import-Bundle:
Import-Bundle:
...
com.typesafe.akka.osgi;version="[2.2.0.M3, 2.3)"
Then I have it in the log (now it complains to com.typesafe.akka.osgi version):
.. failed. org.eclipse.virgo.kernel.deployer.core.DeploymentException: Unable to satisfy dependencies of bundle 'com.mycompany.mything-security
' at version '1.0.1.BUILD-SNAPSHOT': Import-Bundle with symbolic name 'com.typesafe.akka.osgi' in version range '[2.2.0.M3, oo)' could not be
satisfied

The reason was:
I need to put akka-actor_2.10-2.2-M3.jar (along with akka-osgi_2.10-2.2-M3.jar) to my osgi (virgo) deploy folder.
So, we should NOT do it manually but with help of maven (in order not to miss some jar that comes along with expecting one).

Related

java.lang.NoSuchMethodError when using twilio SMS

I am using Java web in Netbeans 8.2 RC
I try to send an SMS message using Twillio client:
Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
Message message = Message.creator(
new com.twilio.type.PhoneNumber(getContact()),
new com.twilio.type.PhoneNumber("+phonenumber"),
"Sample message"
).create();
The message is successfully delivered.
But the code does not continue after .create().
Following exception is thrown:
java.lang.NoSuchMethodError:
com.fasterxml.jackson.datatype.jsr310.deser.JSR310DateTimeDeserializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/DeserializationContext;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value;
What I tried
I do not have a pom.xml or build.gradle. I only have web.xml
I have already imported the libraries: twilio-8.9.0-jar-with-dependencies.jar
How can I solve this issue?
The libraries I have:
Twillio SDK, exactly the create() method, seems to depend on Jackson (FasterXML converter library), particularly its module for handling Java8 DateTime (JSR-310). This is obvious when a call of create() results in a NoSuchMethod... for a missing method of class JSR310DateTimeDeserializerBase.
🔎 If you would have included the complete error output such as the stack-trace of this exception, then we could have easily seen that.
Analysis
ℹī¸ A NoSuchMethod runtime-error is usually not caused by import statements or web.xml. It usually correlates with mismatching dependency-versions.
See the Twilio Java SDK v 8.9.0 (jar) as shown in Maven's web-UI (same as v 8.8.0) includes pom.xml with following dependency:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>?
and under the properties the required version:
<jackson.version>2.12.1</jackson.version>
Check dependency versions
Make sure that this jar or package is included within the Twillio jar or at least on your classpath.
⚠ī¸ Also the versions must match (e.g. jackson-core v1 is often depending on jackson-datatype v1). A newer or older version may either change the method (currently not found) i.e. the call or the method-declaration.
Did the method change in Jackson versions?
In previous version (2.11) I also found the method findFormatOverrides with expected signature (parameters and return types) in class JSR310DateTimeDeserializerBase.
It was called inside the JsonDeserializer for a Java date-time property. Here when the deserializer is created in context, the parent-class' method is called:
#Override public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
Solving suggestions
See How do I fix a NoSuchMethodError?. A comment to that question fits yours:
In Netbeans: Right click on project in Projects tab, use "Clean and Build". Solved it for me.
💡 This article on NoSuchMethod is very helpful for this issue.
Use Gradle or Maven
💭 You should consider to use a dependency-management and build-automation tool like Maven or Gradle:
Twilio: Java Helper Library, Using with a build automation tool
suggested in similar question: json - java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/JsonMappingException

java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory in OSGi

I'm trying to get the library BioJava to work inside an OSGi context.
To get the JAR into the OSGi context, I'm using the Maven plugin p2-maven-plugin, which generates a file Manifest.MF, and the part relevant to the exception I'm facing is:
Bundle-SymbolicName: org.biojava.core
Bundle-Version: 5.3.0
Import-Package: [snip],
org.slf4j;resolution:=optional,
[snap]
Which looks okay to me. However when I access a class that uses slf4j I get the titular exception:
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
at org.biojava.nbio.core.sequence.template.AbstractCompoundSet.<clinit>(AbstractCompoundSet.java:40)
at org.biojava.nbio.core.sequence.io.ABITrace.getSequence(ABITrace.java:179)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory cannot be found by org.biojava.core_5.3.0
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:511)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:422)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:414)
Now it's easy to find this exception everywhere, because a lot of people have tried (and failed) to install slf4j. I checked sites like the documentation or the SO question ClassNotFoundException: org.slf4j.LoggerFactory and hence tried to add the following bundles:
slf4j-simple
slf4j-log4j12 (plus the log4j dependencies)
pax-logging-log4j2
However neither worked. Maybe the OSGi container is having problems, but slf4j JARs have the bundle information with the export packages out of the box, so I'm assuming these work. And the BioJava JAR has an import package, so I have no idea why it wouldn't be able to find the class.
Oh, I checked, the LoggerFactory is present in slf4j-api, so it's not that, either.
I also tried different start levels and autostart for the implementations. And I rebundled the JAR without the optional dependency, but I keep having problems because now the MD5 hash is broken.
Has anybody managed to get slf4j to work in OSGi? Or failing that, is there any way to replace that stupid dependency with some kind of Java proxy so I will not need the broken dependency anymore?
resolution:=optional means that when the bundle resolves, it will either get access to the package or not. The framework is permitted to resolve the bundle without access to the package. If the bundle needs access to the package, why make resolution of the package optional?

Integrating external library into OSGI

I have been trying to fix this issue for several days now, but i seem stuck somehow. I want to develop a OSGi bundle, and my implementation requires an external library (that has some more dependencies). The situation is as follows: My project is using gradle and i got a simple code snippet to compile, but it crashes at runtime when the bundle is launched ( i am using apache felix), giving me an exception complaining about unmet dependencies. But all libraries are present in the jar bundle, and i added them into the classpath. The missing package org.ethereum.facade is listed within Private-Packages.
I read a lot of questions with similar problems, but none of the silutions proposed seems to solve my problem.
I am posting my gradle.build files
// ETHEREUM NODE
configurations.create('embed')
repositories {
mavenLocal()
mavenCentral()
maven {
url "http://dl.bintray.com/ethereum/maven"
}
}
dependencies {
// This will compile the openMuc Framework and place the result into the build classpath:
compile project(':openmuc-core-api')
// This will place the etherum libraries into the classpath
compile ("org.ethereum:ethereumj-core:latest.release")
embed ("org.ethereum:ethereumj-core:latest.release")
}
jar {
manifest {
name = 'OpenMUC App - EthereumNode'
instruction 'Bundle-ClassPath', 'lib/ethereumj-core-1.4.2-RELEASE.jar,.'
}
into('lib') {
from configurations.embed
}
}
The resulting jar:
[MANIFEST openmuc-app-ethereumNode-0.16.0.jar]
Bnd-LastModified 1490003658351
Bundle-ClassPath lib/ethereumj-core-1.4.2-RELEASE.jar,.
Bundle-ManifestVersion 2
Bundle-Name OpenMUC App - EthereumNode
Bundle-SymbolicName org.openmuc.framework.openmuc-app-ethereumNode
Bundle-Version 0.16.0
Created-By 1.8.0_25 (Oracle Corporation)
Export-Package org.openmuc.framework.app.ethereumNode;version="0.16.0";uses:="javax.xml.bind,org.osgi.service.component"
Import-Package javax.xml.bind,org.osgi.service.component;version="[1.2,2)",org.slf4j;version="[1.7,2)",org.ethereum.facade
Manifest-Version 1.0
Private-Package genesis,org.ethereum,org.ethereum.cli,org.ethereum.config,org.ethereum.config.blockchain,org.ethereum.config.net,org.ethereum.core,org.ethereum.core.genesis,org.ethereum.crypto,org.ethereum.crypto.cryptohash,org.ethereum.crypto.jce,org.ethereum.datasource,org.ethereum.datasource.inmem,org.ethereum.datasource.leveldb,org.ethereum.datasource.mapdb,org.ethereum.db,org.ethereum.db.index,org.ethereum.facade,org.ethereum.json,org.ethereum.jsonrpc,org.ethereum.listener,org.ethereum.manager,org.ethereum.mine,org.ethereum.net,org.ethereum.net.client,org.ethereum.net.dht,org.ethereum.net.eth,org.ethereum.net.eth.handler,org.ethereum.net.eth.message,org.ethereum.net.message,org.ethereum.net.p2p,org.ethereum.net.rlpx,org.ethereum.net.rlpx.discover,org.ethereum.net.rlpx.discover.table,org.ethereum.net.server,org.ethereum.net.shh,org.ethereum.net.submit,org.ethereum.net.swarm,org.ethereum.net.swarm.bzz,org.ethereum.samples,org.ethereum.solidity,org.ethereum.solidity.compiler,org.ethereum.sync,org.ethereum.trie,org.ethereum.util,org.ethereum.util.blockchain,org.ethereum.validator,org.ethereum.vm,org.ethereum.vm.program,org.ethereum.vm.program.invoke,org.ethereum.vm.program.listener,org.ethereum.vm.trace,lib
Require-Capability osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.7))"
Service-Component OSGI-INF/org.openmuc.framework.app.ethereumNode.EthereumNode.xml
Tool Bnd-3.0.0.201509101326
[IMPEXP]
Import-Package
javax.xml.bind
org.ethereum.facade
org.osgi.service.component {version=[1.2,2)}
org.slf4j {version=[1.7,2)}
Export-Package
org.openmuc.framework.app.ethereumNode {version=0.16.0}
[USES]
org.openmuc.framework.app.ethereumNode java.lang
javax.xml.bind
org.ethereum.facade
org.osgi.service.component
org.slf4j
[USEDBY]
java.lang org.openmuc.framework.app.ethereumNode
javax.xml.bind org.openmuc.framework.app.ethereumNode
org.ethereum.facade org.openmuc.framework.app.ethereumNode
org.osgi.service.component org.openmuc.framework.app.ethereumNode
org.slf4j org.openmuc.framework.app.ethereumNode
[COMPONENTS]
OSGI-INF/org.openmuc.framework.app.ethereumNode.EthereumNode.xml
<?xml version="1.0" encoding="UTF-8"?>
<component name="org.openmuc.framework.app.ethereumNode.EthereumNode">
<implementation class="org.openmuc.framework.app.ethereumNode.EthereumNode"/>
</component>
[LIST]
META-INF
MANIFEST.MF extra='\uFFFD\uFFFD\u0000\u0000'
OSGI-INF
org.openmuc.framework.app.ethereumNode.EthereumNode.xml
lib
aopalliance-1.0.jar
commons-codec-1.10.jar
commons-collections4-4.0.jar
commons-lang3-3.4.jar
commons-logging-1.2.jar
config-1.2.1.jar
core-1.53.0.0.jar
ethereumj-core-1.4.2-RELEASE.jar
guava-16.0.1.jar
jackson-annotations-2.5.0.jar
jackson-core-2.5.1.jar
jackson-core-asl-1.9.13.jar
jackson-databind-2.5.1.jar
jackson-mapper-asl-1.9.13.jar
java-util-1.8.0.jar
javassist-3.15.0-GA.jar
json-io-2.4.1.jar
json-simple-1.1.1.jar
jsr305-3.0.0.jar
leveldb-0.7.jar
leveldb-api-0.7.jar
leveldbjni-all-1.18.3.jar
logback-classic-1.1.7.jar
logback-core-1.1.7.jar
mapdb-2.0-beta12.jar
netty-all-4.0.30.Final.jar
prov-1.53.0.0.jar
slf4j-api-1.7.20.jar
solcJ-all-0.4.8.jar
spring-aop-4.2.0.RELEASE.jar
spring-beans-4.2.0.RELEASE.jar
spring-context-4.2.0.RELEASE.jar
spring-core-4.2.0.RELEASE.jar
spring-expression-4.2.0.RELEASE.jar
spring-jdbc-4.2.0.RELEASE.jar
spring-orm-4.2.0.RELEASE.jar
spring-tx-4.2.0.RELEASE.jar
org
org/openmuc
org/openmuc/framework
org/openmuc/framework/app
org/openmuc/framework/app/ethereumNode
EthereumNode.class
The exception i encounter when the bundle is loaded:
ERROR: Bundle org.openmuc.framework.openmuc-app-ethereumNode [3] Error starting file:/Volumes/UserData/Documents/FH/MasterThesis_MatthiasPosch/java/openmuc/framework/bundle/openmuc-app-ethereumNode-0.16.0.jar (org.osgi.framework.BundleException: Unable to resolve org.openmuc.framework.openmuc-app-ethereumNode [3](R 3.0): missing requirement [org.openmuc.framework.openmuc-app-ethereumNode [3](R 3.0)] osgi.wiring.package; (osgi.wiring.package=org.ethereum.facade) Unresolved requirements: [[org.openmuc.framework.openmuc-app-ethereumNode [3](R 3.0)] osgi.wiring.package; (osgi.wiring.package=org.ethereum.facade)])
org.osgi.framework.BundleException: Unable to resolve org.openmuc.framework.openmuc-app-ethereumNode [3](R 3.0): missing requirement [org.openmuc.framework.openmuc-app-ethereumNode [3](R 3.0)] osgi.wiring.package; (osgi.wiring.package=org.ethereum.facade) Unresolved requirements: [[org.openmuc.framework.openmuc-app-ethereumNode [3](R 3.0)] osgi.wiring.package; (osgi.wiring.package=org.ethereum.facade)]
at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:4112)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2118)
at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1372)
at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308)
at java.lang.Thread.run(Thread.java:745)
So it seems all libraries are in place in the lib folder, but still the bundle does not work. I tried to play with the code, but any reference to the included libraries (eg. spring) will lead to a similar exception. Why?
My solution was to use the osgi-run plugin for gradle instead of the original osgi plugin. Declaring my dependencies as SystemLibrary systemLib ("org.ethereum:ethereumj-core:1.2.0-RELEASE") resolved the issues and i am able to use the library without exceptions and errors.
In your Manifest you import the package org.ethereum.facade. This can only work if there is also a bundle that exports this package. If the package is purely internal then you should set it as private package and not import it.
If the package might be needed from the outside then make sure you have an import and an export for it in your bundle. If you have not configured the import manually then for some reason the build seems to think you need it and it is not present locally in your bundle.
How do you create the Manifest? Do you use bnd for this? If yes then maybe the manual change in bundle classpath is not recognized by it.

Invocation of MavenCli fails within a Maven plugin

I've created small util to wrap MavenCli, which generates a new Maven project, using the quickstart archetype.
When executing the Util as a unit test, it is working quite well (just generating an empty Maven project).
Now I want to integrate this small wrapper into a Maven plugin. But when I execute the mojo (within a third Maven project), the invocation of MavenCli fails with exception:
[ERROR] Error executing Maven.
[ERROR] java.util.NoSuchElementException
role: org.apache.maven.eventspy.internal.EventSpyDispatcher
roleHint:
[ERROR] Caused by: null
The util looks like:
public void createProject() {
final MavenCli cli = new MavenCli();
System.setProperty("maven.multiModuleProjectDirectory", "/usr/share/maven");
cli.doMain(new String[] { "archetype:generate", "-DgroupId=com.my.company",
"-DartifactId=hello-world", "-DarchetypeArtifactId=maven-archetype-quickstart",
"-DinteractiveMode=false" }, "/tmp", System.out, System.out);
}
relevant dependency of the util:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.3.9</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.9</version>
</dependency>
The mojo code looks like:
#Mojo(name = "custommojo", requiresProject = false)
public class CustomMojo extends AbstractMojo {
#Override
public void execute() throws MojoExecutionException, MojoFailureException {
Util.createProject();
}
}
The POM of the mojo just includes dependencies to relevant Maven artifacts (plugin-api, plugin-annotation, etc.) and the util.
The third project I mentioned, is an empty "maven-quickstart" project which have dependency to the mojo-project and a configuration for the mojo to execute in compile phase.
I have no idea why it works in context of unit test, but not in context of a mojo.
Can anybody help?
This is a class loading issue.
MavenCli will try to load classes from the context classloader of the current thread. Inside of a Maven plugin, there is a special, restricted, classloader, which has access to:
its own classes;
the classes used in its dependencies block;
exported classes as part of a possible build extension of the project;
exported classes from the Maven core and core extensions;
and has the bootstrap classloader as parent.
However, the specific class org.apache.maven.eventspy.internal.EventSpyDispatcher is part of Maven core, but it is not part of the exported APIs (the package org.apache.maven.eventspy is not listed as an exportedPackage). So the plugin cannot load that class. This is also why it works in your tests: you're not inside of a plugin, so the classloader is different and has access to that class.
You won't even be able to get away with adding explictly a dependency on maven-core for the plugin: it will be disgarded since it is supposedly already provided.
There are 2 solutions here:
Don't use the Maven Embedder API from within a plugin, but the Invoker API. The difference between the two is that the Invoker API will launch Maven in a clean environment, completely distinct with regard to the current one. Since it starts everything anew, you won't have any classloading issue.
Use the mojo-executor library, that provides an easy way to invoke other Mojos from within a Maven plugin. You could use it here to invoke the archetype:generate Mojo.
This works for me inside a custom maven plugin (using Maven 3.5.0):
ClassRealm classRealm = (ClassRealm) Thread.currentThread().getContextClassLoader();
MavenCli cli = new MavenCli(classRealm.getWorld());
cli.doMain( ... );
The plexus Launcher sets the context class loader to its ClassRealm, which has access to the "global" ClassWorld.
Not sure how stable that solution is, but so far looking good.
Used imports:
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.apache.maven.cli.MavenCli;
#Alexander:
You answer put me in the right direction, I was getting the mentioned error when trying to run to doMain maven commands subsequently (one command would succeed).
However your code gives me a ClassCast exception :
Exception in thread "main" java.lang.ClassCastException: sun.misc.Launcher$AppClassLoader cannot be cast to org.codehaus.plexus.classworlds.realm.ClassRealm
at com.misys.tools.integration.codegen.cli.cmd.InstallApi.mavenInstallMchApi(InstallApi.java:58)
at com.misys.tools.integration.codegen.cli.cmd.InstallApi.run(InstallApi.java:50)
at com.misys.tools.integration.codegen.cli.OpenApiGen.main(OpenApiGen.java:26)
I managed to rewrite the code to:
MavenCli cli = new MavenCli(new ClassWorld("maven",Thread.currentThread().getContextClassLoader()));
And then 2 subsequent doMain invocations of embedded maven succeed!

starting slf4j bundle doesn't start on felix

I have felix-framework-5.0.1 and I'm trying to start slf4j-api-1.6.0.jar bundle into felix isgi container.
in felix console I'm typing install file:bundle/slf4j-api-1.6.0.jar
I'm getting a message Bundle ID: 42
then I'm trying to start the bundle start 42
I'm getting the message
org.osgi.framework.BundleException: Unable to resolve slf4j.api [42](R 42.0): missing requirement [slf4j.api [42](R 42.0)] osgi.wiring.package; (&(osgi.wiring.p
ackage=org.slf4j.impl)(version>=1.5.5)) Unresolved requirements: [[slf4j.api [42](R 42.0)] osgi.wiring.package; (&(osgi.wiring.package=org.slf4j.impl)(version>=
1.5.5))]
g!
Can any body help me? how can I start slf4j bundle into felix?
slf4j-api needs org.slf4j.impl package. This package is included into every slf4j implementations like slf4j-simple, slf4j-logback, etc.
The implementation bundles need org.slf4j package that comes from the API artifact. There is a cross-reference. This can work only due to the reason that implementations are fragment bundles of the API. When the implementation is installed together with the API, they will have a common classloader and they will be resolved together. Both of their requirements will be satisfied.
In short: You must choose one of the implementations and install that as well. E.g.: slf4j-simple.
You should use the same version of API and implementation to satisfy their "cross requirement".
Your library contains the following 3 packages (link):
org.slf4j
org.slf4j.helpers
org.slf4j.spi
but you have to have an additional library that will contain org.slf4j.impl package.
Also, from manifest file you can see what packages are exported (Export-Package) (they are visible by other bundles) and what packages are imported (Import-Package) (they have to be accessible for the given bundle). Sometimes the given package have to be from bundle with the correct version.
If you cannot find correct bundle maybe this page will help you.

Categories