Accessing MuleMessage and a flow variable from Java component - java

I have a Java component that receives a payload (JsonData), like this:
public String myMethod(JsonData payload) throws IOException {
// do things with payload.
}
This is working fine, but I also need to access a flow variable within the method. I understand that, to do so, I need to run myMessage.getInvocationProperty("my-variable-name");
However, since I'm only passing the payload, I don't have access to the MuleMessage. How can I change my method so I can get access to my message/property?
I tried:
org.mule.RequestContext.getEvent().getMessage()
but it is deprecated.
Also, I've read all sorts of answers on this issue but never found a complete answer.
Thanks,

Pass the flow variable as a second argument to myMethod via the invoke message processor.
So, assuming the new signature of myMethod is:
public String myMethod(JsonData payload, String myVariable) throws IOException {
// do things with payload.
}
you would do:
<invoke object-ref="myComponent"
method="myMethod"
methodArguments="#[message.payload],#[flowVars['my-variable-name']]" />

Use the message.getInvocationProperty method.
Setting variable:
<set-variable variableName="lastname" value="#[payload.lastname]" />
Retrieve variable from invocation scope:
String lastname = message.getInvocationProperty("lastname");

Related

Jersey 2 Path Parameters separated by a . throws exception when one parameter is numeric

we have an application running Jersey 2.25 and we have an old interface that contains a signature like this:
#GET
#Path("/release/{id}.{filename}")
public Response release(#PathParam("id") long id, #PathParam("filename") String filename) { ... }
This interface worked fine under Jersey 1, but now we are having problems. After a little research we found that when Jersey 2 attempts to inject the value into the path parameter of the id value, it takes both parameters which of course causes a NumberFormatException as it cannot parse a parameter 1031.myfile.txt as a long. Where as it should have split the value into two parameters.
As stated with Jersey 1 this functioned perfectly, but since we moved to Jersey 2 we've noticed the problem during testing. Is this a change in behavior of Jersey, meaning we'll need to redefine our interface, or is this something that was simply overlooked during the development of Jersey 2?
To resolve this issue, you'll need to redefine your interface to handle this change in behavior. You can either modify the path parameter to accept a string that contains both the "id" and "filename" values and then parse the string within the method to extract the separate values, or you can modify the path parameter to accept two separate values, one for the "id" and one for the "filename".
In the first solution, you can modify the path parameter to the following:
#GET
#Path("/release/{id_filename}")
public Response release(#PathParam("id_filename") String id_filename) {
String[] parts = id_filename.split("\.");
long id = Long.parseLong(parts[0]);
String filename = parts[1];
// rest of the implementation
}
In the second solution, you can modify the path parameter to the following:
#GET
#Path("/release/{id}/{filename}")
public Response release(#PathParam("id") long id, #PathParam("filename") String filename) {
// rest of the implementation
}

Set Query Parameters on a Jersey Test Call

I have a Jersey based Java servlet:
#Path("foo")
class Foo {
#GET
#Path("bar")
public Response bar(#QueryParam("key") String value) {
// ...
}
}
I can call it in Tomcat just fine as:
http://localhost:8080/container/foo/bar?key=blah
However, in my JerseyTest, using Grizzly, it's not handling the parameters properly. This test case returns a 404 error:
#Test
public void testBar() {
final Response response = target("foo/bar?key=blah").request().get();
}
I suspect the issue is it's looking for a resource named foo/bar?key=blah rather than trying to pass key=blah to the resource at foo/bar. If I pass just "foo/bar" to target(), I get a 500, as the code throws an exception for a null parameter.
I looked through the Jersey Test documentation, and some examples, and I found some cryptic looking stuff that might have been for passing parameters to a GET, but none of it looked like it was assigning values to parameters, so I wasn't positive how I would use it.
How can I pass my value in for that parameter?
JavaDoc to WebTarget.queryParam() should give you an answer to your problem. Basically you need to transform your code to something like:
target("foo/bar").queryParam("key", "blah").request().get()

Verify Overloaded Method Call

I am attempting to verify that a method was called a number of times using the Mockito verify functionality. The problem I am encountering however is that the method is overloaded so it claims that the method was not called. To Add a wrench into the mix, I also wish to capture what the argument was that was passed to this method. Here is what I have so far:
#Test
public void simpleTest() throws IOException {
FlumeAppender mockAppender = Mockito.mock(FlumeAppender.class);
ArgumentCaptor<LoggingEvent> arguments = ArgumentCaptor.forClass(LoggingEvent.class);
// Load the message that should be sent to the class being tested
InputStream in = this.getClass().getResourceAsStream("/testMessage.xml");
StringWriter writer = new StringWriter();
IOUtils.copy(in, writer, "UTF-8");
String testMessage = writer.toString();
// Send a message to the class being tested. This class will
// (hopefully) call the function I am listening to below
eventSubscriber.handleMessage(testMessage);
// Verify that the append method was called twice
Mockito.verify(mockAppender, Mockito.times(2)).append(
arguments.capture());
// Do something with the arguments
}
Like I said, the function I am attempting to verify (append) is overloaded. Is it possible to specify which append function I am asking to verify while still capturing the arguments?
Embarrassingly, I have discovered the solution to my problem was the result of a simple error. I will post the answer for reference.
When creating the ArgumentCaptor, specify the argument type you are expecting using generics. I had done this, but sadly I used the type from one of the other versions of the method that I was not expecting to be called. Simple mistake.
// This declaration
ArgumentCaptor<LoggingEvent> arguments = ArgumentCaptor.forClass(LoggingEvent.class);
// Should have been:
ArgumentCaptor<Event> arguments = ArgumentCaptor.forClass(Event.class);
Once this is correct the verify function should work as expected, using the type from the ArgumentCaptor to determine which method to look at.
So close...

Netty - How to pass information between handlers in the same pipeline

I would like to create a pipeline of handlers such as:
public ChannelPipeline getPipeline() throws Exception
{
return Channels.pipeline(
new ObjectEncoder(),
new ObjectDecoder(),
new AuthenticationServerHandler(),
new BusinessLogicServerHandler());
}
The key here is that I'd like the AuthenticationServerHandler to be able to pass the login information to the BusinessLogicServerHandler.
I do understand that you can use an Attachment, however that only stores the information for that handler, the other handlers in the pipeline cannot access it. I also noticed there was something called ChannelLocal which might do the trick, however I cannot find any real information on how to use it. All I've seen is people create a static instance to it, but how do you retrieve and access the info in another handler? Assuming that's the correct method.
My question is: how you do pass information between handlers in the same pipeline. In the example above, how do I pass the login credentials from the AuthenticationServerHandler to the BusinessLogicServerHandler?
ChannelLocal is the way to go atm. Just create an static instance somewhere and then access it from within your handlers by pass the Channel to the set/get method. This way you can share stuff between your channels.
I wasn't a fan of the ChannelLocal implementation with the lack of an internal static map, so what I ended up doing was putting my object on the Channel's attachment for now:
ctx.getChannel().setAttachment(myobj);
Then I make "myobj" basically a context POJO that contains all the information gathered about the request so far.
public class RequestContext {
private String foo = "";
public String getFoo(){
return foo;
}
public void setFoo(String foo){
this.foo = foo;
}
}
RequestContext reqCtx = new RequestContext();
reqCtx.setFoo("Bar");
ctx.getChannel().setAttachment(reqCtx);
reqCtx = (RequestContext)ctx.getChannel().getAttachment();
It's not elegant, but it works...
I pass information from one handler to the next ones by using dedicated instances to compose the pipeline for each channel, and by having the handlers reference each others within each pipeline.
The passing of information is made the old way, very simply, without any problem.

Play framework: setting a java method return value to a javascript var

Is there's a way to get the value returned by a java controller method in javascript in the views ?
what I want to do is:
i'm in view showX rendered by controller method X.show()
i want to create an object y so $.post('#{Y.create()}')
now i need the id of the created object of type y to use it in the same view (showX).
is that possible?
It sound like what you need (although your question is very vague), is to return JSON from your controller method.
Such as, in your controller, you can do
public static void myActionOne() {
renderJSON(myObject);
}
And then you will call myActionOne from your javascript using $.post. I would also suggest looking at the Play jsAction tag if you are not already using it. This will return a JSON representation of the object. You can then take whatever information you need and call a second action in the same way.
Again, in the second action, I would suggest jsAction, as it makes passing parameters into your actions far easier.
EDIT:
Based on your edit, then all you need to do is in your controller method Y.create, do something like
public static void create() {
MyObject obj = new MyObject();
obj.save();
Long id = obj.id;
renderJSON(id);
}
Obviously your code to create your object will be different, but you get the idea. You can then just take the data from the JQuery post response, and access the id that has been returned, using standard javascript.
You question is too vague. But you probably will need of AJAX to get a value of this kind.
Take a look here: http://www.oracle.com/technetwork/articles/javaee/ajax-135201.html

Categories

Resources