Can you spy on the Vert.x event bus in Quarkus tests? - mockito

Does anyone know of a way to spy on the Vert.x event bus in Quarkus tests? Ideally I'd like to assert that during a method in the service layer we are sending an event to the correct address, but does anyone know if this is possible?
If I just try to use #InjectMock I get the following error
io.vertx.core.eventbus.impl.EventBusImpl#5769679b is not a normal scoped CDI bean, make sure the bean is a normal scope like #ApplicationScoped or #RequestScoped

I solved this Problem, by creating an ApplicationScoped Delegate around the EventBus. This Delegate can be mocked and inspected as a normal bean in Quarkus. All the Beans which were using the EventBus directly need to use the EventBusDelegate instead. In your test you can use the #InjectMock annotation to inject the EventBusDelegate mocked.

As suggested here https://github.com/quarkusio/quarkus/issues/8983
#InjectMock(convertScopes = true)
should solve your problem. If convertScopes is true, then Quarkus will change Singleton to ApplicationScoped to make the bean mockable.
NOTE: the documentation states that this is an advanced setting and should only be used if you don't rely on the differences between Singleton and ApplicationScoped beans

Related

How to create a CDI Interceptor which advises methods from a Feign client?

I've been trying to figure out how to intercept methods defined in a Feign client with CDI (1.2) interceptors. I need to intercept the response value the client is returning, and extract data to log and remove some data prior to it being returned to the calling process.
I'm running a Weld 2.3 container which provides CDI 1.2. In it, I would like to create a CDI interceptor which is triggered everytime a call to filter() is made.
public interface MyRepository {
#RequestLine("POST /v1/data/policy/input_data_filtered")
JsonNode filter(Body body);
}
and a matching Producer method:
#Produces
public MyRepository repositoryProducer() {
return Feign.builder()
.client(new ApacheHttpClient())
.encoder(new JacksonEncoder(mapper))
.decoder(new JacksonDecoder(mapper))
.logger(new Slf4jLogger(MyRepository.class))
.logLevel(feign.Logger.Level.FULL)
.target(MyRepository.class, "http://localhost:9999");
}
I've tried the standard CDI interceptor way by creating an #InterceptorBinding and adding it to the interface definition, but that didn't work. I suspect because the interceptor must be applied to the CDI bean(proxy) and cannot be defined in an interface. I tried applying it to the repositoryProducer() method but that too was non functional.
I've read about the javax.enterprise.inject.spi.InterceptionFactory which is availabel in CDI 2.0, but I don't have access to it.
How can I do this in CDI 1.2? Or alternatively, is there a better interceptor pattern I can use that is built into Feign somehow?
The short, somewhat incorrect answer is: you cannot. InterceptionFactory is indeed how you would do it if you could.
The longer answer is something like this:
Use java.lang.reflect.Proxy to create a proxy implementation of the MyRepository interface.
Create an InvocationHandler that performs the interception around whatever methods you want.
Target Feign at that proxy implementation.

How to inject an #Normal (#ApplicationScoped) bean into a #Dependent scope if the bean does not have a no-arg constructor

This post is related to an older SO Post of mine, wherein I was trying to understand the requirements of a no-args constructor by WELD.
Right now, I'm trying to figure out if there is a way in CDI to inject an #ApplicationScoped bean (#Normal) into a #Dependent scope. From what I've read from WELD, the requirements are to have a non-private no-arg constructor to be proxyable. However, I do not have control over the bean definition as it is provided by a library. My code is doing the following:
#Produces
#ApplicationScoped
#Named("keycloakAdmin")
public Keycloak getKeycloakAdminClient(#Named("keycloakDeployment") final KeycloakDeployment deployment) {
String clientId = deployment.getResourceName();
Map<String, Object> clientCredentials = deployment.getResourceCredentials();
// need to set the resteasy client connection pool size > 0 to ensure thread safety (https://access.redhat.com/solutions/2192911)
ResteasyClient client = new ResteasyClientBuilder().connectionPoolSize(CONNECTION_POOL_SIZE).maxPooledPerRoute(CONNECTION_POOL_SIZE)
.defaultProxy("localhost",8888)
.build();
KeycloakBuilder builder = KeycloakBuilder.builder()
.clientId(clientId)
.clientSecret((String) clientCredentials.get(CredentialRepresentation.SECRET))
.realm(deployment.getRealm())
.serverUrl(deployment.getAuthServerBaseUrl())
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.resteasyClient(client);
return builder.build();
}
// error thrown here that cannot inject #Normal scoped bean as it is not proxyable because it has no no-args constructor
#Produces
#Dependent
#Named("keycloakRealm")
public RealmRepresentation getKeycloakRealm( #Named("keycloakAdmin") final Keycloak adminClient ){
// error thrown here that cannot inject #Normal scoped bean as it is not proxyable because it has no no-arg
return adminClient.realm(resolveKeycloakDeployment().getRealm()).toRepresentation();
}
The problem is that I do not control the Keycloak bean; it is provided by the library. Consequently, I have no way of providing a no-argument constructor to the bean.
Does this mean it is impossible to do? Are there any workarounds that one can use? This would seem like a significant limitation by WELD, particularly when it comes to #Produceing 3rd party beans.
My goal is to have a single Keycloak bean for the application as it is thread-safe and only needs to be initialized once. However, I want to be able to inject it into non-application-scoped beans.
There is a #Singleton scope which may address my issue, but if #Singleton works for this case, what is the purpose of the 2 different scopes? Under what circumstances would one want a non-proxied singleton (#Singleton) vs a proxied one (#ApplicationScoped)? Or is #Singleton for the entire container, whereas #ApplicationScoped for the application (WAR) only instead? How does it apply to an EAR or multiple ears?

Are jaxrs 1.1 (WLP 8.5) annotated methods thread safe?

I am using jaxrs1.1 jar shipped with Websphere liberty profile 8.5 for creating REST WebService.
Lets suppose we have a method addNewProject as shown below :
If many people call this webservice method to add project concurrently. using link below , are there any concurrency issue? In servlet, each request is a separate thread , is it the same case here or should we handle concurrency by ourselves ?
endpointLink: http://somehost.com/path1/path2/addprojectdetails and POST the JSON object.
#POST
#Path("addprojectdetails")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response addNewProject(ProjectDetails projectdetailsObj) {
return Response.status(200).entity("Project"+projectdetailsObj.getProjectname()+"successfully added").build();
}
I'm not sure what kind of concurrency issues you might be thinking of. The object itself can be either a singleton or request scoped (if using CDI) or a stateless session bean (if using EJB). If you're using a singleton, then you may need to be thread aware and not store state within the class.
It would probably help to understand what kind of concurrency issues you had in mind to answer more thoroughly.

How to make a serviceloader created class handle container managed objects

I'm currently writing a library where I want the user of my library to implement an interface. From within my library I'm calling this implementation.
I'm using ServiceLoader to instantiate the implementation provided by the integrator and it works just fine. The integrator calls a start() method in my library and in the end he gets something in return. The implementation is used to give me some things along the way that I need in order to get to the final result.
(I'm deliberately not using CDI or any other DI container 'cause I want to create a library that can be used anywhere. In a desktop application, a spring application an application using guice...)
Now I'm facing a problem. I'm creating a showcase in which I'm using my own library. It's a webapplication where I'm using jsf and CDI. When I instantiate the implementation provided in said webapp from within my library, I'm dealing with a non-container managed object. But since this implementation needs to use container managed objects I'm kinda screwed since this can never work.
Example:
Interface in lib:
public interface Example{
public abstract String getInfo();
}
Implementation in war:
public class ExampleImpl implements Example{
#Inject
private ManagedBean bean;
public String getInfo(){
return bean.getSomethingThatReturnsString();
}
}
As you can see this is a huge problem in the way my library is build since the bean will always be null... This means no one using a DI container can use my library. I know I can get the managedbean by doing a FacesContext lookup and get the managedbean but more importantly, my library isn't very well designed if you think about it.
So to conclude my question(s):
Is there any way I can make the serviceloader use a DI container to instantiate the class?
Anyone who knows a better way to fix my problem?
Anyone who knows a better way to get the things I need without making the integrator implement an interface but I can get information from the integrator?
I know this is a quite abstract question but I'm kinda stuck on this one.
Thanks in advance
As the implementation of Example is not performed within the CDI container the injection doesn't happen. What you can do is to lookup the bean manually using the BeanManager. According to the docs, the BeanManager is bound to the jndi name java:comp/BeanManager. Using the following code you can get the BeanManager within your implementation class and lookup the dependencies manually:
InitialContext context = new InitialContext();
BeanManager beanManager = (BeanManager) context.lookup("java:comp/BeanManager");
Set<Bean<?>> beans = beanManager.getBeans(YourBean.class, new AnnotationLiteral<Default>() {});
Bean<YourBean> provider = (Bean<YourBean>) beans.iterator().next();
CreationalContext<YourBean> cc = beanManager.createCreationalContext(provider);
YourBean yourBean = (YourBean) beanManager.getReference(provider, YourBean.class, cc);
where YourBean is the dependency you are looking for.

How can I initialize a Java FacesServlet

I need to run some code when the FacesServlet starts, but as FacesServlet is declared final I can not extend it and overwrite the init() method.
In particular, I want to write some data to the database during development and testing, after hibernate has dropped and created the datamodel.
Is there a way to configure Faces to run some method, e.g. in faces-config.xml?
Or is it best to create a singleton bean that does the initialization?
Use an eagerly initialized application scoped managed bean.
#ManagedBean(eager=true)
#ApplicationScoped
public class App {
#PostConstruct
public void startup() {
// ...
}
#PreDestroy
public void shutdown() {
// ...
}
}
(class and method names actually doesn't matter, it's free to your choice, it's all about the annotations)
This is guaranteed to be constructed after the startup of the FacesServlet, so the FacesContext will be available whenever necessary. This in contrary to the ServletContextListener as suggested by the other answer.
You could implement your own ServletContextListener that gets notified when the web application is started. Since it's a container managed you could inject resources there are do whatever you want to do. The other option is to create a #Singleton ejb with #Startup and do the work in it's #PostCreate method. Usually the ServletContextListener works fine, however if you have more than one web application inside an ear and they all share the same persistence context you may consider using a #Singleton bean.
Hey you may want to use some aspects here. Just set it to run before
void init(ServletConfig servletConfig)
//Acquire the factory instances we will
//this is from here
Maybe this will help you.

Resources