Danger of instantiating a class in a verticle vert.x - java

I explain my problem, I have a verticle in which I defined all the routes. And I have simple java classes that contain methods that I call in my verticle depending on the route. For example, my downloadFile() method is in the MyFile class like this:
public class MyFile {
public final void downloadFile(RoutingContext rc, Vertx vertx) {
final HttpServerResponse response = rc.response();
response.putHeader("Content-Type", "text/html");
response.setChunked(true);
rc.fileUploads().forEach(file -> {
final String fileNameWithoutExtension = file.uploadedFileName();
final JsonObject jsonObjectWithFileName = new JsonObject();
response.setStatusCode(200);
response.end(jsonObjectWithFileName.put("fileName", fileNameWithoutExtension).encodePrettily());
});
}
public final void saveFile(RoutingContext rc, Vertx vertx) {
//TODO
}
}
And I use this class in my verticle like this:
public class MyVerticle extends AbstractVerticle{
private static final MyFile myFile = new MyFile();
#Override
public void start(Future<Void> startFuture) {
final Router router = Router.router(vertx);
final EventBus eventBus = vertx.eventBus();
router.route("/getFile").handler(routingContext -> {
myFile.downloadFile(routingContext, vertx);
});
router.route("/saveFile").handler(routingContext -> {
myFile.saveFile(routingContext, vertx);
});
}
}
My colleague tells me that it is not good to instantiate a class in a verticle and when I asked him why, he replied that it becomes stateful and I have doubts about what he says to me because I don't see how. And as I declared my MyFile class instance "static final" in my verticle, I want to say that I even gain in performance because I use the same instance for each incoming request instead of creating a new instance .
If it's bad to instantiate a class in a verticle, please explain why?
In addition I would like to know what is the interest of using 2 verticles for a treatment that only one verticle can do?
For example, I want to build a JsonObject with the data I select in my database, why send this data to another verticle knowing that this verticle does nothing but build the JsonObject and wait for it to answer me for sent the response to the client so that I can build this JsonObject in the verticle where I made my request and immediately sent the response to the client.I put you a pseudo code to see better :
public class MyVerticle1 extends AbstractVerticle{
public void start(Future<Void> startFuture) {
connection.query("select * from file", result -> {
if (result.succeeded()) {
List<JsonArray> rowsSelected = result.result().getResults();
eventBus.send("adress", rowsSelected, res -> {
if (res.succeded()) {
routinContext.response().end(res.result().encodePrettily());
}
});
} else {
LOGGER.error(result.cause().toString());
}
});
}
}
public class MyVerticle2 extends AbstractVerticle{
public void start(Future<Void> startFuture) {
JsonArray resultOfSelect = new JsonArray();
eventBus.consumer("adress", message -> {
List<JsonArray> rowsSelected = (List<JsonArray>) message.body();
rowsSelected.forEach(jsa -> {
JsonObject row = new JsonObject();
row.put("id", jsa.getInteger(0));
row.put("name", jsa.getString(1));
resultOfSelect.add(row);
});
message.reply(resultOfSelect);
});
}
}
I really do not see the point of making 2 verticles since I can use the result of my query in the first verticle without using the second verticle.
For me, EventBus is important for transmitting information to verticles for parallel processing.

bear in mind... the answers you're looking for are unfortunately very nuanced and will vary depending on a number of conditions (e.g. the experience of whoever is answering, design idioms in the codebase, tools/libraries at your disposal, etc). so there aren't an authoritative answers, just whatever suits you (and your co-workers).
My colleague tells me that it is not good to instantiate a class in a
verticle and when I asked him why, he replied that it becomes stateful
and I have doubts about what he says to me because I see not how.
your colleague is correct in the general sense that you don't want to have individual nodes in a cluster maintaining their own state because that will in fact hinder the ability to scale reliably. but in this particular case, MyFile appears to be stateless, so introducing it as a member of a Verticle does not automagically make the server stateful.
(if anything, i'd take issue with MyFile doing more than file-based operations - it also handles HTTP requests and responses).
And as I declared my MyFile class instance "static final" in my
verticle, I want to say that I even gain in performance because I use
the same instance for each incoming request instead of creating a new
instance .
i'd say this goes to design preferences. there isn't any real "harm" done here, per se, but i tend to avoid using static members for anything other than constant literals and prefer instead to use dependency injection to wire up my dependencies. but maybe this is a very simple project and introducing a DI framework is beyond the complexity you wish to introduce. it totally depends on your particular set of circumstances.
In addition I would like to know what is the interest of using 2
verticles for a treatment that only one verticle can do?
again, this depends on your set of circumstances and your "complexity budget". if the processing is simple and your desire is to keep the design equally simple, a single Verticle is fine (and arguably easier to understand/conceptualize and support). in larger applications, i tend to create many Verticles along the lines of the different logical domains in play (e.g. Verticles for authentication, Verticles for user account functionality, etc), and orchestrate any complex processing through the EventBus.

Related

Bridge Pattern applied to messaging API

I wish to have the bridge pattern applied for a project, basically I want this project to be able to trigger requests towards multiple different channels.
Example, I want to create messages which can be SMSs, E-mails or Viber for example... Obviously each of them is a message, but each with some different things, and so I wanted to have the Bridge applied there.
Is the bridge pattern the right one? If yes, how can it be implemented? In case another one should be used, also, please let me know how to use it in this context.
Thank you!
DISCLAMER This example is built from my understanding of the bridge pattern. If you feel like I'm not giving an appropriate definition, please let me know and I will happily remove it.
Bridge pattern is a good guess, but not for your objects. You can simply use polymorphism to create an Abstract Message class. This class could be extend in all of your specific objects.
public abstract class Message {
/* ... */
}
public class SmsMessage extends Message {
/* ... */
}
Where the bridge pattern could be useful is when you want to actually send the message. Chances are you are going to need different protocol to send different message so implementing a bridge pattern is a good idea.
The benefit of the bridge pattern is to generalize some classes, that way, if you need to add a new type of those classes, the code that uses it doesn't change.
Lets say your sending logic is tangle into a 3000 line class and that each time you want to send a message, you need to check what type of message it is, to send via the correct protocol. Well, adding a new message type, like FlyingPigeonMessage would be a real pain, since you need to replace every code that check what message to send.
On the other hand, if your 3000 line classes never know what TYPE of message they are, only that they are MESSAGEs, they adding a new type is a walk in the park. With that in mind, here is a simple implementation of the bridge pattern.
First, we need to define our bridge. In our case, it can be an interface that implements a simple method send.
public interface IMessageProvider {
public void send(Message message)
}
We then need to create different implementation of that Interface, one for each type of message. Here I'm only going to build the SMS class because this is an example.
public class SmsMessageProvider implements IMessageProvider {
#override
public void send(Message message) {
/* call a sms service or somehting... */
}
}
Once we have multiple providers, we need a way to instanciate them depending on a given condition. I like to use factories for that, you can pass it an object and depending on it's type, you get a specific implementation.
/**
* Creates message providers.
*/
public class MessageProviderFactory {
public static IMessageProvider getProviderForMessage(Message message) {
// we return an implementation of IMessageProbvider depending on the type of message.
if(message instanceOf SmsMessage) {
return new SmsMessageProvider();
} else {
// other types of message
}
}
}
Now, we have a bridge interface, we have implementations and we have a factory. All we need is to send the message. The beauty of the bridge pattern is that the function that call the send methods doesn't need to know exactly what object it has. Which make it way easier to maintain.
public class Application() {
public static void main(String[] args) {
Message message;
Boolean isSendingSMS = true; // user prefer sms over email
// we build the message depending on the config.
if(isSendingSMS) {
message = new SmsMessage("my awesome message");
} else {
/* ... */
}
// will send the message we built.
Application.sendMessage(message);
}
public static void sendMessage(Message message) {
// for a given message, we retreive the appropriate provider
IMessageProvider provider = MessageProviderFactory.getProviderForMessage(message);
// using this provider we send the message
provider.send(message);
}
}
In the end, we end up sending a message via the correct provider without having to actually know what provider it was. We used the bridge pattern to build the provider and simple polymorphism to build our object.
NOTE I havn't done Java in a long time, this code might not be syntaxically valid but I hope it provide a good example.

Java Jersey: Whats the best way to share data between the Main-object and the Webservice

Lets say I have a Jersey-service inside a grizzles server and I like to share data between the server and the service-implementation (e.g. mydata).
public class MyServer
{
String mydata="";
public static void main (String [] args)
{
ResourceConfig rc = new ResourceConfig ().packages (MyServer.class.getPackage ().getName ());
HttpServer hs = GrizzlyHttpServerFactory.createHttpServer (URI.create ("http://localhost/myserver"), rc);
for (int i = 0; i < 10; i ++)
{
mydata += "bla";
}
hs.shutdown ();
}
}
#Path ("myservice")
public class MyService
{
#GET
public String getIt()
{
// how to access mydata?
}
}
Whats the best way to share that data?
I can think of a singleton or make mydata static. But maybe there is a standard-way I do not see here?
Thanks!
You can make mydata static or instance variable of singleton if and only if mydata is really static and cannot be changed by multiple threads (e.g. inside your getIt() method of the service).
Such technique applies and uses usually for common configuration properties.
In general it is a standard way for such situation. BTW you can keep your mydata not necessary in the Server class, but make another class to keep such common data there (if there are bunch of them) , but it is a matter of choice.
Also it is more standard to do not make actual mydata field public , but provide getter/setter pair for it.
Finally, if such common/static value can be changed by multiple threads you need to make it synchronized to avoid concurrent modifications.
There are much more different approaches to handle concurrency and make code thread-safe, but it belongs to your actual needs. Anyway all of them end up to static/singleton synchronized implementation.
PS. Be careful, if it is a common static data you have to populate it before start the server not after (as in your example) - otherwise there is a possibility that request may come before data ready to use by service thread.

Reactor / WebFlux implement a reactive http news ticker

I have a request that is rather simple to formulate, but I cannot pull it of without leaking resources.
I want to return a response of type application/stream+json, featuring news events someone posted. I do not want to use Websockets, not because I don't like them, I just want to know how to do it with a stream.
For this I need to return a Flux<News> from my restcontroller, that is continuously fed with news, once someone posts any.
My attempt for this was creating a Publisher:
public class UpdatePublisher<T> implements Publisher<T> {
private List<Subscriber<? super T>> subscribers = new ArrayList<>();
#Override
public void subscribe(Subscriber<? super T> s) {
subscribers.add(s);
}
public void pushUpdate(T message) {
subscribers.forEach(s -> s.onNext(message));
}
}
And a simple News Object:
public class News {
String message;
// Constructor, getters, some properties omitted for readability...
}
And endpoints to publish news respectively get the stream of news
// ...
private UpdatePublisher<String> updatePublisher = new UpdatePublisher<>();
#GetMapping(value = "/news/ticker", produces = "application/stream+json")
public Flux<News> getUpdateStream() {
return Flux.from(updatePublisher).map(News::new);
}
#PutMapping("/news")
public void putNews(#RequestBody News news) {
updatePublisher.pushUpdate(news.getMessage());
}
This WORKS, but I cannot unsubscribe, or access any given subscription again - so once a client disconnects, the updatePublisher will just continue to push onto a growing number of dead channels - as I have no way to call the onCompleted() handler on the subscriptions.
TL;DL:
Can one push messages onto a possible endless Flux from a different thread and still terminate the Flux on demand without relying on a reset by peer exception or something along those lines?
You should never try to implement yourself the Publisher interface, as it boils down to getting the reactive streams implementation right. This is exactly the issue you're facing here.
Instead you should use one of the generator operators provided by Reactor itself (this is actually a Reactor question, nothing specific to Spring WebFlux).
In this case, Flux.create or Flux.push are probably the best candidates, given your code uses some type of event listener to push events down the stream. See the reactor project reference documentation on that.
Without more details, it's hard to give you a concrete code sample that solves your problem. Here are a few pointers though:
you might want to .share() the stream of events for all subscribers if you'd like some multicast-like communication pattern
pay attention to the push/pull/push+pull model that you'd like to have here; how is the backpressure supposed to work here? What if we produce more events that the subscribers can handle?
this model would only work on a single application instance. If you'd like this to work on multiple application instances, you might want to look into messaging patterns using a broker

Best practice to associate message and target class instance creation

The program I am working on has a distributed architecture, more precisely the Broker-Agent Pattern. The broker will send messages to its corresponding agent in order to tell the agent to execute a task. Each message sent contains the target task information(the task name, configuration properties needed for the task to perform etc.). In my code, each task in the agent side is implemente in a seperate class. Like :
public class Task1 {}
public class Task2 {}
public class Task3 {}
...
Messages are in JSON format like:
{
"taskName": "Task1", // put the class name here
"config": {
}
}
So what I need is to associate the message sent from the broker with the right task in the agent side.
I know one way is to put the target task class name in the message so that the agent is able to create an instance of that task class by the task name extracted from the message using reflections, like:
Class.forName(className).getConstructor(String.class).newInstance(arg);
I want to know what is the best practice to implement this association. The number of tasks is growing and I think to write string is easy to make mistakes and not easy to maintain.
If you're that specific about classnames you could even think about serializing task objects and sending them directly. That's probably simpler than your reflection approach (though even tighter coupled).
But usually you don't want that kind of coupling between Broker and Agent. A broker needs to know which task types there are and how to describe the task in a way that everybody understands (like in JSON). It doesn't / shouldn't know how the Agent implements the task. Or even in which language the Agent is written. (That doesn't mean that it's a bad idea to define task names in a place that is common to both code bases)
So you're left with finding a good way to construct objects (or call methods) inside your agent based on some string. And the common solution for that is some form of factory pattern like: http://alvinalexander.com/java/java-factory-pattern-example - also helpful: a Map<String, Factory> like
interface Task {
void doSomething();
}
interface Factory {
Task makeTask(String taskDescription);
}
Map<String, Factory> taskMap = new HashMap<>();
void init() {
taskMap.put("sayHello", new Factory() {
#Override
public Task makeTask(String taskDescription) {
return new Task() {
#Override
public void doSomething() {
System.out.println("Hello" + taskDescription);
}
};
}
});
}
void onTask(String taskName, String taskDescription) {
Factory factory = taskMap.get(taskName);
if (factory == null) {
System.out.println("Unknown task: " + taskName);
}
Task task = factory.makeTask(taskDescription);
// execute task somewhere
new Thread(task::doSomething).start();
}
http://ideone.com/We5FZk
And if you want it fancy consider annotation based reflection magic. Depends on how many task classes there are. The more the more effort to put into an automagic solution that hides the complexity from you.
For example above Map could be filled automatically by adding some class path scanning for classes of the right type with some annotation that holds the string(s). Or you could let some DI framework inject all the things that need to go into the map. DI in larger projects usually solves those kinds of issues really well: https://softwareengineering.stackexchange.com/questions/188030/how-to-use-dependency-injection-in-conjunction-with-the-factory-pattern
And besides writing your own distribution system you can probably use existing ones. (And reuse rather then reinvent is a best practice). Maybe http://www.typesafe.com/activator/template/akka-distributed-workers or more general http://twitter.github.io/finagle/ work in your context. But there are way too many other open source distributed things that cover different aspects to name all the interesting ones.

Desktop program communicating with server

I am in the process of moving the business logic of my Swing program onto the server.
What would be the most efficient way to communicate client-server and server-client?
The server will be responsible for authentication, fetching and storing data, so the program will have to communication frequently.
it depends on a lot of things. if you want a real answer, you should clarify exactly what your program will be doing and exactly what falls under your definition of "efficient"
if rapid productivity falls under your definition of efficient, a method that I have used in the past involves serialization to send plain old java objects down a socket. recently I have found that, in combination with the netty api, i am able to rapidly prototype fairly robust client/server communication.
the guts are fairly simple; the client and server both run Netty with an ObjectDecoder and ObjectEncoder in the pipeline. A class is made for each object designed to handle data. for example, a HandshakeRequest class and HandshakeResponse class.
a handshake request could look like:
public class HandshakeRequest extends Message {
private static final long serialVersionUID = 1L;
}
and a handshake response may look like:
public class HandshakeResponse extends Message {
private static final long serialVersionUID = 1L;
private final HandshakeResult handshakeResult;
public HandshakeResponse(HandshakeResult handshakeResult) {
this.handshakeResult = handshakeResult;
}
public HandshakeResult getHandshakeResult() {
return handshakeResult;
}
}
in netty, the server would send a handshake request when a client connects as such:
#Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
Channel ch = e.getChannel();
ch.write(new HandshakeRequest();
}
the client receives the HandshakeRequest Object, but it needs a way to tell what kind of message the server just sent. for this, a Map<Class<?>, Method> can be used. when your program is run, it should iterate through the Methods of a class with reflection and place them in the map. here is an example:
public HashMap<Class<?>, Method> populateMessageHandler() {
HashMap<Class<?>, Method> temp = new HashMap<Class<?>, Method>();
for (Method method : getClass().getMethods()) {
if (method.getAnnotation(MessageHandler.class) != null) {
Class<?>[] methodParameters = method.getParameterTypes();
temp.put(methodParameters[1], method);
}
}
return temp;
}
this code would iterate through the current class and look for methods marked with an #MessageHandler annotation, then look at the first parameter of the method (the parameter being an object such as public void handleHandshakeRequest(HandshakeRequest request)) and place the class into the map as a key with the actual method as it's value.
with this map in place, it is very easy to receive a message and send the message directly to the method that should handle the message:
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
try {
Message message = (Message) e.getMessage();
Method method = messageHandlers.get(message.getClass());
if (method == null) {
System.out.println("No handler for message!");
} else {
method.invoke(this, ctx, message);
}
} catch(Exception exception) {
exception.printStackTrace();
}
}
there's not really anything left to it. netty handles all of the messy stuff allowing us to send serialized objects back and forth with ease. if you decide that you do not want to use netty, you can wrap your own protocol around java's Object Output Stream. you will have to do a little bit more work overall, but the simplicity of communication remains intact.
It's a bit hard to say which method is "most efficient" in terms of what, and I don't know your use cases, but here's a couple of options:
The most basic way is to simply use "raw" TCP-sockets. The upside is that there's nothing extra moving across the network and you create your protocol yourself, the latter being also a downside; you have to design and implement your own protocol for the communication, plus the basic framework for handling multiple connections in the server end (if there is a need for such).
Using UDP-sockets, you'll probably save a little latency and bandwidth (not much, unless you're using something like mobile data, you probably won't notice any difference with TCP in terms of latency), but the networking code is a bit harder task; UDP-sockets are "connectionless", meaning all the clients messages will end up in the same handler and must be distinguished from one another. If the server needs to keep up with client state, this can be somewhat troublesome to implement right.
MadProgrammer brought up RMI (remote method invocation), I've personally never used it, and it seems a bit cumbersome to set up, but might be pretty good in the long run in terms of implementation.
Probably one of the most common ways is to use http for the communication, for example via REST-interface for Web services. There are multiple frameworks (I personally prefer Spring MVC) to help with the implementation, but learning a new framework might be out of your scope for now. Also, complex http-queries or long urls could eat your bandwidth a bit more, but unless we're talking about very large amounts of simultaneous clients, this usually isn't a problem (assuming you run your server(s) in a datacenter with something like 100/100MBit connections). This is probably the easiest solution to scale, if it ever comes to that, as there're lots of load-balancing solutions available for web servers.

Categories

Resources