Execute a camel route directly - java

I recently took over some Java code and there was a method that took in an object and based on some properties of that object, performed some processing on that object.
I was playing around with Apache Camel and was able to define a route that accomplished the same task. Where I am struggling is, how can I find the easiest way to pass an object to the route and execute the logic? What I have right now is a
producerTemplate.sendBody("direct:blah", myObject)
and the route itself defines a
from("direct:blah").process(...)
The above is working fine, albeit a little slower than before.
Is this the simplest way to replace the logic of a method? I was hoping to just be able to grab the route itself and pass an object to it for execution, but I don't see any ways to do this.

You don't necessarily need a from().process(). You can also inject an endpoint to your method. For example:
#Consume(uri = "direct:blah")
public void onFileSendToQueue(String body, #Header("CamelFileName") String name) {
LOG.info("Incoming file: {}", name);
producer.sendBody(body);
}
You can do the same for producers as well. See the Camel pojo messaging for more details.
http://camel.apache.org/pojo-messaging-example.html

Related

Struts2 application scope instances

I've inherited a Struts2 project which needs some functionality addition. When I ran into de code to guess how the previous guy did things, I found out that if he wants a class to instantiate only once when the Tomcat server starts (because it has to read heavy loads of data from disk, but only once to get its config, for instance), he did this in the following way:
public class ExampleClass {
public ExampleClass(){//Read files and stuff to initialize}
public Object method(Object[] args){//The job to do}
}
And then, in the struts action which uses it he instantiates it this way:
public class SomeAction extends ActionSupport {
ExampleClass example = new ExampleClass()
public String execute() {
//Do stuff every time the action is called
Object result = example.method(args);
// Do stuff with results
}
}
I know from servlet times that this does the trick, however, I feel like the guy who handled this before was as inexperienced in Struts2 as I am, so here comes my question:
Is this the proper way to do so according to style recommendations and best practices? Does struts2 provide a more controlled way to do so?
I found some answers related to simple parameters here, but I'm not sure if this is the proper way for objects like those? What would happen if ExampleClass instance is really heavy? I don't want them to be copied around:
How to set a value in application scope in struts2?
Some background about ExampleClass: When the constructor is called, it reads large sets of files and extracts it's configurations from them, creating complex internal representations.
When method() is called, it analyzes it's parameters using the rules, and outputs results to the user. This process usually takes seconds, and doesn't modify the previously initialized rule values.
This is running in Tomcat 7, however, I'm planning to upgrade to Tomcat 8.5 when everything is in place. I'd like to know if there are known issues about this regarding to this setup aswell (there are no other incompatibilities in the code).
BTW: He's not checking if ExampleClass is broken or anything like that, this definetly looks like a recipe to disaster xD. In fact, If I remove the source files, it is still trying to execute the method()... Poor soul...
Ideally, I need a way to instantiate all my application-level objects on start-up (they're the application itself, the rest is just a mere interface) in a way that if they fail Struts2 will tell Tomcat not to start that war, with the corresponding error logging and so on.
If Struts2 doesn't support this, which is the commonly accepted work-around? Maybe some Interceptor to check the object status and return to a error page if it hasn't been correctly instantiated? Execute a partial stop of tomcat from within?
All the objects of this project are thread safe (the only write operation inside them is performed on initialization), but I'd like to know best practices for Struts2 when objects are not so simple. What happens if a user can actually break one? (I know I should by any means avoid that, and I do, but mistakes happen, so I need a secure way to get through them, and get properly alerted, and of course I need a way to reinstantiate it safelly or to stop the whole service).
Right now, I can manually execute something like:
public class SomeAction extends ActionSupport {
ExampleClass example = new ExampleClass();
private boolean otherIsBuildingExample = false;
public String execute() {
if(otherIsBuildingExample) return '500 error';
if(example==null || example.isBroken()){
otherIsBuildingExample = true;
example = new ExampleClass();
otherIsBuildingExample = false;
}
Object result = example.method(args);
// Do stuff with results
}
}
Indeed, this would be cleaner with Interceptors, or so, however, this sounds like a pain in the *** for concurrency, specially taking into consideration thay example takes several seconds to start, and that more requests can come, so more concerns to take into consideration, like: what if two people call if(otherIsBuildingExample) and the second one gets the value before the first one performs otherIsBuildingExample=true? Nothing good... If the class is simple enough, both will instantiate and the slower one will prevail, but if one instantiation blocks the other's resources... well, more problems.
The only clean solution I can think of is to make ExampleClass robust enough so you can repare it using its own methods (not reinstantiating) and make those thread safe in the common way (if 10 people try to repair it, only one will proceed, while the others are just waiting for the first to end to continue, for instance).
Or maybe everytime you call execute() you get a copy of example, so no worries at all about this?
I'm digging into struts documentation
Thanks in advance.

Camel: route messages based on the contents of a map

Currently, my code for routing messages in Camel according to a JMS message header field looks like this:
// MyRouteBuilder.java
#Override
public void configure() {
from(...)
.choice()
.when(header("type").isEqualTo("A"))
.to("proc_a:1")
.when(header("type").isEqualTo("B"))
.to("proc_b:1", "proc_b:2", "proc_b:3")
.when(header("type").isEqualTo("C"))
.to("proc_c:1", "proc_c:2")
.when(...)
.to(...) // ~15 more branches to follow
.otherwise()
.to("proc_default");
}
Dependend on the value of the type header field, there is a specific pipeline of processors that should be used in each case. As you can see, the code is not only repetitive, but also cumbersome to maintain.
There already is a dynamically created Map<String, String[]> which maps types to processors, e.g. the key B returns ["proc_b:1", "proc_b:2", "proc_b:3"]. However, I don't know how to make use of it in the scenario shown above.
I also read about the dynamic router. However, the given example didn't really help me and I don't want to add more complexitiy by having to manage the state of my routing logic or to ensure thread safety.
I'm grateful for any solution. The only requirements are that I'm stuck with Camel 2.15 and that I'm not allowed to adapt the existing processors (this especially means that the routing logic should not remove any header fields since they are needed later on).
Use dynamic to (eg toD), where you use some java method to compute the url to route to: http://camel.apache.org/how-to-use-a-dynamic-uri-in-to.html and here as well about dynamic to: http://camel.apache.org/message-endpoint.html

Producing multiple outputs from a Camel Processor/Component

I am trying to implement a Camel Component/Processor that takes one input and produces multiple output messages, similar to a Splitter. Like Splitter, the output should go to the next processor/endpoint in the route.
I have looked at Splitter & MulticastProcessor classes in the hope that I can reuse them or use similar logic. The idea, as I understood, is to create an new Exchange for each output and emit them. To do this, I need to provide the endpoint to which output is written to. This works, if I dynamically create the end point within the Processor class; my requirement is to send the output to the end point configured in the route. That is in the route below, mycomponent needs to write (multiple times) to file:output.
<route>
<from uri="file:input"/>
<to uri="mycomponent:OrderFlow?multi.output=true"/>
<to uri="file:output" />
</route>
In case of Splitter, it is instantiated by SplitDefinition class which has access to the output Processor/Endpoint.
a) From within a Processor is it possible to access the configured Output Processor/Endpoint?
b) If not, should I be writing a ProcessorDefinition class for my processor? Any pointers on this would help.
Two solutions suggested below by Petter are,
a) Inject a Producer template
b) Use Splitter component with a method call instead of writing a new component.
I assume you have read this page.
Yes, you can send multiple exchanges from a custom processor, but not really to the next processor in the flow. As in the link above, you can decouple the component implementation by injecting a producer template with a specific destination. You can cut your route into several parts using the direct or seda transport and make your component send the messages there. This way, you can reuse the code in several routes.
This is, as you point out, done in the splitter component (among others) in Camel core. Take a look at the multicastprocessor baseclass for example. However, there processors are aware of the following processors in the route, thanks to the route builder. You custom processor is not that lucky.
You can, non the less, extract that information from the CamelContext. Get hold of your route and there you can find the processors in the route. However, that seems like overcomplicating things.
UPDATE:
Instead of trying to alter the DSL, make use of the already existing DSL and components.
.split().method("mycomponent", "OrderFlow")
Instead of emitting new exchanges, your OrderFlow method just needs to create a List<..> with the resulting messages.

How to send a message using Apache Camel?

I am trying to create a sample application hosted at "mina:tcp://localhost:9991" that sends a very simple message to a server hosted at "mina:tcp://localhost:9990".
Now admittedly I have some problems understanding how to do this. My first approach was to create a class called Message, that has two fields: String order and String host. However, I am terribly confused on how to do this.
First I tried to follow the loadbalancer-example basing myself on the ReportGenerator and create a MessageGenerator class that could create a message and return it:
http://camel.apache.org/loadbalancing-mina-example.html
However, there is a problem, I need parameters to create my Message, something that doesn't happen when creating the Report from the example:
//Message constructor
public Message(String order, String host){
//constructor stuff
}
By reading Camel in Action I know how to use beans to call methods that have no parameters, however I still do not understand how I should use them to call a method that has several parameters (Am I forced to use processors?)
Then i realized that perhaps I am complicating things a little bit and there is an easier way to send messages. So I tried another approach that resulted in a small sample of code that does not work as well. I have created a separate question for that matter:
Apache camel send a simple message
Obviously I am doing something wrong and I don't get what. So, I have 2 questions:
Manning's Camel in Action defines an Easy way and a Hard way to use beans, but I did not understand the easy way of using beans with parameters. Can someone provide an example of it?
Is there a way to send a message composed of several fields in Camel (an easy way, without processors) that does not involve using beans? If so, how?
There are several ways to sends Messages in Camel. According to the help provided in the Camel forums, the two best are:
Using beans linked to POJOS and routes (example: http://camel.apache.org/loadbalancing-mina-example.html)
Using the Producer Template (docs: http://camel.apache.org/producertemplate.html)
Hope it helps someone one day.

How do people write unit test in this scenario

I have a question regarding unit test.
I am going to test a module which is an adapter to a web service. The purpose of the test is not test the web service but the adapter.
One function call the service provide is like:
class MyAdapterClass {
WebService webservice;
MyAdapterClass(WebService webservice) {
this.webservice = webservice;
}
void myBusinessLogic() {
List<VeryComplicatedClass> result = webservice.getResult();
// <business logic here>
}
}
If I want to unit test the myBusinessLogic function, the normal way is to inject an mocked version of webservice with getResult() function setup for some predefined return value.
But here my question is, the real webservice will return a list of very completed classes each with tens of properties and the list could contain hundreds or even thousands of element.
If I am going to manually setup a result using Mockito or something like that, it is a huge amount of work.
What do people normally do in this scenario? What I simply do is connect to the real web service and test again the real service. Is something good to do?
Many thanks.
You could write the code to call the real web service and then serialize the List<VeryComplicatedClass> to a file on disk and then in the setup for your mock deserialize it and have mockwebservice.getResult() return that object. That will save you manually constructing the object hierarchy.
Update: this is basically the approach which Gilbert has suggested in his comment as well.
But really.. you don't want to set up a list of very completed classes each with tens of properties and the list could contain hundreds or even thousands of element, you want to setup a mock or a stub that captures the minimum necessary to write assertions around your business logic. That way the test better communicates the details that it actually cares about. More specifically, if the business logic calls 2 or 3 methods on VeryComplicatedClass then you want the test to be explicit that those are the conditions that are required for the things that the test asserts.
One thought I had reading the comments would be to introduce a new interface which can wrap List<VeryComplicatedClass> and make myBusinessLogic use that instead.
Then it is easy (/easier) to stub or mock an implementation of your new interface rather than deal with a very complicated class that you have little control over.

Categories

Resources