Pax Exam: provisioning bundle with all dependencies - pax-exam

Currently, to set up configuration for Pax Exam, I find that I need to include all dependencies. E.g. something like
#Configuration
public Option[] сonfig() {
MavenArtifactProvisionOption commonsDbcp = mavenBundle("commons-dbcp",
"commons-dbcp");
MavenArtifactProvisionOption commonsPool = mavenBundle("commons-pool",
"commons-pool");
...
return options(
felix(),
provision(commonsDbcp, commonsPool));
}
But since commons-dbcp depends on commons-pool, this feels like duplicate information. Is it possible for Pax Exam to figure out that commons-dbcp is needed without adding it explicitly?

Not really...
Not every Maven dependency of an OSGi bundle is an OSGi bundle.
A dependency may be an interface-only, and at run-time, you want to provision an implementation bundle instead.
Listing all bundles explicitly is the only safe way of provisioning your framework. At least, you can use the versionAsInPom() option method to avoid duplicating the artifact versions.

Related

bundle's service (autowire) not available in controller's method

I'd like to use https://github.com/tedious/TedivmStashBundle bundle in my symfony 4 project. Added by composer, configured in /config/stash.yaml file and according to the profiler bar, it's working basically.
Now, I want to use to caching values in my controller. I've try to add the service stash by its name to the method's parameter, using the same name as the example says:
$pool = $this->container->get('stash');
but the framework did not find the service. It can't be added like the example explained neither.
How can I use this bundle as a service (autowired) in my symfony 4 app?
UPDATE
services.yaml:
stash.default_cache:
class: Tedivm\StashBundle\Service\CacheService
public: true
arguments:
$name: 'stash'
Tedivm\StashBundle\Service\CacheService: '#stash.default_cache'
Controller:
public function something(Request $request, CacheService $service, ...
It's looks like working now :)
Thanx for the suggestion (and the correct solution later) to #Cerad
Here is an example of how to approach this sort of problem when dealing with bundles that are not quite ready for autowire.
Start by installing a test project:
symfony new --full stash --version=lts
composer require tedivm/stash-bundle
Note that the bundle does not directly support Symfony 5 hence the lts. Note also that the bundles does not support Flex so you have to add your own config/packages/stash.yaml file per the bundle's readme file.
# config/packages/stash.yaml
stash:
drivers: [ FileSystem ]
FileSystem: ~
At this point we can determine which service we need to inject:
bin/console debug:container stash
Information for Service "stash.default_cache"
=============================================
Class CacheService
---------------- -----------------------------------------
Option Value
---------------- -----------------------------------------
Service ID stash.default_cache
Class Tedivm\StashBundle\Service\CacheService
Most of the time you would like to use an interface for injection but a peek at the source code reveals that the bundle does not use interfaces. As a side note, calling a third party service 'stash' is not a good idea. It really should have been 'tedivm.stash' but I digress.
We can now create an alias and then typehint against it:
# config/services.yaml
Tedivm\StashBundle\Service\CacheService : '#stash' # alias for typehinting
# Controller class
public function index(CacheService $cacheService)
{
return new Response('Cache ' . get_class($cacheService));
}
And that should do it.

How can CorDapps deal with transitive dependencies

Currently in v2, if a CorDapp references a module X, which has a transitive dependency to a module Y, such that Y is used by Corda, a potential version conflict can occur if the respective versions of Y for Corda and X differ. An example is the reuse of an existing internal library, containing business and serialisation logic, that depends on Jackson.
In this case, the resulting CorDapp packaging and Corda runtime, seem to enforce the version of Y that is relevant for Corda.
If the versions of Y differ sufficiently, we can get such scenarios as X breaking because Y doesn’t support certain types and methods.
Is there a general way that the gradle configuration (or some other mechanism) can be used to restrict the correct version of Y for usage by X, without impacting the Corda runtime?
So I worked this out, and in the process, finally learnt some gradle basics (having come from a maven background). No doubt the following is inelegant and could be generalised better - but it works!
TLDR: shadowJar
Assumptions
you're using the current v2 kotlin cordapp template
the cordapp sub module uses dependencies that either they or their dependencies clash against the Corda runtime.
Solution
1. add the shadowJar reference
In the root build.gradle file add the following
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
to the buildscript dependencies:
buildscript {
// ...
dependencies {
// ...
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.2'
}
}
2. add shadowJar task to the cordapp
In the cordapp project, apply the shadowJar plugin.
Please Note: I needed to put this before all existing plugins for it to work.
apply plugin: 'com.github.johnrengelman.shadow'
apply plugin: 'kotlin'
// ... etc
Then add the invocation parameterisation:
tasks {
shadowJar {
mergeServiceFiles()
// Place your shaded packages here!
relocate 'io.netty', 'shadow.io.netty'
relocate 'com.fasterxml', 'shadow.com.fasterxml'
configurations = [project.configurations.compile]
baseName = jar.baseName + "-" + jar.version
classifier = null
version = null
dependencies {
include(dependency(".*:.*:.*"))
exclude(dependency('org.jetbrains.kotlin:.*:.*'))
exclude(dependency('net.corda:.*:.*'))
exclude(dependency('org.apache.logging.*:.*:.*'))
exclude(dependency('org.apache.activemq:.*:.*'))
exclude(dependency('com.google.*:.*:.*'))
exclude(dependency('io.reactivex:.*:.*'))
exclude(dependency('org.bouncycastle.*:.*:.*'))
exclude(dependency('org.glassfish.*:.*:.*'))
exclude(dependency('co.paralleluniverse.*:.*:.*'))
exclude(dependency('co.paralleluniverse.*:.*:.*'))
exclude(dependency('com.typesafe.*:.*:.*'))
exclude(dependency('com.esotericsoftware.*:.*:.*'))
exclude(dependency('org.qpid.*:.*:.*'))
}
}
}
3. Alter the build dependencies
Now change the definition of deployNodes to not depend on the jar task, but instead, depend on the build of each module:
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: [':cordapp-contracts-states:jar', ':cordapp:shadowJar']) {
// ... etc
}

Pax Exam: resolving project dependencies with bundles and wrapped bundles

I'm aware of this answer: Pax Exam: provisioning bundle with all dependencies
But it feels like I'm doing something wrong when I have to include bundles that are part of bundles that are external to my project.
Here is the error I'm getting:
java.lang.Exception: Could not start bundle wrap:mvn:org.apache.cxf/cxf-bundle-jaxrs/2.7.14 in feature(s) test-dependencies-0.0.0: Unresolved constraint in bundle org.apache.cxf.bundle-jaxrs [80]: Unable to resolve 80.0: missing requirement [80.0] osgi.wiring.package; (&(osgi.wiring.package=com.ctc.wstx.stax)(version>=4.4.0)(!(version>=5.0.0)))
Here is my configuration code for my pax exam test:
#Configuration
public Option[] config() {
MavenArtifactUrlReference karafUrl = maven()
.groupId("org.apache.karaf")
.artifactId("apache-karaf")
.version(karafVersion())
.type("tar.gz");
MavenUrlReference karafStandardRepo = maven()
.groupId("org.apache.karaf.features")
.artifactId("standard")
.classifier("features")
.version(karafVersion())
.type("xml");
return new Option[] {
// KarafDistributionOption.debugConfiguration("5005", true),
karafDistributionConfiguration()
.frameworkUrl(karafUrl)
.unpackDirectory(new File("target/exam"))
.useDeployFolder(false),
keepRuntimeFolder(),
KarafDistributionOption.features(karafStandardRepo , "scr"),
//**Do I seriously need to do this?**
wrappedBundle(mavenBundle("org.codehaus.woodstox", "wstx-lgpl")).noStart(),
//**Why am I doing this?**
wrappedBundle(mavenBundle("org.apache.cxf", "cxf-bundle-jaxrs").version("2.7.14")).noStart(),
//**Some of my bundles use this so I guess this makes sense**
wrappedBundle(mavenBundle("org.apache.commons", "commons-lang3")),
mavenBundle("com.company.project", "common-core").versionAsInProject().start(),
mavenBundle("com.company.project", "common-properties", "1.3.1").start(),
mavenBundle("com.company.project", "rev-common-core", "1.3.1").start(),
mavenBundle("com.company.project", "rev-common-properties", "1.3.1").start(),
mavenBundle("com.company.project", "maintenance-core", "1.3.1").start(),
};
}
So my questions are: why am I getting the error about unresolved constraints, do I have to include even external bundles, and what do I need to do to get my tests to run?
Yes, you have to include all required bundles, Karaf container is running empty, you have to provide all bundles required in your test.
You can create a feature for the module you want to test as a way to supply all required bundles. Then you can use it in your test, e.g:
KarafDistributionOption.features("mvn:group/artifact-id/version/xml", "feature-name")

Qt, Qbs: generate moc_Filename.cpp automatically

So I have a Q_OBJECT tagged class, which requires pregenerated .moc to be usable.
In my .qbs file, I have a CppApplication item; this seems to be the wrong type of project, as qbs does not call moc ClassName.cpp to generate moc's for me. What should be used instead/tweaked?
-
So I knew about Qt.core dependency, but it wasn't working on my crippled install of Qt; while I was trying to fix it, these facts came up:
It was required to detect Qt toolchain (qbs-setup-qt) and call qbs-config-ui
Qbs indeed stores the build rules in core.qbs, linked in via Qt/core dependency.
it's possible to copy/paste the build rules into my own .qbs file and avoid external dependencies; I'm considering this as a dirty hack for deploying the code on really crippled build systems (now I have a word for Qt support on Gentoo).
I think you might be missing the dependency of the application on the Qt-modules.
The rule for generation of the moc files is part of the Qt.core module.
You might add this dependency with:
CppApplication {
name: "MyApp"
files: "path_to_source/**"
Depends { name: "Qt.core" } // Optional
Depends { name: "Qt.widgets" }
}
As all other Qt modules have an implicit dependency on Qt.core the explicit dependency could on Qt.core could be skipped if there is a dependency on a different Qt-module (Qt.widgets in this example).
More details could be found at http://doc.qt.io/qbs/qt-modules.html

seam solder (former weld-extensions project) is not initialized

I want to use logger in my java web application.
I'm using JBossAS 6.0.0.final, cdi (weld), jsf ... etc. Seam solder proposes to use an abstract logger is not tying to a concrete implementation (slf4j, log4j, etc) using jboss-logging api.
In order to get this logger in your code will need to write
# Inject
org.jboss.logging.Logger log
seam-solder.jar has the producer for this logger.
package org.jboss.seam.solder.log;
...
class LoggerProducers
{
# Produces
org.jboss.logging.Logger produceLog (InjectionPoint injectionPoint) {}
}
When I deploying my application, I get an error
15:51:18,300 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController] Error installing to Start: name=vfs:///C:/Java/jboss-6.0.0.Final/server/default/deploy/kamis-web-client.5.0.0-SNAPSHOT.ear_WeldBootstrapBean state=Create: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Logger] with qualifiers [#Default] at injection point [[field] #Inject private ru.kamis.suite.webclient.web.breadcrumbs.BreadcrumbsManager.log]
This is due to the seam-solder.jar has not META-INF/beans.xml file, and it is necessary for cdi container.
If to add beans.xml file in seam-solder.jar manually, then the application works WELL.
How to do without hacks?
To build my application I use maven, so my solution is not comfortable and NOT fine.
PS: Former weld-extensions project contained META-INF/beans.xml file in jar.
with seam-solder-3.0.0.Beta1 there should be no need to modify the jar

Resources