Explicitly declaring service gateway in Java configuration - spring

I have an application using Spring Integration where I have multiple handlers (strategies) for some service gateway methods, and I want the deployment launcher to be able to select which specific handlers are loaded. Since component scanning will pick up all of the handlers indiscriminately, I prefer to explicitly declare JavaConfig #Beans for them.
This works fine for the service objects themselves, but I can't find a way to load the service interface itself in Java without #IntegrationComponentScan. My current workaround is to include a "one-liner" XML file with an <int-gateway> tag and #ImportResource it, but I'd really prefer a more direct solution.
Is there any straightforward way in JavaConfig to tell Spring Integration to create a proxy service interface for a specific class?

GatewayProxyFactoryBean is for you.
This class is used to populate bean definition from <int:gateway> tag and from MessagingGateway annotation.
So, you can do like this:
#Bean
public GatewayProxyFactoryBean myGateway() {
GatewayProxyFactoryBean factoryBean = new GatewayProxyFactoryBean(YourServiceInterface.class);
factoryBean.setDefaultRequestChannel(gatewayRequestChannel());
return factoryBean;
}

Related

How to make a bean discoverable by Quarkus CDI without using annotations

I have a simple Quarkus resource:
#Path("/rosters")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class RosterResource {
private final RosterService rosterService;
public RosterResource(RosterService rosterService){
this.rosterService = rosterService;
}
#GET
#Path("/{rosterId}")
public Response getRoster(#PathParam("rosterId")Long rosterId){
return Response.ok(rosterService.getRosterById(rosterId)).build();
}
}
I am trying to inject the RosterServiceinstance in my resource, but I am getting a javax.enterprise.inject.UnsatisfiedResolutionException. However, if I use the #ApplicationScoped annotation on RosterService, then everything works just fine. Is there a way of injecting the RosterService class in my resource without using annotations? In other words, is there a way of making RosterService discoverable by the Quarkus container without directly annotating the class?
Edit: looking into the CDI docs, it seems that you can manually register beans using a method with a #BuildStep annotation. However, it is not clear to me which class should contain the annotated method)
Another option would be to use a Jandex index
To the best of my knowledge, Quarkus only implements so called annotated bean discovery. That means that all CDI beans in Quarkus have to have a bean defining annotation. #ApplicationScoped is one of them.
EDIT: regarding a Jandex index, that allows you to scan for beans in additional JARs. In other words, it will only expand the set of classes that are scanned for a bean defining annotation.
When it comes to a #BuildStep method -- that is only possible in a Quarkus extension. Extensions are powerful (and indeed they can define additional beans) but also complex. You can start at https://quarkus.io/guides/building-my-first-extension, but it may feel overwhelming. It may also feel like this is not the right thing to do if you want to just make your class a bean -- and that would be true. But if your class comes from an external library that you can't change, extension makes sense.
Is there a specific reason why you don't want to annotate your service class with #ApplicationScoped (or any other of the bean discover/scope annotations)?
The only other way that I'm aware of (instead of annotations) is - as you yourself mentioned - the use of Jandex index.

Spring boot: Instantiating Spring java configuration class

I am converting a Spring legacy application based on XML to Spring Boot with java based configuration.
My question is, is it possible to instantiate same bean class with different bean names?
Example:
#Configuration
public class HelloWorldConfig {
#Bean
public HelloWorld helloWorld(){
return new HelloWorld();
}
}
Can I have Spring boot instantiate above helloWorld bean using dynamically generated names like
helloWorld_1, helloWorld_2 etc in a loop? I want to control the naming of these beans. _1, _2 is something I will provide and these actually are IP Addresses.
All these beans are instances of same class HelloWorld.
Here is more context to what I am asking.
I am performing a distributed transactions on several data sources. These data sources can be anywhere from 2 to N. Now, I need to instantiate session factories, transaction managers and Dao impl classes one for each of these data sources. This is my usecase. I am not building a web application, but a console application. Just to be clear.
Really appreciate, if there is a way out for this problem.

How to inject a bean in my own WireMock Extension in Spring Cloud Contract

I successfully registered my own Wiremock extension by using the spring.factories approach described in the documentation (8.5.6 Registering Your Own WireMock Extension) but I also need to inject a bean in the class that implements the WireMockExtensions in order to pass it down to my custom extension, to provide some services to my custom extension.
I tried to use Autowired in the class that implements the WireMockExtensions but it doesn't work.
You can't out of the box. Since we're using the spring.factories mechanism, it's creating the extensions via new.
What you can do is try to access the application context statically from your extension. What you can do is to create a bean in test scope that will contain a static field in which applicationContext will be injected. Then from outside Spring context you will be able to access it.
Also, why do you need Spring context in a WireMock extension?

Why do we need #Component spring annotation for Jersey resource in spring-boot-starter-jersey project?

This question is regarding the sample:
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-jersey/src/main/java/sample/jersey/Endpoint.java
Why do we need "#Component" annotation for Jersey resource when using spring-boot -starter-jersey project?
If I remove it, the Jersey servlet can still serve resources.
So what is the need for "#Component"?
You don't need it. Jersey uses HK2 as it's internal DI framework, and HK2 has a Spring bridge. This is what's used internally to bridge Spring components into the HK2 IoC container, so that they can be injected into Jersey components. And Jersey implements an AutowiredInjectionResolver1 that allows for injection of Spring components using #Autowired. You don't even need #Autowired though. All the Spring components can be injected with the normal #Inject.
The only drawback I've ran into, not making the Jersey components a Spring #Component is that it doesn't support #Value when you want to inject property values.
The one thing I don't like is that when you declare something a Spring #Component, it automatically makes it a singleton. But Jersey resources are by default request scoped. You can add a Spring #Scope("request"), and it should change the resource to a request scoped resource. Jersey has declared the Spring RequestScope, so we can use it. How exactly it ties in to Jersey's request scope, I am not a hundred percent sure. I ran into a problem a while back. I can't remember what it was, but that has kept me from ever using the Spring request scope again.
Assuming I want to keep all my resources request scoped, I would take sticking to the normal Jersey request scope, and not being able to inject #Values, over having to use Spring's request scope. Maybe I'm imagining things, and there was no issue using it, but personally I'll just stick to what I know works :-)
UPDATE
Another thing that does't work if you don't make the resource a Spring #Component is Spring's AOP. That's fine with me though as HK2 also has AOP.
1 - An InjectionResolver allows you to use custom annotations to create injection targets.
When you remove #Component jersey takes control of the scope of the instance. With #Component a singleton instance is created, removing it you can use the following jersey annotations:
• Request scope (Default):
By using the #RequestScope annotation or none, we can have a life-cycle till
the request lasts. This is the default scope of the root-resource classes. For
each new request, a new root-resource instance is being created and served
accordingly for the first time. However, when the same root-resource method
is being called, then the old instance will be used to serve the request.
• Per-lookup scope:
The #PerLookup annotation creates root-resource instances for every request.
• Singleton:
The #Singleton annotation allows us to create only a single instance
throughout the application.
Try different behaviors using a counter inside your class...
public class MyWebResource {
private int counter;
#GET
#Path("/counter")
#Produces(MediaType.APPLICATION_JSON)
public Response getCounter() {
counter++;
return Response.status(Status.OK).entity(counter).build();
}
}

Spring fallback bean implementation

I'm currently trying to configure Spring Boot (using Java Annotations and ComponentScan) for the following scenario:
Scenario
There's an interface MyService.
I want to provide a default implementation for MyService, let's call it MyDefaultService.
If the component scan detects no other implementation for MyService, Spring should instantiate MyDefaultService as a "fallback".
If there is a different implementation of MyService present, let's say MyCustomService, then that bean should always take precedence over MyDefaultService when autowiring a dependency to MyService. In that regard, MyDefaultService should be recessive (as opposed to #Primary).
Ideally, there should not need to be an additional annotation on MyCustomService to have it "override" MyDefaultService.
Ideally, no explicitly implemented factories or factory methods should be required.
Question
The question is: how do I need to annotate the MyDefaultService class in order to achieve this?
What I tried so far to solve the problem
Annotating MyDefaultService with #ConditionalOnMissingBean(MyService.class). Didn't work because MyDefaultService is never used, even if there is no other implementation of MyService.
There is an annotation called #Primarythat solves the problem. However, it needs to reside on MyCustomService, a class that I try to keep free of additional annotations. Essentially, I need the inverse annotation of #Primary on MyDefaultService. However, I couldn't find such an annotation.
Concrete use case
I am developing a service layer in one project, and a different project will implement a web UI layer on top of it. The UI project has a dependency to the service layer project. However, for certain functionalities implemented at the service layer, I need to know which user is currently logged in at the web context. So I have to define a service interface for that in the service layer project, such that it can be implemented by the UI project. However, for testing purposes in the service-layer project, I need a default implementation of that interface. Also, in case that the UI project team forgets to implement this interface, the app should not crash, but instead instantiate the fallback bean and issue a warning.
Thanks & kind regards,
Alan
I suggest writing an implementation of FactoryBean to do this. Your FactoryBean would scan the bean factory looking for beans that implement MyService, and if it finds one it returns that bean from getObject. If it doesn't, then it can instantiate MyDefaultService directly and return that. Your factory bean then gets annotated with #Primary.
So pieces like this (pseudo-code):
public class MyServiceFactory implements FactoryBean<MyService> {
ListableBeanFactory beanFactory;
public MyService getObject() {
Map beans = beanFactory.getBeansOfType(MyService.class)
if (beans.isEmpty())
return new MyDefaultService(); // plus args, obviously
else
return get_some_bean_from_the_map
}
}
and then
#Primary
#Bean
public MyServiceFactory MyServiceFactory() {
return new MyServiceFactory();
}
Spring will automatically handle the factory bean (i.e. it will make the MyService object available as a bean for injection like normal.
This solution doesn't require any special magic, and it's fairly obvious how it works. You can also handle errant cases such as multiple MyService beans being declared.

Resources