Camel only sends the message on startup, then stops - java

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.

Related

How to handle exception using onException() in Spring Boot Camel

Spring boot Apache Camel-Java DSL app reads messages from Kafka topic.
#Component
public class KafkaTopicService extends RouteBilder {
public void configure(){
from("kafka:myTopic?brokers=localhost:9092")
.log("Message received from Kafka: ${body}")}
}
If I stop Kafka I get org.apache.kafka.common.errors.DisconnectException
I looked into onException(...class).handled(true) but Im not sure how to implement handling of the exception in my code. Can someone give me few implementation examples? What options are available? For example logging the message or reattempting to read message?
Documentation also mentions Quarkus. Do I need Quarkus to use onException()?
You can do something like (have not tried running it so please take care of any typos)
#Component
public class KafkaTopicService extends RouteBilder {
public void configure(){
onException(org.apache.kafka.common.errors.DisconnectException.class)
.log("Error connecting kafka");
from("kafka:myTopic?brokers=localhost:9092&bridgeErrorHandler=true")
.log("Message received from Kafka: ${body}")}
}
Please note that I have added bridgeErrorHandler=true. Normally exception handling happens after from. In most of the case using bridgeErrorHandler we can use onException function for those.
Also note that I have defined onException outside your route, so the exception handling logic which you add would be global and applicable to all routes wherever you encounter DisconnectException

Java EE7 websocket initialization - implement logic before first #OnOpen

I think this is more a design specific question, than direct coding issue.
I want to implement a websocket service which serves an updated dataset from a foreign http:// resource to the clients.
but i want to have the data available before the first client connects, so #OnLoad notation won't do.
In HttpServlet world I would
#Override
public void init() throws...
I could not figure out a suitable way for doing so just using JSR-356.
I tried with custom ServerEndpointConfig.Configurator but that does not seem to give me access to method similar to init() from HttpServlet.
So my question is:
Letting the websocket Endpoint class extend HttpServlet gives me access to the init() method and I can place my initial logic there.
Is that a suitable way for solving my problem, or have i missed something in JSR-356 which does the job elegantly and without importing mostly unused servlet packages?
Thank you very much!
A class annotated with #ServerEndpoint("/myEndPoint") is instantiated each time a new connection is created via #OnOpen. It is not a static class nor a singleton (e.g. not behaves as Spring #Service).
I have a similar problem to yours, I need to make a web socket the observer of a Spring web service (don't ask, I'm with you that is a bad architecture the problem). In order to make it an observer, I have to add it to the observable class, but because of the lack of an initialization for the web socket I don't have a clear spot where to add the observer, adding it in the #OnOpen method would repeatedly add it on each new connection.
The only solution I found is a workaround. Usually a web socket class has a static Set of the peers connected to it, you need something similar for your initialization. Either use a static block or a static flag in the constructor. In my case I solved with:
private static boolean observerFlag = false;
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
public MyWebSocket() {
if (!observerFlag) {
observable.addObserver(this);
observerFlag = true;
}
}
And to remove the observer:
#OnClose
public void onClose(Session peer) {
peers.remove(peer);
if (peers.isEmpty()) {
observable.deleteObserver(this);
observerFlag = false;
}
}
I repeat that this is a workaround, I think that there is a more elegant solution.

How to log within shutdown hooks with Log4j2?

Log4j2 also uses shutdown hooks to end it's services. But of course I want to log throughout the whole lifecycle of my application - shutdown included. With Log4j this was no problem. Now it seems to be impossible. Logging shuts down, while my application is still working on it. Has anyone some hope for me?
Best regards
Martin
As of 2.0-beta9 this is now configurable in xml
<configuration ... shutdownHook="disable">
Considering its now disabled, I guess I need to manually shutdown the logging system at the end of my shutdown hook. However I couldn't find a means thorough the external interface, only in the internal api
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.LoggerContext;
...
public static void main(String[] args) {
final AnnotationConfigApplicationContext springContext = new AnnotationConfigApplicationContext(AppConfig.class)
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
//shutdown application
LOG.info("Shutting down spring context");
springContext.close();
//shutdown log4j2
if( LogManager.getContext() instanceof LoggerContext ) {
logger.info("Shutting down log4j2");
Configurator.shutdown((LoggerContext)LogManager.getContext());
} else
logger.warn("Unable to shutdown log4j2");
}
});
//more application initialization
}
Update:
There is LogManager.shutdown() method since log4j version 2.6
I basically just answered the same question and I tough I'll share my answer here. I encourage you to read the complete answer available here. I'll try to provide a summary here and adapt my answer to the current context.
In the first version, Log4j was providing an API to manually call the shutdown procedure. For reasons we don't have the knowledge of, it was removed from the second version. Now, the right way of doing it (according to the none-existent documentation), is to provide your own implementation of the ShutdownCallbackRegistry interface, which is responsible of the shutdown procedure.
Proposed solution
What I did to fix this issue is that I implemented my own version of the ShutdownCallbackRegistry interface. It mostly does the same things the default implementation does, but instead of registering itself as a shutdown hook to the JVM, it wait until it's invoked manually.
You can find the complete solution and instructions on GitHub/DjDCH/Log4j-StaticShutdown and use it in you own projects. Basically, at the end, you only have to do something like this in your application:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
try {
// Do your usual shutdown stuff here that need logging
} finally {
// Shutdown Log4j 2 manually
StaticShutdownCallbackRegistry.invoke();
}
}
}));
I can't say without any doubt that this is the perfect solution and that my implementation is perfect, but I tried to do it the right way. I'll be glad to hear feedback from you, either if you find this solution appropriate or not.

Remove Webservice from Windows machine

I am following a little tutorial for JAX-WS mkyong - jax-ws
I have published this little example with the following code on my Windows 7 machine.
But how can I update or remove this webservice?
public class HelloWorldPublisher {
public static void main(String[] args) {
Endpoint.publish("http://localhost:9999/ws/hello", new HelloWorldImpl());
}
}
Remove : If you want to remove the web service, just use the Endpoint.stop() (read here) methods for stopping it accept the requests.
Update : Just change the code in the HelloWorldImpl class. It will automaticaly call the newly updated code.
Endpoint.publish() simply tells the server that the requests in the given URL should be processed using HelloWorldImpl

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;
}

Categories

Resources