Unsatisfied dependencies with Weld during integration testing - testing

I am able to deploy a RESTEasy application working well with Weld (meaning my CDI works) but I am having some trouble with my integration tests. I get this error:
org.jboss.weld.exceptions.DeploymentException:
WELD-001408: Unsatisfied dependencies for type SomeService with qualifiers #Default
while testing:
#RunWith(WeldJUnit4Runner.class)
public class SomeServiceIT {
#Inject
private SomeService service;
#Test
public void test() {
System.out.println(service);
}
}
The last message in my logs is
DEBUG::WELD-000100: Weld initialized. Validating beans
Content of src/test/resources/META-INF/beans.xml:
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
By the way I tried the cdi-unit library and it works, but I need to use my own WeldJUnit4Runner which is currently:
public class WeldJUnit4Runner extends BlockJUnit4ClassRunner {
private final Weld weld;
private final WeldContainer container;
public WeldJUnit4Runner(Class<?> klass) throws InitializationError {
super(klass);
this.weld = new Weld();
this.container = weld.initialize();
}
#Override
protected Object createTest() throws Exception {
return container.instance().select(getTestClass().getJavaClass()).get();
}
}
I use weld-se 2.4.1.Final for testing.
Thanks.
EDIT:
So it seems like Weld only looks into src/test/java (when I copy SomeService over to src/test/java it woks). This is silly, I am not going to duplicate all my classes to test them... How to tell Weld to retrieve classes from src/main/java?

So I was able to make it work by creating src/main/resources/META-INF/beans.xml in addition to the existing src/main/webapp/WEB-INF/beans.xml and src/test/resources/META-INF/beans.xml meaning now I have 3 times the exact same file in the same project which I find silly but I guess this is how it is in the Weld world...
Thanks all for your time.
EDIT:
Actually I am able to deploy the application with only src/main/resources/META-INF/beans.xml (I removed src/main/webapp/WEB-INF/beans.xml)

Sorry, I have no solution, but only a small clue: if you want to do some customizations of the BlockJUnit4ClassRunner - why don't you try to extend the org.jglue.cdiunit.CdiRunner or org.apache.deltaspike.testcontrol.api.junit.CdiTestRunner? Or at least take a look at their source code.
Ps. I always find Weld's class-path scanning brittle & error prone. And try to avoid it as much as possible.

It should work so I post here what I did.
Firstly, I use :
Eclipse Luna
JDK 7
The tree of my project is the following one :
Here are my pom dependencies :
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>2.4.1.Final</version>
<scope>test</scope>
</dependency>
The SomeService interface :
package org.jvi.cdirunner;
public interface SomeService {
void test();
}
The SomeServiceImpl implementation :
package org.jvi.cdirunner;
public class SomeServiceImpl implements SomeService {
#Override
public void test() {
// TODO Auto-generated method stub
}
}
And the test to run :
package org.jvi.cdirunner.test;
import javax.inject.Inject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jvi.cdirunner.SomeService;
#RunWith(WeldJUnit4Runner.class)
public class SomeServiceIT {
#Inject
private SomeService service;
#Test
public void test() {
System.out.println(service);
}
}
And everything works fine if I run the test under Eclipse. I can't figure out why it doesn't work on your side.

Related

HttpComponentsClientHttpConnector is not accepting org.apache.http.impl.nio.client.CloseableHttpAsyncClient for Webclient with Apache Http Client

Im trying to run Webflux on Tomcat and try to create Sping WebClient with Apache Http Client.
Reference Documentation stated that theres built-in support:
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#webflux-client-builder-http-components
private ClientHttpConnector getApacheHttpClient(){
HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom();
clientBuilder.setDefaultRequestConfig(RequestConfig.DEFAULT);
CloseableHttpAsyncClient client = clientBuilder.build();
ClientHttpConnector connector = new HttpComponentsClientHttpConnector(client);
return connector;
}
But Springs HttpComponentsClientHttpConnector is not accepting org.apache.http.impl.nio.client.CloseableHttpAsyncClient. It requires org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient. So there seems to be a package rename and I canĀ“t find a Maven Dependency that has the required class.
Does anybody know the right Maven Dependency for that class. Or how could I make it work?
Apache HTTP Client 5 is a separate artifact. You'll need to add the following dependencies to your pom.xml:
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5-reactive</artifactId>
<version>5.1</version>
</dependency>
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.springframework.http.client.reactive.HttpComponentsClientHttpConnector;
public class ApacheHttp {
public static void main(String[] args) {
new HttpComponentsClientHttpConnector(HttpAsyncClients.custom().build())
}
}

CDI doesn't work in a simple adapter

I've added the CDI feature to the server.xml file<feature>cdi-1.2</feature>.
My maven module contains the beans.xml inside the <module_name>/src/main/resources/META-INF folder.
This is the beans.xml content:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="1.1" bean-discovery-mode="all">
</beans>
But when I use the #Inject annotation it doesn't work, my bean is always null.
Code:
package ch.webapp.presentation;
...
#Path("/test/")
public class MyController {
#Inject
private MyService myService;
#GET
#Path("/foo/{count}")
#OAuthSecurity(scope = "login")
#Produces("application/json")
public Response news(#PathParam("count") int count) {
return Response
.ok(myService.getBar(count))
.build();
}
}
EDIT:
That's my bean
package ch.webapp.service;
...
#RequestScoped
public class MyService {
public String getBar(int count) {
return "foo";
}
}
I initialize jax-rs by extended the MFPJAXRSApplication class
package ch.webapp;
...
public class AccountApplication extends MFPJAXRSApplication {
#Override
protected void init() throws Exception {
}
#Override
protected void destroy() throws Exception {
}
#Override
protected String getPackageToScan() {
return getClass().getPackage().getName();
}
}
Environment details:
Launching mfp (WebSphere Application Server 8.5.5.8/wlp-1.0.11.cl50820151201-1942) on Java HotSpot(TM) 64-Bit Server VM, version 1.8.0_172-b11 (en_CH)
Console Product version: 8.0.0.00-20180717-175523
What's wrong?
First it seems that websphere jax-rs implementation does not integrate jax-rs resources automatically unless you annotate them appropriately.
Put the jax-rs in a CDI managed context by annotating it appropriately
#Path("/test/")
#javax.enterprise.context.RequestScoped
public class MyController {
#Inject
private MyService myService;
#GET
#Path("/foo/{count}")
#OAuthSecurity(scope = "login")
#Produces("application/json")
public Response news(#PathParam("count") int count) {
return Response
.ok(myService.getBar(count))
.build();
}
}
Also be sure that the annotation used for your service is
#javax.enterprise.context.RequestScoped
Based on the inputs provided by you please go through the below checklist.
Your services and controllers are in the same module and its packaging type is war, So you must place your beans.xml in this path src/main/resources/WEB-INF/beans.xml. (If this is Java EE 7 application then beans.xml is optional.
In your AccountApplication class try hardcoding the package name to ch.webapp.presentation
#Override
protected String getPackageToScan() {
return "ch.webapp.presentation";
}
This is just to check Behaviour of MFPJAXRSApplication.getPackageToScan() method whether it is scanning the specified package only or its child packages too.
Except these, everything seems fine to me. If this still doesn't work add complete application startup logs so that community can find the root cause of it.
This is classical mistake. CDI works for managed beans (for instance EJB's and servlets). If you want to enable it on your JAXRS bean, you have to make it "managed", that is annotate MyController as (for instance) javax.annotation.ManagedBean or as a javax.ejb.Stateless.
Also beware that in case of webapp (.war), the beans.xml file has to be located in the WEB-INF folder !

GlassFish 4.1.1: Unable to #Inject simple #Stateless in Java EE 7 JAX-RS App

I am using Glassfish 4.1.1 as my Java server. I am trying to #Inject a simple #Stateless bean in my JAX-RS class having #Path annotation. Here is the exception I am getting:
javax.servlet.ServletException: A MultiException has 1 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=MongoCollectionStore,parent=DemoJaxrsApp,qualifiers={},position=-1,optional=false,self=false,unqualified=null,310751270)
Here is my JAX-RS config:
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/rest")
public class JaxrsAppConfig extends Application {
}
This is how my JAX-RS resource class looks like:
#Path("/tn-collection")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class DemoJaxrsApp {
#Inject
MongoCollectionStore mongoCollectionStore;
#POST
public List<CollectionTO> getColl() {
return mongoCollectionStore.findAll();
}
}
I am using only 2 dependencies:
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
It shouldn't be a problem with dependencies. I am not using any xml files (other than POM.xml and nb-configuration.xml, generated by Netbeans 8.1) as Java EE 7 need not have any config files. I don't know what might have going wrong.
Could anybody please help me out with this UnsatisfiedDependencyException problem?
UPDATE:
Here is my MongoCollectionStore Java class:
#Stateless
public class MongoCollectionStore {
public List<CollectionTO> findAll(MongoConfig mongoConfig) {
List<CollectionTO> tuples = new ArrayList<>();
Gson gson = new Gson();
MongoClient mongoClient = new MongoClient("127.0.0.1", 27017);
MongoDatabase mongoDB = mongoClient.getDatabase("Demo");
MongoCollection<Document> coll = mongoDB.getCollection("DemoCollection");
try(MongoCursor<Document> cursor = coll.find().iterator()) {
while (cursor.hasNext()) {
String jsonDoc = cursor.next().toJson();
CollectionTO tuple = gson.fromJson(jsonDoc, CollectionTO.class);
tuples.add(tuple);
}
}
return tuples;
}
}
I was looking through this problem on internet and found that a CDI bean can only be injected into another CDI bean. They both need to be managed by the container. So, I made my DemoJaxrsApp #RequestScoped, in order to make it a CDI bean.
For guys coming here from Google, Original (and more elaborate) answer can be found here:
Inject an EJB into JAX-RS (RESTful service)
One thing I still don't know is that when I #Injected a #Stateless resource inside my #RequestScoped class, was that resource an EJB? Or, was it a CDI bean? I guess, that's a different question altogether.

Infinispan 6.0 CDI and default configuration

I'm having problems defining configuration for a CDI application (glassfish 4).
I have:
#CacheResult(cacheName = "example")
public String getSomething(String something){
logger.debug("getSomething "+something);
return "this is "+something;
}
This works as expected, the second time is called is not executed because it's cached
However, I want to specify a configuration for my caches. I have tried writing a infinispan.xml file (in src/main/resources), but it's ignored. I have also tried with both:
#Produces
#Default
public Configuration defaultEmbeddedCacheConfiguration() {
return new ConfigurationBuilder().expiration().lifespan(3000l)
.eviction()
.strategy(EvictionStrategy.LRU)
.maxEntries(2)
.build();
}
#Produces
#ApplicationScoped
public EmbeddedCacheManager defaultEmbeddedCacheManager() {
return new DefaultCacheManager(defaultEmbeddedCacheConfiguration());
}
But these methods are never called.
I have also tried with #ConfigureCache
My dependencies are:
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-cdi</artifactId>
<version>6.0.2.Final</version>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-jcache</artifactId>
<version>6.0.2.Final</version>
</dependency>
Any ideas?
Thx

How to execute a jar file on jboss7 startup?

I have a simple java class which displays "waiting" text on execution , in "TMSCore" java project.
package com.stock.bo;
public class example {
/**
* #param args
*/
public static void main(String[] args) {
// ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("================================> waiting");
}
}
I have created TMSCore.jar and have set this example.class as entry point ,of my jar file.
Then i have created a module for this project in C:\Jboss\jboss-as-7.1.1\modules\org\tms\main , and pasted the jar in the same path
then i have created module.xml and pasted in the same path
module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.tms">
<resources>
<resource-root path="TMSCore.jar"/>
</resources>
</module>
then i have created a jboss-deployment-structure.xml in my webproject/web-inf directory
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.tms"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
when i start the server with my war containing above jboss-deployment-structure.xml, in my console its showing deployed TMSCore.jar
but my "waiting" text in my jar is not displayed on console
my requirement is i should get "================================> waiting" on my console once jboss is started up
or else can any one can suggest how to make a jar to execute on starting jboss server?
BTW i am using JBOSS7.1
If I am right it's because JBoss doesn't execute a library, it only loads the classes contained in the jar file. So putting a main function and generating an executable jar will not help.
If your goal is to have an global module on the server, I suggest you these modifications:
Create the module (as you have already done)
Declare it as dependency in jboss-deployment-structure.xml (as you have already done)
Declare it as global module on the server, so it will be loaded only once by JBoss. Edit the configuration file standalone.xml and modify the section:
<subsystem xmlns="urn:jboss:domain:ee:1.0">
<global-modules>
<module name="org.tms" />
</global-modules>
</subsystem>
Now you have a module that have classes loaded only once. I you need to have only one instance of your Example class, the I suggest you to use an singleton:
public class Example {
// The only one instance
private static Example instance;
// Private constructor to avoid creation of other instances of this class
private Example()
{
System.out.println("================================> waiting");
}
public static Example getInstance()
{
if(instance == null)
{
instance = new Example();
}
return instance;
}
}
Then to use it in all projects on the server
Example ex = Example.getInstance();
will give you back the existing instance (or create one the first time).
Notice: I can't try, so no guarantee that that will work.
Edit: Maybe a small modification of the Example class can also make it run during the classes loading:
public class Example {
// The only one instance
private static Example instance = new Example();
// Private constructor to avoid creation of other instances of this class
private Example()
{
System.out.println("================================> waiting");
}
public static Example getInstance()
{
return instance;
}
}
Again: not tested.
You can't run a jar, but you can execute a startup method in a singleton.
#Startup
#Singleton
public class FooBean {
#PostConstruct
void atStartup() { ... }
#PreDestroy
void atShutdown() { ... }
}
This will happen at application start up and shutdown. I'd call the function you need from there.
See http://docs.oracle.com/javaee/6/tutorial/doc/gipvi.html