Camel hiding middleware API send JMS exchange with headers - java

Does anybody know how to follow this recommendation at [camel pojo producing][1]:
We recommend Hiding Middleware APIs from your application code so the
next option might be more suitable. You can add the #Produce
annotation to an injection point (a field or property setter) using a
ProducerTemplate or using some interface you use in your business
logic. e.g.
public interface MyListener {
String sayHello(String name);
}
public class MyBean {
#Produce(uri = "activemq:foo")
protected MyListener producer;
public void doSomething() {
// lets send a message
String response = producer.sayHello("James");
}
}
Here Camel will automatically inject a smart client side proxy at the
#Produce annotation - an instance of the MyListener instance. When we
invoke methods on this interface the method call is turned into an
object and using the Camel Spring Remoting mechanism it is sent to the
endpoint - in this case the ActiveMQ endpoint to queue foo; then the
caller blocks for a response.
but with headers, in order to work with this line of DSL:
from("jms:activemq:toBeStored").recipientList(header("stores").tokenize(",")).parallelProcessing().ignoreInvalidEndpoints();
which I have successfully tested with the method of #EndpointInject
public class Foo {
#EndpointInject(uri="activemq:foo.bar")
ProducerTemplate producer;
public void doSomething() {
if (whatever) {
producer.sendBodyAndHeader("<hello>world!</hello>", "stores","store1");
}
}
}
like as described before the recommendation.
In brief: how can I make the injected smart client side proxy send also the headers I want?
thanks

Related

How do I share an interface between a graphql server and a graphql client

I am currently reevaluating a graphql stack at work. We iterate fairly quickly on our internal graphql API and the iterations get more and more painful to manage, especially for the consumers, due to breaking changes in the API. Therefore, I would like to pursue a code-first approach in java. By that I mean I want to share the classes for our domain model between the server side and client side. In addition, I want one or more java interfaces to define a set of public methods which returns objects of our domain model classes. The purpose of the interfaces is to make a contract or public API between the server and client to ensure both sides implements the contract. Our graphql API is the main product but I want to hide the API slightly and rather expose a java client.
Main objective: How to obtain a versioned graphql API hosted by a versioned server and a versioned reference client in java for customers of the graphql API. On new releases of the graphql API I want to be able to release a corresponding client and domain model.
So far i have been playing around with the Quarkus extensions quarkus-smallrye-graphql and quarkus-smallrye-graphql-client.
Interface
#GraphQLClientApi(configKey = "star-wars-typesafe")
public interface StarWarsClientApi {
List<Film> allFilms();
}
Client
#Path("/")
#ApplicationScoped
public class StarWarsResource {
#Inject
StarWarsClientApi client;
#GET
#Path("/typesafe")
#Produces(MediaType.APPLICATION_JSON)
#Blocking
public List<Film> getAllFilmsUsingTypesafeClient() {
return client.allFilms();
}
}
Server
#GraphQLApi
public class FilmResource implements StarWarsClientApi{
#Inject
GalaxyService service;
#Query()
#Description("Get all Films from a galaxy far far away")
public List<Film> allFilms() {
return service.getAllFilms();
}
}
Then I run into a AmbiguousResolutionException. Which I guess makes sense, even for me. Afterwards, I tried to define a Qualifier called #Client. Now I am facing a UnsatisfiedResolutionException. And by now my knowledge and creativity stops in regards to CDI.
Anyone who can pinpoint what I am doing wrong or suggest an alternative approach to achieve the main objective from above?
Interface
#GraphQLClientApi(configKey = "star-wars-typesafe")
#Client
public interface StarWarsClientApi {
List<Film> allFilms();
}
Client
#Path("/")
#ApplicationScoped
public class StarWarsResource {
#Inject #Client
StarWarsClientApi client;
#GET
#Path("/typesafe")
#Produces(MediaType.APPLICATION_JSON)
#Blocking
public List<Film> getAllFilmsUsingTypesafeClient() {
return client.allFilms();
}
}

Send namespaced data from Service to Client in Java

Consider I have a bunch of data processors extending the same interface :
IProcessor.java
public interface IProcessor() {
void processName(String name);
}
BookProcessor.java
public class BookProcessor implements IProcessor {
#Override
public void processName(String name){
//Process name in book specific logic
}
}
MagazineProcessor.java
public class MagazineProcessor implements IProcessor {
#Override
public void processName(String name){
//Process name in magazine specific logic
}
}
All of these processors reside in a client, say MyClient and this client receives data from a service, say MyService.
I want to implement namespacing so that from this namespacing, MyClient can pick up the correct processor automatically. For this I was thinking MyService itself should send namespaced data (maybe namespaced id). My question how do I implement this namesapcing so that both MyService and MyClient are sharing it even when MyService has no knowledge about the processors that are present in MyClient.
When MyService sends data to MyClient, it has to provide a hint on what type of data it's sending. So that MyClient can pick up the right processor for this type of data.
So the right approach would be:
Make a contract between a client and the server which states what type of data the server can send. And then, on the client side, you should implement a matcher, which matches a data type to its processor.
So that MyService does not know anything about data processors a client can use. It just knows what it's sending.

CXF-Proxy Client and #Suspended AsyncResponse

I recently learned that with JAX-RS 2.0 long running service endpoints can make use of the #Suspended annotation and AsyncResponse to free resources for incoming requests while the actual work is done in the background. All client examples - at least the ones I found so far - are either calling such endpoints directly (plain http-call) or make use of the JAX-RS client API. However I was not able to figure out how to use this with the proxy-based API.
Given a REST endpoint that uses #Suspended:
public interface HeavyLiftingService {
#GET
#Path("/heavylifting")
public void heavyLifting(#Suspended final AsyncResponse aResponse);
}
its implementation using Spring:
#Component
public class HeavyLiftingServiceImpl implements HeavyLiftingService {
#Override
#Async
public void heavyLifting(#Suspended final AsyncResponse aResponse) {
final Result result = doHeavyLifting();
aResponse.resume(result);
}
}
And a proxy-based client, that wants to obtain the result:
HeavyLiftingService proxy = JAXRSClientFactory.create("https://some-server.xyz", HeavyLiftingService.class);
proxy.heavyLifting(null); // what to put in here?
Result result = null; // how can I get the result?
Obviously there are two problems:
What do I need to provide to the heavyLifting method as value for the AsyncResponse parameter?
How can I get the result as the return type of methods using #Suspended has to be void?
And another question is how exceptions in the service method are handled. Will an exception automatically resume the response and return a corresponding error status?

Apache Camel: Can I use #Produce without specifying the endpoint uri in the annotation?

In the camel documentation, it is mentioned that we can inject the ProducerTemplate using the #Produce annotation as shown below.
#Produce(uri = "activemq:foo")
private ProducerTemplate producer;
I am wondering if it is possible not to specify the uri in the annotation and pass the uri to the producer in its sendBody method, like below, so that I can use this in a Util class to produce to any endpoint?
public class JmsProducerUtils {
#Produce
private ProducerTemplate producer;
public void publishMessageToEndpoint(String endpoint, String message) {
producer.sendBody(endpoint, message);
}
}
Are there any concerns, to be aware of, in using it like this?
Well, no worries, it should definitely work - you can write a simple unit test to verify it - but unless your URIs are dynamically formed in runtime I would suggest using the approach they mention in their documentation e.g. have an interface:
#InOnly
public class JmsProducer {
void publish(String message);
}
and then inject it in your class like so:
public class Foo {
#Produce(uri = "activemq:foo")
private JmsProducer fooProducer;
#Produce(uri = "activemq:bar")
private JmsProducer barProducer;
}
If in doubt, create a URI that starts with "stub:" (ex "stub:noUri")
From https://camel.apache.org/components/3.18.x/stub-component.html
The Stub component provides a simple way to stub out any physical endpoints while in development or testing, allowing you for example to run a route without needing to actually connect to a specific SMTP or Http endpoint. Just add stub: in front of any endpoint URI to stub out the endpoint.

Using Spring Integration to route domain objects to the appropriate method

I have recently started looking into Spring Integration as a result of this question and have a question about object-type based routing.
The application I am maintaining needs to process requests from an incoming ActiveMQ queue (request.queue) and send a response back to the caller on a topic (response.topic). At present the requests are structured as follows:
public abstract class Request {
// base class
}
public abstract class CustomerRequest extends Request {
// base class for customer-specific requests
}
public class FindCustomerByIdRequest extends CustomerRequest {
private int id;
}
public class FindAllCustomersRequest extends CustomerRequest {
private boolean includeArchivedCustomers;
}
public class AddCustomerRequest extends CustomerRequest {
private String name;
private Date signupDate;
private Address address;
}
I have a service for each high level domain object which provides the functionality to service these incoming requests:
#Service
public class CustomerService {
public CustomerResponse findCustomerById(FindCustomerByIdRequest request) {
// code snipped
return customerResponse;
}
public AddCustomerResponse addCustomer(AddCustomerRequest request) {
// code snipped
return addCustomerResponse;
}
}
I need to route each specific request to the approriate method in CustomerService via #ServiceActivator which I understand can be done by creating a separate channel for each request and implementing a PayloadTypeRouter to place requests on the correct channel based on type.
Over time the list of request types is going to grow, and I am questioning whether a one-channel-per-request setup is efficient/practical/scalable. For example, if there are 100 different request types in the future there are going to be 100 different channels.
What would be great is if I could route the high-level requests of superclass CustomerRequest to CustomerService and have Spring work out the approriate method to call via an annotation or some other mechanism. Does anyone know if this is possible, or have any comments regarding the many-channels approach?
If there is no ambiguity, use <service-activator ... reg="fooBean" /> (no method) and the framework will chose the target method based on the payload.
If there is ambiguity (more than one method for the same type), it will fail.
However, a single class with 100+ methods is probably not a good design.
It seems to be that your request types are app feature specific. This suggest that you have one queue for all the possible application features. That is horrible idea. You should have at least separate queue per feature.
I suggest to rethink the design of your app.

Categories