In the service activator documentation it says:
Using a "ref" attribute is generally recommended if the custom Service Activator handler implementation can be reused in other definitions.
But the below snippet gives me
IllegalArgumentException: An AbstractReplyProducingMessageHandler may only be referenced once
<bean id="groupResequencer" class="com.core.flow.GroupResequencer"/>
<int:service-activator id="groupResequencer1" ref="groupResequencer"/>
<int:service-activator id="groupResequencer2" ref="groupResequencer"/>
When I change my bean definition to prototype it works but the onInit() method gets called twice, once with a generic component name and the second time with the spring integration service activator id as component name.
It doesn't matter to me whether the bean is singleton or prototype but I need a clean creation that happens only once.
We need to improve that documentation - it only applies when the ref references a POJO.
Some time ago, we added an optimization to service activator such that if the ref bean is an AbstractReplyProducingMessageHandler we reference it directly rather than wrapping it in a new handler, to avoid that overhead.
Since such a bean can only have one outputChannel we can't use it in more than one endpoint. Making it a prototype means each service activator gets its own instance.
If you change your bean to a POJO rather than extending from ARPMH you can reuse it that way.
Related
I am have created the camel route which use camel-paho component to consume MQTT stream. It is enabled with SSL and i need to pass the socket-factory. I went through the documentation od camel-paho and below parameter is available
socketFactory (security)
Sets the SocketFactory to use. This allows an application to apply its own policies around the creation of network sockets. If using an SSL connection, an SSLSocketFactory can be used to supply application-specific security settings.
I have passed the custom socket-factory in the URL by setting the above parameter to the class name as below
from("paho:"test?brokerUrl="+MQTT_BROKER_URL+"&clientId=subX4&cleanSession=false&socketFactory=com.sample.mqttCustomSocketFactory.java")
Above setting is not working. Is that the correct way of passing the parameter ?
Whenever you set a complex object to the Camel endpoint parameter, it needs to be a bean reference. So in your case, the endpoint should look something like this:
from("paho:test?...&socketFactory=#mySocketFactory")
where the #mySocketFactory is defined in the Camel bean registry like this:
SocketFactory mySocketFactory = ...
context.getRegistry().bind("mySocketFactory", mySocketFactory);
or in Spring context XML:
<bean id="mySocketFactory" ...>
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
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.
I have a general question. We are upgrading some old code to v4.1.3 of spring-integration. Let's say we have a service activator that receives a domain object of type Foo, and returns the same object on the output channel (after changing some properties of that object).
Our existing code has signatures like below. Is it the right convention? If I don't need the headers, can I return my payload directly and will the framework wrap it into a Message?:
public Message<Foo> computeValue(Foo payload, #Headers Map<String, Object> headerMap) {
//...
return MessageBuilder.withPayload(payload).copyHeaders(headerMap).build();
}
Yes, you don't need do that. More over that is pointless because in case of Service Activator the Framework populates request headers to the reply message independently of your effort.
So, consider do not care about headers at all if you don't need to do some specific logic on the matter.
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.