Vert.x - How to get POST Value passed between Verticles? - java

This the class that runs verticles :
public class RequestResponseExample {
public static void main(String[] args) throws InterruptedException {
Logger LOG = LoggerFactory.getLogger(RequestResponseExample.class);
final Vertx vertx = Vertx.vertx();
final Handler<AsyncResult<String>> RequestHandler = dar-> vertx.deployVerticle(new ResponseVerticle());
vertx.deployVerticle(new ResponseVerticle(), RequestHandler);
}
}
This is The Request verticle Class :
public class RequestVerticle extends AbstractVerticle{
public static final Logger LOG = LoggerFactory.getLogger(RequestVerticle.class);
static final String ADDRESS = "my.request.address";
#Override
public void start() throws Exception {
Router router = Router.router(vertx);
router.get("/Test").handler(rc -> rc.response().sendFile("index.html"));
vertx.createHttpServer()
.requestHandler(router)
.listen(8080);
}
}
This is The Response verticle Class: Here Im having a difficulty getting The Inserted value in the HTML file
public class ResponseVerticle extends AbstractVerticle{
public static final Logger LOG = LoggerFactory.getLogger(RequestVerticle.class);
#Override
public void start() throws Exception {
Router router = Router.router(vertx);
// How to handle the POST value ?
router.post("/Test/Result").handler(rc -> rc.end("The Post Value"));
vertx.createHttpServer()
.requestHandler(router)
.listen(8080);
}

When the user invokes POST /Test/Result and sends some POST value, you receive it in your Response verticle class (third snippet). If you want to share that method with other verticles, you should store it somewhere inside the handler method so other verticles access it or immediately forward it to other verticle via the event bus.
One possible solution would be to create a third verticle (e.g. StorageVerticle) which has get and set methods. That way, ResponseVerticle invokes the set method to store the value it got, and the RequestVerticle invokes the get method to fetch the value the user sent on calling POST method.
The other solution of direct communication between verticles involves the Event Bus message exchange - one verticle publishes/sends a message and all other verticles can register as a consumer to get that message. More on this you can find here: https://vertx.io/docs/vertx-core/java/#_the_event_bus_api.
It is hard to say which approach is better because it is case-to-case basis and I have limited information here about the scope of the project.

Related

JDA send notification to private channels

I want to have an ability to send notification to private channels of all users in my group
This is my code
public static void main(String[] args) throws LoginException {
final JDA bot =
new JDABuilder(AccountType.BOT)
.setToken("secret")
.addEventListener(new DemoApplication())
.build();
}
#Override
public void onPrivateMessageReceived(final PrivateMessageReceivedEvent event) {
if (event.getAuthor().isBot()) {
return;
}
event.getJDA().getGuilds().get(0).getMembers().forEach(user->user.getUser().openPrivateChannel().queue());
event.getJDA().getPrivateChannels().forEach(privateChannel -> privateChannel.sendMessage("ZDAROVA").queue());
}
But only sender of this private message receive a message . What did i miss ?
I use JDA with version 3.8.3_462
Your code makes use of async operations. An async task is one that is started on another thread and possibly happens at a later time.
Discord has rate-limits which have to be respected by the operating client. For this reason and the reason that HTTP requests take some time, the requests happen in the background. The method you're using which is called queue() simply puts the request on a queue that is drained by a worker thread.
openPrivateChannel() returns RestAction<PrivateChannel> which means it will receive a private channel instance as a response. This response can be interacted with by using the callback parameter of queue(Consumer<PrivateChannel> callback).
static void sendMessage(User user, String content) {
user.openPrivateChannel().queue(channel -> { // this is a lambda expression
// the channel is the successful response
channel.sendMessage(content).queue();
});
}
guild.getMembers().stream()
.map(Member::getUser)
.forEach(user -> sendMessage(user, "ZDAROVA"));
More information on RestAction is available in the JDA Wiki and Documentation.

Vertx http server only creating one instance

I am creating a simple micro service using vertx and when i start my server it only create one event thread when available is 12.
My code to start server is
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
int processorCounts = Runtime.getRuntime().availableProcessors();
DeploymentOptions options = new DeploymentOptions().setInstances(processorCounts);
vertx.deployVerticle( HttpRouter.class.getName(),options);
}
And my http router looks like this
#Override
public void start() throws Exception {
super.start();
Router router = Router.router(vertx);
router.get("/").handler(event -> {
event.response().end("Hello World");
});
vertx.createHttpServer().requestHandler(router::accept).listen(8001);
}
What is your process for testing? I assume you opened a browser and hit refresh on the same page. Then yes, the same verticle instance will handle the requests. The reason is Vert.x load balances connections among verticles instances, not requests.
Open a different browser and you should see different event loop names.

How to keep apache camel context alive in thread main

I'm trying to make simple application that will listen one queue from artemis and then proceed messages and after that create new message in second queue.
I have created in method Main Camel context and added routing (it forwards messages to bean). And to test this routing and that this bean works correctly I'm sending
few messages to this queue - rigth after context started in main thread
public static void main(String args[]) throws Exception {
CamelContext context = new DefaultCamelContext();
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616", "admin", "admin");
context.addComponent("cmp/q2", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));
context.addRoutes(new RouteBuilder() {
public void configure() {
from("cmp/q2:cmp/q2").bean(DataRequestor.class, "doSmth(${body}, ${headers})");
}
});
ProducerTemplate template = context.createProducerTemplate();
context.start();
for (int i = 0; i < 2; i++) {
HashMap<String, Object> headers = new HashMap<String, Object>();
headers.put("header1", "some header info");
template.sendBodyAndHeaders("cmp/q2:cmp/q2", "Test Message: " + i, headers);
}
context.stop();
}
And in this case application works fine, but it stops when method main completed - it proceess only messages that were created by it self.
Now after I have test bean that is used in routing, I want to modify application such way that it should start and stay active(keeping camle context and routin alive ) - so that i can create massages manually in web UI (active mq management console).
But I really don't know how.
I have tried infinite loop with Thread.sleep(5000);
I tried to start one more thread(also with infinite loop) in main method.
But it didn't work.(The most suspicious for me in case with infinite loop is that apllication is running, but when i create message in web UI it just desapears - and no any traces in system out that it was processed by my bean in routing, a suppose that it should be processed by my bean or just stay in the queue untouched, but it just disapears).
I now that my question is dummy, but I already have wasted 3 days to find a solution, so any advices or link to tutorials or some valueable information are appreciated.
PS: I've got one painfull restriction - Spring frameworks are not allowed.
I think the most simple solution for running standalone camel is starting it with camel Main. Camel online documentation has also an example of using it http://camel.apache.org/running-camel-standalone-and-have-it-keep-running.html.
I will copy paste the example code here just in case:
public class MainExample {
private Main main;
public static void main(String[] args) throws Exception {
MainExample example = new MainExample();
example.boot();
}
public void boot() throws Exception {
// create a Main instance
main = new Main();
// bind MyBean into the registry
main.bind("foo", new MyBean());
// add routes
main.addRouteBuilder(new MyRouteBuilder());
// add event listener
main.addMainListener(new Events());
// set the properties from a file
main.setPropertyPlaceholderLocations("example.properties");
// run until you terminate the JVM
System.out.println("Starting Camel. Use ctrl + c to terminate the JVM.\n");
main.run();
}
private static class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer:foo?delay={{millisecs}}")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Invoked timer at " + new Date());
}
})
.bean("foo");
}
}
public static class MyBean {
public void callMe() {
System.out.println("MyBean.callMe method has been called");
}
}
public static class Events extends MainListenerSupport {
#Override
public void afterStart(MainSupport main) {
System.out.println("MainExample with Camel is now started!");
}
#Override
public void beforeStop(MainSupport main) {
System.out.println("MainExample with Camel is now being stopped!");
}
}
}
The route keeps executing until you hit Ctlr+c or stop it in some other way...
If you test this, notice that you need example.properties file in your classpath, with the property millisecs.
At the very minimum you need a main thread to kick off a thread to run the camel route and then check for when that thread is done. The simple java threading approach using the main loop to check .wait() and the end of the camel route thread to signal .notify() when it finishes (or shutdown) would get the job done.
From there you can look into an executor service or use a micro-container like Apache Karaf
PS. Props for going Spring-free!
Disclaimer: this is written in Kotlin but it is somewhat trivial to port to java
Disclaimer: this is written for Apache-Camel 2.24.2
Disclaimer: I am also learning about Apache-Camel. The docs are a little heavy for me
I tried the Main route to set it up but it quickly got a little convoluted. I know that this is a java thread but I'm using kotlin ATM, I'll leave most of the types and imports available so it's easier for java devs.
class Listener
The first I had to fight with was understanding the lifecycle of Main. It turns out that there is an interface you can implement to add in the implementations of such events. With such an implementation I can hook up any routines that have to be sure that camel has started (no guessing required).
import org.apache.camel.CamelContext
import org.apache.camel.main.MainListener
import org.apache.camel.main.MainSupport
typealias Action = () -> Unit
class Listener : MainListener {
private var afterStart: Action? = null
fun registerOnStart(action:Action) {
afterStart = action
}
override fun configure(context: CamelContext) {}
override fun afterStop(main: MainSupport?) {}
override fun afterStart(main: MainSupport?) {
println("started!")
afterStarted?.invoke().also { println("Launched the registered function") }
?: println("Nothing registered to start")
}
override fun beforeStop(main: MainSupport?) {}
override fun beforeStart(main: MainSupport?) {}
}
class ApplicationCore
Then I set up the configuration of the context (Routes, Components, etc,...)
import org.apache.camel.CamelContext
import org.apache.camel.impl.DefaultCamelContext
import org.apache.camel.impl.SimpleRegistry
import org.apache.camel.main.Main
class ApplicationCore : Runnable {
private val main = Main()
private val registry = SimpleRegistry()
private val context = DefaultCamelContext(registry)
private val listener = Listener() // defined above
// for Java devs: this is more or less a constructor block
init {
main.camelContexts.clear()
listener.registerOnStart({ whateverYouAreDoing().start() })// <- your stuff should run in its own thread because main will be blocked
main.camelContexts.add(context)
main.duration = -1
context.addComponent("artemis", ...)// <- you need to implement your own
context.addRoutes(...)// <- you already know how to do this
...// <- anything else you could need to initialize
main.addMainListener(listener)
}
fun run() {
/* ... add whatever else you need ... */
// The next line blocks the thread until you close it
main.run()
}
fun whateverYouAreDoing(): Thread {
return Thread() {
ProducerTemplate template = context.createProducerTemplate();
for (i in 0..1) {
val headers = HashMap<String, Any>()
headers["header1"] = "some header info"
template.sendBodyAndHeaders("cmp/q2:cmp/q2", "Test Message: $i", headers)
}
context.stop()// <- this is not good practice here but its what you seem to want
}
}
}
In kotlin, initialization is rather easy. You can easily translate this into java because it is quite straight forward
// top level declaration
fun main(vararg args:List<String>) = { ApplicationCore().run() }

Is there any way to know whether referring to to non existing actor in akka

I am trying to post messages to some existing actors like show below but there may be a chance to to refer non existing actor and i would like to know before posting the message.
Thanks in advance
actor = getContext().actorFor("actorSystem/user/" + nameOfActor);
actor.tell("message",getSelf());
You can send them Identify message prior to sending your actual message. All actors understand it and should reply with Self(). Alternatively use resolveOne method:
You can acquire an ActorRef for an ActorSelection with the
resolveOne method of the ActorSelection. It returns a Future of the
matching ActorRef if such an actor exists. It is completed with
failure [[akka.actor.ActorNotFound]] if no such actor exists or the
identification didn't complete within the supplied timeout.
The only possible way of knowing that an actor is alive (without DeathWatch) is by receiving a message from it. And that only proves that the actor was alive at some point in time (when it has sent the message).
The following is snippet of my code how i implemented used DeadLettersHandler actor to handle DeadLetters
public class MyActor extends UntypedActor
{
#Override
public void onReceive(Object message) throws Exception
{
System.out.println("MyActor received : "+message.toString());
}
}
public class DeadLettersHandler extends UntypedActor
{
public void onReceive(Object deadLetter) throws Exception
{
System.out.println("DeadLettersHandler received : "+deadLetter.toString());
}
}
public class DeadLetterTest
{
public static void main(String[] args)
{
ActorSystem MyActorSystem = ActorSystem.create("MyActorSystem");
ActorRef existingActor = MyActorSystem.actorOf(Props.create(MyActor.class),"ExistingActor");
ActorRef DLH = MyActorSystem.actorOf(Props.create(DeadLettersHandler.class), "DeadLetterHandler");
MyActorSystem.eventStream().subscribe(DLH, DeadLetter.class);
ActorSelection nonExist = MyActorSystem.actorSelection("akka://user/MyActorSystem/NonExistingActor");
existingActor.tell("Hello Akka", existingActor);
nonExist.tell("Hello Akka", DLH);
MyActorSystem.shutdown();
}
}
output:
MyActor received : Hello Akka
DeadLettersHandler received : DeadLetter(Hello Akka,Actor[akka://MyActorSystem/user/DeadLetterHandler#-3707992],Actor[akka://MyActorSystem/deadLetters])
[INFO] [10/10/2013 15:43:43.343] [MyActorSystem-akka.actor.default-dispatcher-6] [akka://MyActorSystem/deadLetters] Message [java.lang.String] from Actor[akka://MyActorSystem/user/DeadLetterHandler#-3707992] to Actor[akka://MyActorSystem/deadLetters] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
Actually I need to handle the every message received, if a actor not exists then that message has to be handled separately which i achied using Deadletter implementation
final ActorRef actor = actorSystem.actorOf(new Props(DeadLetterHandlerActor.class));
actorSystem.eventStream().subscribe(actor, DeadLetter.class);

Netty - How to get server response in the client

I'm mostly there with Netty but one concept is still alluding me, and I can't find anything in the tutorials and so on. Firstly I do understand that Netty is asynchronous, but there must be a way for a client to call the server and be able to get a response beyond the handler. Let me explain more.
I have a client as illustrated below. And please note that I understand it's bootstrapped and a new connection is established on each call, that's just there to make the example smaller and more succinct. Please ignore that fact.
Client.java
// ServerResponse is a result from the server, in this case
// a list of users of the system (ignore that each time it's all bootstrapped).
public User[] callServerForInformationFromGUIWidget()
{
ClientBootstrap bootstrap = new ClientBootstrap(...);
bootstrap.setPipelineFactory(...);
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
Channel channel = future.awaitUninterruptibly().getChannel();
// Where request is a POJO sent to the server,
// with a request such as get me a list of users
RequestPojo request = new RequestPojo(requestUserListCommand);
ChannelFuture lastWriteFuture = channel.write(request);
if(lastWriteFuture != null)
lastWriteFuture.awaitUninterruptibly();
}
Now I understand how to get the data on the server, and fire back the result. The only thing is how do I handle it on the client side? Yes the clientHandler class can do something like the following:
ClientHandler.java
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
{
User[] users = (User[])e.getMessage();
}
The problem is how does the client code actually get that result? All the examples are similar to a chat service, where the event fires off something else on the client that's not waiting on a response. Even the http client example I found lacking this. The documentation overall is really good, but it's lacking on how to do callbacks. Anyways, in this case I need the client to get the response from the server, and based on the results it will do what it needs.
In other words, how do I write the client to do something like this:
IdealClient.java
// ServerResponse is a result from the server, in this case
// a list of users of the system.
public User[] callServerForInformationFromGUIWidget()
{
...
RequestPojo request = new RequestPojo(requestUserListCommand);
ChannelFuture lastWriteFuture = channel.write(request);
if(lastWriteFuture != null)
lastWriteFuture.awaitUninterruptibly();
User[] users = resultFromCallToServer();
performSomeAction(users);
}
Because the handler doesn't know who is looking for the answer, or who asked the question. And if it's done in the handler, than how?
Back to my comments about the examples, the http client (and handler) examples just dump the result to System.out. If you had a GUI how would you pass the result from your request up to the GUI? I never saw any examples for this.
Jestan is correct. In my case I have a client that need to process price tick data. I use Antlr for the parsing. I fire my events in my parser, but in my case my protocol is String based. Below is an example without Antlr, I pass the String message in your case it could be the users.
//----------------- Event --------------
public class DataChangeEvent {
private String message;
public DataChangeEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
//----------------- Listener --------------
public interface DataChangeListenter {
public void dataChangeEvent(DataChangeEvent event);
}
//----------------- Event Handler that fires the dataChange events --------------
// This class needs to be static since you need to register all your classes that want to be notified of data change events
public class DataChangedHandler {
private static List<DataChangeListenter> listeners = new ArrayList<DataChangeListenter>();
public static void registerDataChangeListener(DataChangeListenter listener) {
listeners.add(listener);
}
public static void fireDataChange(DataChangeEvent dataChangeEvent) {
for(DataChangeListenter listenter : listeners) {
listenter.dataChangeEvent(dataChangeEvent);
}
}
}
//----------------- Example class that implements the listener and registers itself for events --------------
public class ProcessMessage implements DataChangeListenter {
public ProcessMessage() {
DataChangedHandler.registerDataChangeListener(this);
}
public void dataChangeEvent(DataChangeEvent event) {
//Depending on your protocal, I use Antlr to parse my message
System.out.println(event.getMessage());
}
}
//---------------- Netty Handler -----------
public class TelnetClientHandler extends SimpleChannelHandler {
private static final Logger logger = Logger.getLogger(TelnetClientHandler.class.getName());
#Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
String message = (String) e.getMessage();
DataChangedHandler.fireDataChange(message);
}
}
You have to handle it in the Handler with messageReceived(). I'm not sure what your issue is exactly. My guess is you have a response to a request that changes depending on what request was made? Maybe a concrete description of something you are doing of a response that has to know what request it came from. One thing you might be able to do is to pass a long living object the handler that knows the outstanding request, and it can match up the response when it receives it. The pipeline factory method can pass a reference to a manager type object to the Handler.
This was pretty much what I was trying to say. Your Handler is created in the PipelineFactory which is easy to pass parameters to the Handler from there:
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.nulDelimiter()));
pipeline.addLast("decoder", new XMLDecoder() );
pipeline.addLast("encoder", new XMLEncoder() );
// notice here I'm passing two objects to the Handler so it can
// call the UI.
pipeline.addLast("handler", new MyHandler(param1, param2));
return pipeline;
}
});
When you create your pipeline you'll add your Handler upon a new connection. Simply pass one or more objects that allows it to communicate back to the UI or a controller.

Categories