Vertx Eventbus not working in Java - java

OS Linux
JDK 1.7.0_67
Vert.x 2.1.5
Just getting started for wiring some of the vertx examples found on github.
Due to the manual want to try out a simple Sender <-> Receiver example, over EventBus. Many hours later, no ping, neither a hello world.
Anyone has an idea, what I'm missing on this simple code:
Sender.java
import org.vertx.java.platform.Verticle;
public class Sender extends Verticle {
public void start(){
vertx.eventBus().send("ping-address", "Hello");
}
}
Receiver.java
import org.vertx.java.core.Handler;
import org.vertx.java.core.eventbus.EventBus;
import org.vertx.java.core.eventbus.Message;
import org.vertx.java.platform.Verticle;
public class Receiver extends Verticle {
public void start() {
EventBus eb = vertx.eventBus();
eb.registerHandler("ping-address", new Handler<Message<String>>(){
#Override
public void handle(Message<String> message) {
container.logger().info("Message: "+message.body());
}
});
container.logger().info("PingVerticle started");
}
}
Running both in seperate JVM instances on the same machine, with following CLI command:
vertx run Receiver.java
> Succeeded in deploying verticle
another console:
vertx run Sender.java
> Succeeded in deploying verticle

The way you're running the vertices, they won't be able to see each other. They're essentially being started as completely separate processes with clustering disabled (the default). You have to run the vertices in cluster mode in order to get them to locate and communicate with one another. Use the -cluster option to enable Hazelcast clustering. You may also want to specify -host or -port.
If you continue seeing problems with even bus communication after that, enable Hazelcast logging and ensure the two nodes see each other. You may have to alter cluster.xml (the Hazelcast configuration) if your network does not support multicast.

Might be helpful for those who is using programmatic way of clustering.
Please check you have the following values set in your vertx options:
VertxOptions options = new VertxOptions().setClustered(true)
.setClusterHost("198.12.12.12")
.setHAEnabled(true)
.setHAGroup("dev");
Vertx.clusteredVertx(options, res -> System.out.println(res.succeeded()));

Related

Publishing multiple Endpoints with built-in Java JAX-WS web server

So I have 2 implementations, Impl1 and Impl2, of a web service interface class. I would like to publish both under the same domain and port but with different URLS:
http://some.domain.asd/ws1 and http://some.domain.asd/ws2
Apparently, I should be able to create a configuration where I have 2 Endpoints, one for each implementation, bound to a single web server instance.
Note that I am not deploying but using the Java 7 internal publishing mechanism.
I noticed that instead of calling
Endpoint.publish(URL, new Implementor());
to directly publish a web service, I can call
Endpoint ep = Endpoint.create(new Implementor());
ep.publish(serverContext);
to publish the Implementor at a specific serverContext. What exactly is such a serverContext and how do I use it? I noticed that the publish method instantiates a javax.xml.ws.spi.Provider class and uses it for publishing purposes. But that is apparently not what I am looking for. Ideally, I would like a solution that resembles something like this:
Object serverContext = new Server(URL);
Endpoint impl1 = Endpoint.create(new Impl1());
Endpoint impl2 = Endpoint.create(new Impl2());
impl1.publish(serverContext);
impl2.publish(serverContext);
Can this even be done with the built-in publishing system, maybe using EndpointReferences objects? Or am I required to use a web service container to deploy my Endpoints seperately?
Publishing multiple Endpoints running on the same port could be achieved with this code :
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Endpoint.publish("http://localhost:8888/ws/send", new SendServiceImpl());
Endpoint.publish("http://localhost:8888/ws/send23", new SendServiceImpl());
}
}
Running this locally in Eclipse it works , but when you deploy it to another server its broken.
To fix this you can either use http://0.0.0.0:8888 instead of localhost or the correct internal ip-address of the server.
You find it running:
windows: ipconfig
unix: ifconfig
It looks something like this: 192.168.100.55.
I stumbled across this problem today; I kept getting "java.net.BindException: Address already in use" when publishing two different endpoints to the same host+port. The solution is to instantiate the HttpServer yourself and "bind" each endpoint to this server:
package mypackage;
import com.sun.net.httpserver.HttpServer;
import javax.xml.ws.Endpoint;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public static void main(String[] args) throws IOException {
final HttpServer httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 8080), 16);
final Endpoint fooEndpoint = Endpoint.create(new FooImpl());
fooEndpoint.publish(httpServer.createContext("/Foo"));
final Endpoint barEndpoint = Endpoint.create(new BarImpl());
barEndpoint.publish(httpServer.createContext("/Bar"));
httpServer.start();
}

Can a deployment stop itself?

I'm currently searching for a way to stop a deployment on wildfly programmatically.
Background:
The application does some health checks in its startup phase using an MBean.
If the app determines that the environment is not valid because some resources are missing, it needs to stop its own deployment.
The way it was:
The application was formerly running on JBoss 4 and simply stopped the whole app server calling the shutdown command using JMX.
In case this command failed, it simply terminated the whole JVM using System.exit(1).
Current problems:
Calling shutdown() via JMX does not work on wildfly since the whole server hangs when trying to stop it from within a deployed application.
System.exit() will also not work since wildly must be catching the command in any way.
So does anyone know how to stop the server from within the deployment or stop the deployment process or undeploy the app?
Thanks a lot!
I assume the core question is stopping the deployment process if some health checks fail. Throwing a run-time exception during app startup is enough to do the job.
#Startup
#Singleton
public class StartupBean {
#PostConstruct
public void start() {
//your checks
boolean check = doHealthCheck();
if(!check){
throw new RuntimeException("Your error message");
}
}
}
or
#Startup
#Singleton
public class StartupBean {
#PostConstruct
public void start() {
//your checks
boolean check = doHealthCheck();
if(!check){
throw new Error("Your error message");
}
}
}
I suggest you to try WildFly CLI:
Running the CLI
or use Marker Files.
But in any case, I'm not sure how the server will behave. For example what will happen when You add file myWarName.dodeploy when there is myWarName.isdeploying. So let us know when You will earn some experience in this topic (it is quite interesting).
Ok, I did not yet manage to undeploy the app but I've been able to shutdown the server in case of an error. This is not perfect but matches the behavior of the app on the older version of JBoss, so I think it's not too bad at all.
I'm now calling the CLI interface like so
try {
String jbossBinDir = System.getProperty("jboss.server.base.dir").replace("standalone", "bin");
Runtime.getRuntime().exec("sh " + jbossBinDir + "/jboss-cli.sh -c command=:shutdown");
} catch(IOException e) {
...
}
This works reliable for us.
In my comment above I stated that the execution returns with an error code but this was probably the case because I must have had a typo in the command call.
We're using a CDI Extension to abort the deployment if our DB schema doesn't match the application's expectation:
class MyValidatingExtension implements javax.enterprise.inject.spi.Extension {
void deploymentValidationFinished(#Observes AfterDeploymentValidation afterDeploymentValidation) {
if (!stateExpected) {
afterDeploymentValidation.addDeploymentProblem(new IDontLikeThisException());
}
}
}
The deployment of the WAR will fail with the stacktrace of the exception listed as DeploymentProblem, leaving your WAR in an undeployed state. This solution is independent of your container implementation, it uses a CDI standard mechanism only. Note that this will not stop/shutdown the server!

Camel only sends the message on startup, then stops

I have hopefully a trivial problem. I wrote super short 'program' for Apache Camel to read the context.xml and then do as it is told:
public class CamelBridge {
public static void main(String[] args) throws Exception {
ApplicationContext context = new FileSystemXmlApplicationContext("camelContext.xml");
}
}
I connect between two JMS queues. The program works, but just when I start it. Then it stops sending messages. If I restart- it sends them all again. Is there something oviously wrong that I am missing here?
Edit:
I have updated my Main, but it does not help:
public class Bridge {
private Main main;
public static void main(String[] args) throws Exception {
Bridge bridge = new Bridge ();
bridge.boot();
}
public void boot() throws Exception{
main = new Main();
main.enableHangupSupport();
main.setApplicationContextUri("camelContext.xml");
main.run();
}
}
Edit 2
I think I found the issue (not the solution). After enabling tracing, I found the error message which reads:
jms cannot find object in dispatcher with id --some id--
And after some more digging I found that this is connected clientLeasePeriod in the remoting file. Any idea if it is possible to fix this kind of problem on Camel side?
You have to prevent JVM from finishing
Check this example: http://camel.apache.org/running-camel-standalone-and-have-it-keep-running.html
Provided you app contains only Main and xml file which configures Camel's context then context will be destroyed (so your routes destroyed as well). Even if different context run JMS implementation on same JVM. Sergey link should help you.
If you want just make it work to test things, add while(true) as a last line of your main. Note this is not the best approach :).
I realised that the problem was with the server on which the program was installed. The server thought that it resides on a public network, rather than private network (Windows Server 2012). After changing the network to private, the process worked correctly.
Note- the Camel did not give any errors regarding this, so this can be difficult to spot.

Migrating an application to a service mode [java/groovy]

I've got an application written in groovy. It takes some cmd args and returns previously formatted response. As system grew, it appeared that it is required to run this app extremely frequently (like 80 times in 5 mins) which leads to certain performance issues. In particular it creates all its objects over and over again which leads to filling up to 60MB RAM in one run (can be easily calculated how severely ROM/swap is used).
I want to migrate it to a service running mode which will simply take certain params and return formatted output. But:
App is always triggered by a bat/sh script (this can't be changed)
Both script and app are on the same host server
So, I'm wondering how it would be better to perform the communication of a script and a service?
P.S.: Sorry that I didn't mention, it's a standalone app, it will never use a server or anything like that as it appears to be redundant. Solution should be as simple as possible and extremely lightweight.
Example: The simplest thing I can think of by now is never to migrate it (I know it's contradictory ;)) and simply introduce a DB where all thee result will be stored and an app will have it's own schedule of when to trigger. Whenever it is triggered with any params, it should simply search the latest result in DB and return it. Easy, light, fast, and working. :)
For enterprise environments I would suggest a JavaEE application with EJB running in an application server. For your requirements this might be an overkill. A simple solution can be:
Service: Implement a RMI server with a local RMI registry. Calculations will be done here.
Script: Connect to the RMI server, invoke a method at the RMI server and display the result.
RMI Server
public class RmiServer extends UnicastRemoteObject implements RmiInterface
{
private static final long serialVersionUID = 1L;
public RmiServer() throws RemoteException
{
super();
}
public String random() throws RemoteException
{
return "Helo World! "+(new Random()).nextInt(100);
}
public static void main(String[] args) throws RemoteException, MalformedURLException
{
LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
Naming.rebind("myServer", new RmiServer());
}
}
RMI Client
RmiInterface server = (RmiInterface)Naming.lookup("//127.0.0.1/myServer");
System.out.println(server.random());
RMI Interface
public interface RmiInterface extends Remote
{
public String random() throws RemoteException;
}

file listener process on tomcat

I need a very simple process that listens on a directory and
does some operation when a new file is created on that directory.
I guess I need a thread pool that does that.
This is very easy to implement using the spring framework, which I normally use but I can't use it now.
I can only use tomcat, How can I implement it? what is the entry point that "starts" that thread?
Does it have to be a servlet ?
thanks
since you refined the question, here comes another answer: how to start a daemon in tomcat:
first, register your Daemons in web.xml:
< listener >
my.package.servlet.Daemons
< /listener >
then implement the Daemons class as an implementation of ServletContextListener like this:
the code will be called every 5 seconds, tomcat will call contextDestroyed when your app shuts down. note that the variable is volatile, otherwise you may have troubles on shutdown on multi-core systems
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class Daemons implements ServletContextListener {
private volatile boolean active = true;
Runnable myDeamon = new Runnable() {
public void run() {
while (active) {
try {
System.out.println("checking changed files...");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
public void contextInitialized(ServletContextEvent servletContextEvent) {
new Thread(myDeamon).start();
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
active = false;
}
}
You could create a listener to start the thread, however this isn't a good idea. When you are running inside a Web container, you shouldn't start your own threads. There are a couple of questions in Stack Overflow for why is this so. You could use Quartz (a scheduler framework), but I guess you couldn't achieve an acceptable resolution.
Anyway, what you are describing isn't a Web application, but rather a daemon service. You could implement this independently from your web application and create a means for them to communicate with each other.
true java-only file notifiaction will be added in java 7. here is a part of the javadoc that describes it roughly.
The implementation that observes events from the file system is intended to map directly on to the native file event notification facility where available
right now you will have to either create a native platform-dependent program that does that for you,
or alternatively implement some kind of polling, which lists the directory every so often to detect changes.
there is a notification library that you can use right now - it uses a C program on linux to detect changes over at sourceforge. on windows it uses polling. i did not try it out to see if it works.

Categories

Resources