Netty: how to pass an object to a specific handler? - java

I'm writing some http server by using Netty.
Let's imagine that I have something like this (in initializer, all handlers extends ChannelInboundHandlerAdapter):
// REST API handlers
pipeline.addLast(new CreateEventHandler());
pipeline.addLast(new GetEventHandler());
pipeline.addLast(new UpdateEventHandler());
pipeline.addLast("delete", new DeleteEventHandler());
My question is can I pass an object to a specific handler like this (for example, somewhere in CreateEventHandler):
ChannelInboundHandlerAdapter h = (ChannelInboundHandlerAdapter) ctx.pipeline().get("delete");
h.channelRead(ctx, msg);
If yes, is this a good way? Or I'm guaranteed to get some overhead or errors? Or I must pass an object through all handlers in the pipeline?
Thanks.

This not a good way to design your application. The Netty ChannelPipeline defines a sequence of handlers, each of which may transform the data passing through it. Essentially, the incoming/outgoing data is passed through all the inbound/outbound handlers in the pipeline. It is not a "conditional dispatch" mechanism which is what you seem to be looking for.
It looks like you're building a REST service; all you need is a generic HTTP pipeline, and a single inbound handler which will dispatch to your application code based on HTTP method. Which means none of the handlers in your example (GetEventHandler etc) need to extend ChannelInboundHandlerAdapter - they can be simple Java classes that have no netty specific code. This will give you a nice separation between protocol and business logic as well.

Related

Multiple ways to communicate with Akka Actor from outside the system?

I was under the impression that the only way to communicate with an Akka Actor from outside the ActorSystem was via Inbox. However I just found this snippet from Akka's own documentation which shows:
greeter.tell(new WhoToGreet("akka"), ActorRef.noSender());
inbox.send(greeter, new Greet());
So which is it? Is it in fact possible to directly tell an Actor from the outside world, or did Typesafe have a careless intern writing their documentation for them?!?
If it is possible, then when should you do this, and when should you use Inbox? For instance, is one method "fire-and-forget" asynchronous/non-blocking and the other synchronous/blocking?
Inbox is part of the relatively recent Actor DSL API that is "some nice sugar on top of the usual ways to create actors". You can either use the standard way to create / communicate with actors or use the Actor DSL. They are both async. The Actor DSL is nice for creating one-off actors whose lifetime is one method. The advantage of the DSL syntax is a bit more evident in Scala.
You can safely send messages from outside an actor. Akka will fill in a dummy sender. You just won't be able to receive any replies (though you can use an ask for that).

How to route requests based on URI in Netty?

I'm new to Netty and to get more familiar with it I'm working on building a simple HTTP server. One thing I want to do is deal with routing based on the URI. I looked around for examples and found a few approaches and wanted to see which made the most sense.
Have a "route" handler that will add/remove others based on the URI in the HTTPMessage. This seems inefficient if I have to do this for every single request.
Have the "route" handler wrap the HTTPMessage and HTTPContent inside another object that will then be passed in to the appropriate handler. For example, I can have an InfoHandler that extends SimpleChannelInboundHandler and the router InfoHTTPRequest object. This way the pipeline stays fixed and I'm not changing it on the fly - I am creating more objects though.
Have a single route handler that just has methods to handle the different endpoints. I can have a handleInfo method, a handleUpdate method, etc with each of those having their own implementation and referencing their own dependencies.
PS - I'm using Netty 4.0 and most of my understanding has come from various online research and reading the Netty In Action book.
I use a fixed pipeline which is only responsible for decoding/encoding requests/responses (and optional aggregation, compression, static headers, etc).
The final handler in the pipeline passes off to a configurable RequestResolver (generic to support types other than HTTP) which looks a little like:
public interface RequestResolver<T> {
void execute(#Nonnull ChannelHandlerContext ctx, #Nonnull T req);
}
The request resolver is responsible for deciding how to handle the request (i.e. routing if necessary) and generally passes off to one or more actions that have been registered on it, or returns a 404. It doesn't have anything to do with the pipeline so much, other than it takes a ctx with which to queue responses.
I started using Netty 4 right back when it was alpha-01 and there was no routing framework plugins available, so I wrote my own RequestResolver in Java, more recently I've another written in Clojure which re-uses the Clout routing from Compojure.

Design Issue: Should UI layer worry about it's backend?

It is more of a design and architecture question. I am developing a new UI layer for an old system. This system accepts request in particular xml format. Currently request from the new UI layer goes to a data massaging class via controller.
This Translator/Massaging class converts UI request xml to desired request format. It adds few deprecated elements and constants to the XML it received from UI layer.
Request XML from UI is partially similar to the actual back end. But it has to go to the Translator/Massaging class to be converted into actual request.My question does UI layer need to worry about if it's request XML is partially similar to the actual request? Can UI layer just send the data in JSON format to the Translator/Massaging and translator class will convert it into the actual request xml?
My question does UI layer need to worry about if it's request XML is partially similar to the actual request?
No. As you suggested in your next question, the messaging class can convert the GUI data into an actual XML request.
Can the UI layer just send the data in JSON format to the messaging class and messaging class will convert it into the actual request XML?
It could. However, your GUI should have a data model. The GUI would interact with the data model. The data model would interact with the messaging class. There's no need for another data format, unless there's some requirement you're not telling us.
My question does UI layer need to worry about if it's request XML is partially similar to the actual request? Can UI layer just send the data in JSON format to the massaging class and massaging class will convert it into the actual request xml?
Clearly it could do that. But that would mean that the "massaging" class has more work to do.
To my mind, you are probably asking the wrong question here. If I was in your shoes, I'd be asking myself why I can't use the request format for the "old" system directly, or why I can't change the "old" system to accept requests in the "new" format directly.
Or to put it another, ask yourself what is the purpose of implementing a new format, and all of the extra coding and the performance hit of the "massaging".
Unless there is something else going on that you haven't told us, this all sounds a bit unnecessary to me.
Think services! Any functionality the server offers and is used by the client should be abstracted by a service interface, so that code using this service never has to worry about its implementation or any protocols involved. You can then have the actual implementation on the server, and a remote facade implementation for the client, which forwards the request to the server and also handles the responses:
interface SomeService {
public SomeResult doSomething(SomeArguments) throws SomeException;
}
class SomeServiceServerImpl implements SomeService {
// server-side implementation
}
class SomeServiceClientFacade implements SomeService {
// client-side facade, forwards the request, for example to a web service
}
The facade can then convert the arguments to XML, call a web service, parse the XML response and convert it back to a result object or exception.
If you use a standardized RPC (Remote Procedure Call) protocol (such as SOAP or JSON-RPC), the most elegant way to handle this would be to use a Proxy with an InvocationHandler which does the request marshalling and response unmarshalling in a generic way, allowing you to cheaply create remote service proxies.

Known RPC Protocols to put ontop of JMS

I am developing a distributed system which consists of different components (services) which are loosely (asynchronously) coupled via JMS (ActiveMQ).
Thus I do not want to reinvent the wheel, I am looking for a (well) known protocol / library that facilitates remote procedure calls inbetween these components and helps me deal with method interfaces.
So let's decompose the problem I am already solving right now via dirty solutions:
A consumer component want's to call a service, thus it constructs a request string (hand-written and dirty)
The request string is than compressed an put into a JMS message (dirty aswell)
The request message is than transmitted via JMS and routing mechanisms (that part is ok)
The service first of all needs to decompress and parse the request string, to identify the right method (dirty)
The method gets called and the reply goes like #2 - #4.
So that looks pretty much like SOAP, whilst I think that SOAP is to heavy for my application and further I am not using HTTP at all. Given that I was thinking that one might be able to deconstruct the problem into different components.
Part A: HTTP is replaced by JMS (that one is okay)
Part B: XML is replaced by something more lightweight (alright, MessagePack comes in handy here)
Part C: Mechanism to parse request/reply string to identify operation name and parameter values (that one is the real problem here)
I was looking into MessagePack, ProtocolBuffers, Thrift and so forth, but what I don't like about them is that they introduce their own way of handling the actual (TCP) communication. And bypass my already sophisticated JMS infrastructure (which also handles load balancing and stuff).
To further elaborate Part C above, this is how I am currently handling it: Right know I would do something like the following if a consumer would call a service, let's assume the service takes a text and replies keywords. I would have the consumer create a JMS message and transmit it (via ActiveMQ) to the service. The message would contain:
Syntax: OPERATION_NAME [PARAMETERS]
Method: GET_ALL_KEYWORDS [String text] returns [JSON String[] keywords]
Example Request: GET_ALL_KEYWORDS "Hello world, this is my input text..."
Example Reply: ["hello", "world", "text"]
Needless to say that it feels like hacked-together. The problem I see is if I would be to change the method interface by adding or deleting parameters, I would have to check all the request/reply string construction/deconstructions to syncronize the changes. That is pretty errorprone. I'd rather have the library construct the right request/reply syntax by looking at a java interface and throwing real exceptions on runtime if I do mess up stuff, like "Protocol Exception: Mandatory parameter not set" or something...
Any projects/libs known for that?
Requirements would be
It's small and lightweight and fast.
It's implemented in JAVA
It doesn't serve too many purposes (like some fullblown framework e.g. Spring)
I think this Spring package is what you're looking for. See JmsInvokerProxyFactoryBean and related classes.
From the javadoc:
FactoryBean for JMS invoker proxies. Exposes the proxied service for
use as a bean reference, using the specified service interface.
Serializes remote invocation objects and deserializes remote
invocation result objects. Uses Java serialization just like RMI, but
with the JMS provider as communication infrastructure.

How to specify a parameter as part of every web service call?

Currently, each web service for our application has a user parameter that is added for every method. For example:
#WebService
public interface FooWebService {
#WebMethod
public Foo getFoo(#WebParam(name="alwaysHere",header=true,partName="alwaysHere") String user, #WebParam(name="fooId") Long fooId);
#WebMethod
public Result deletetFoo(#WebParam(name="alwaysHere",header=true,partName="alwaysHere") String user, #WebParam(name="fooId") Long fooId);
// ...
}
There could be twenty methods in a service, each with the first parameter as user. And there could be twenty web services.
We don't actually use the 'user' argument in the implementations - in fact, I don't know why it's there - but I wasn't involved in the design, and the person that put it there had a reason (I hope).
Anyway, I'm trying to straighten out this Big Ball of Mud.
I have already come a long way by wrapping the web services by a Spring proxy, which allows me to do some before-and-after processing in an interceptor (before there were at least 20 lines of copy-pasted boiler plate per method).
I'm wondering if there's some kind of "message header" I can apply to the method or package and that can be accessed by some type of handler or something outside of each web service method.
Thanks in advance for the advice,
LES
Who or what is expecting the user message to be bound to SOAP headers? Are your web services secured? Is that some kind of authentication header? It might have been the original intention. Actually, someone should have the answer to these questions. Find who. And if you find out that you won't ever need it, stop passing it. But if you need it, I think it's better to add it (even if you don't use it for now) unless if modifying the WSDL is not an issue (especially on the client side).
PS: I don't know how to avoid adding a parameter with #WebParam(header=true) to Java methods in order to generate a WSDL with operations having a <soap:header> in their input. AFAIK, this is how JAX-WS works when starting from Java.
If there is no reason why you need to have that variable as a parameter, you can have each one of your services extend a super class. In that super class have spring inject the MessageContext, ServletContext, ServletRequest, HttpHeaders or whichever is appropriate (probably MessageContext for JAXWS) using either the #Context annotation or #Resource annotation.
Then supply some methods in that super class to pull the user information from the request.
If authentication is what you are trying to accomplish you can manipulate contexts from predefined handlers such as protocol or Logical Handlers. E.g. implement SoapHanlder(which is a protocol handler) interface , from there add that class to the handler chain of each service you offer. Very simple and powerful. This gentleman has the best tutorial out there on this topic.

Categories