JAX-RS: How to run a method on start (without servlets) - jersey

I have a JAX-RS (Jersey) server with which I register and bind my stuff.
I want to print a banner when the server starts up. I want to do this using the JAX-RS framework not the web server's platform (i.e., no Jetty, Netty, Thorntail, etc hooks).
I saw the following which mentions the tried and true Servlet way of doing things:
Jax rs: How can I run a method automatically everytime my server restarts? , but that does not work because I am not running a servlet container in my server so that lifecycle call is never made.
I figured there must be a JCA-ish type object that I can register with Application/ResourceConfig that has such a lifecycle call, but I am unable to even find any kind of list of the things you can actually register.
Not to complain (but I will), but I cannot decide if this is so difficult because when they moved the project to eclipse, they broke every hyperlink to the old official documentation or that it is simply so implicit, like Spring, that it only works by github'ing other people's code and realizing, 'oh, I did not know you could do that'.

Jersey has Event Listeners. You'll want to use the ApplicationEventListener and the ApplicationEvent.Type you'll probably want to listen for to print the banner is the INITIALIZATION_FINISHED
public class MyApplicationEventListener
implements ApplicationEventListener {
#Override
public void onEvent(ApplicationEvent event) {
switch (event.getType()) {
case INITIALIZATION_FINISHED:
printBanner();
break;
}
}
#Override
public RequestEventListener onRequest(RequestEvent requestEvent) {
return null;
}
}

Related

Mule connector config needs dynamic attributes

I have develop a new Connector. This connector requires to be configured with two parameters, lets say:
default_trip_timeout_milis
default_trip_threshold
Challenge is, I want read ${myValue_a} and ${myValue_a} from an API, using an HTTP call, not from a file or inline values.
Since this is a connector, I need to make this API call somewhere before connectors are initialized.
FlowVars aren't an option, since they are initialized with the Flows, and this is happening before in the Mule app life Cycle.
My idea is to create an Spring Bean implementing Initialisable, so it will be called before Connectors are init, and here, using any java based libs (Spring RestTemplate?) , call API, get values, and store them somewhere (context? objectStore?) , so the connector can access them.
Make sense? Any other ideas?
Thanks!
mmm you could make a class that will create the properties in the startup and in this class obtain the API properties via http request. Example below:
public class PropertyInit implements InitializingBean,FactoryBean {
private Properties props = new Properties();
#Override
public Object getObject() throws Exception {
return props;
}
#Override
public Class getObjectType() {
return Properties.class;
}
}
Now you should be able to load this property class with:
<context:property-placeholder properties-ref="propertyInit"/>
Hope you like this idea. I used this approach in a previous project.
I want to give you first a strong warning on doing this. If you go down this path then you risk breaking your application in very strange ways because if any other components depend on this component you are having dynamic components on startup, you will break them, and you should think if there are other ways to achieve this behaviour instead of using properties.
That said the way to do this would be to use a proxy pattern, which is a proxy for the component you recreate whenever its properties are changed. So you will need to create a class which extends Circuit Breaker, which encapsulates and instance of Circuit Breaker which is recreated whenever its properties change. These properties must not be used outside of the proxy class as other components may read these properties at startup and then not refresh, you must keep this in mind that anything which might directly or indirectly access these properties cannot do so in their initialisation phase or your application will break.
It's worth taking a look at SpringCloudConfig which allows for you to have a properties server and then all your applications can hot-reload those properties at runtime when they change. Not sure if you can take that path in Mule if SpringCloud is supported yet but it's a nice thing to know exists.

Combine Jersey with Tyrus

I have a Jersey JAX-RS application which runs on a Grizzly instance:
public class Application {
public static final String BASE_URI = "http://127.0.0.1:8080/rest";
public static void main(String[] args) throws IOException {
ResourceConfig rc = new ResourceConfig().packages("my.package.rest");
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
System.out.println("Server started, press any key to stop.");
System.in.read();
server.shutdownNow();
}
}
inside my.package.rest there are JAX-RS annotated resources. I'd like to add websocket annotated (#ServerEndpoint, #OnOpen, #OnMessage, etc.) resources using Tyrus on the same server instance (say in "http://127.0.0.1:8080/websocket") but all the documentation I was able to find shows how to start a standalone websocket server using Tyrus + a Grizzly container, not combined with Jersey. I'm looking for something like:
server.getServerConfiguration().addHttpHandler(new SomeTyrusHttpHandler("/websocket"));
but I can't find anything similar to SomeTyrusHttpHandler. How can I combine Jersey and Tyrus in a single Grizzly server?
good question, but there is currently no good answer for this one. You still can do that, but it would require to deep dive into Grizzly internals; Tyrus is registered by an addon (see WebSocketAddOn) and it can be combined with Jersey way of registering into that container.
Please have in mind that integrating these two frameworks together is not trivial challenge - running them in a single container is a first step, but there are other things which need to be taken care of, like "instance provider", lifecycle adjustment, etc. I believe this topic exceeds the scope of one SO answer - you can expect blogpost from me or some other Tyrus/Jersey team member about this. (I'll post it here once that is done).
Anyway, I would recommend to take more conservative approach and use some lightweight container which supports Servlet 3.1; that should require far less work on your side and you'll have standard Servlet runtime / lifecycle.

release db connections in standalone application

I am working on a standalone application using Spring/JPA and I am trying to release properly the database resources used.
In a Web application using tomcat for example, we shutdown the server, and this way, we let Tomcat manage the resources.
But as I am in a standalone app, I have to take care about this, I use Runtime.getRuntime().addShutdownHook to "catch" the shutdown event and call ((ClassPathXmlApplicationContext) context).close();, something like this:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
((ClassPathXmlApplicationContext) context).close();
}
It works but with an exception in the stacktrace if a thread was using a connection.
I am wondering if there is another option? Maybe getting a list of open transactions and force them to rollback?
I believe that you would need to implement something like this and inside your destroy method, you would retrieve your datasource and call a close method or something similar. I'm also assuming you have a few things to do when you shutdown your application.
I can't quite help with the right method name as I don't know what you are using for your datasource.

Use Container/DependencyResolver in other dll

I'm trying to get myself familiar with MVC3 and autofac but I've encountered small problem that I'm having trouble resolving.
I am using autofac integrated with MVC3 and all works well, pages are loading correctly, dependencies are being injected and that's cool. What's bugging me is how to use autofac's Container or MVC's DependencyResover in class library project.
I'm trying to create static class that will help me handle domain events. I simply want to be able to call the method with event parameter and everything should be handeled by this class. Here is code:
public static IContainer Container { get; set; }
public static void Raise<T>(T e) where T : IDomainEvent
{
foreach (var eventHandler in DomainEventManager.Container.Resolve<IEnumerable<EventHandlers.Handles<T>>>())
{
eventHandler.Handle(e);
}
}
As you can see it's pretty straightforward and everything would work great if it wasn't MVC approach. Some of my dependencies are registeres as InstancePerHttpRequest (NHibernate' session), while other are registered as InstancePerDependency or SingleInstance. Thus when I try to use container created in my UI project, I get exception that there is no httpRequest tag available.
How can i reuse the Container created in web project to get access to all of it's features, including InstancePerHttpRequest and httpRequest tag?
Or maybe there is other solution to my problem? I was thinking about using delegate function to obtain event handlers, but I cannot (can I?) create generic delegate that I would not need to initialize with concrete type at time of assignment.
Why I want to do this using static class is basically every entity and aggregate or service needs to be able to raise domain event. Injecting EventManager into every one of these would be troublesome and static class is exactly what would resolve all my problems.
If anyone could help me get my head around it I would be grateful.
Cheers, Pako
You shouldn't be referencing your container directly from your app code. This looks like the Service Locator anti-pattern. The correct action is to pass your objects the services they need to do their jobs, usually done through constructor parameters. BUT... if you are going to insist on depending on a global static, then at least model EventManager as a singleton, such that usage would look like:
EventManager.Current.Raise<SomeEvent>(someObject);
and then you can set EventManager.Current equal to a properly constructed instance when your app is initialized.

OSGi: Is it valid to register services within a declarative service component activation method?

This is a duplicate of another question, but copying from the other one:
I've run into an issue with Felix SCR where I get the message:
ServiceFactory.getService() resulted in a cycle
The reason this appers to be occuring is because within an activation method, call it ServiceAImpl (which provides ServiceA), the service registers another service, call it ServiceB.
I have another service component, call it ServiceCImpl, which depends on both ServiceA and ServiceB. By ServiceAImpl registering ServiceB, ServiceCImpl has become satisfied and within the same call to activate ServiceAImpl, the ServiceCImpl binding methods are called. When the binding method for ServiceA is called, the cycle is detected and the component fails to initialize.
Maybe there is a way to allow the SCR to wait to bind the ServiceCImpl or maybe I need to be registering ServiceB differently?
I guess what doesn't make sense is why the Felix SCR will activate ServiceCImpl within the activation method of ServiceAImpl. I wouldn't think that ServiceCImpl would be considered satisfied until after the activation method has exited. Perhaps this is an issue of using declarative services while still registering services directly with the framework?
Haven't tried other SCR implementations, like Equinox's version, but I might try that to see if there is a difference, but maybe somebody knows if this is a OSGi thing or a Felix thing?
Additional Info: As to why ServiceB is not a service component...ServiceA actually has a service reference of 0..n for another service, call it ServiceD. Everytime a ServiceD interface is provided by a component, a ServiceB is registered using the same service object. Normally the same provider of ServiceD could provide ServiceB, but the idea is to make the overall interface for developers more simplistic so they don't have to provide multiple service interfaces (also, ServiceB has some properties that are set automatically that would have to be done manually and possibly could be done incorrectly).
The reason this appears to be happening is that ServiceAImpl is a delayed component that has already been loaded so ServiceA is in fact already resgistered before the component is activated. However, when another component comes along that needs ServiceA, this causes ServiceAImpl to be activated. Part of the activation process of ServiceAImpl is to register ServiceB which immediately causes ServiceCImpl to be activated. A change was made in FELIX-2368 to immediately activate a component by making most SCR operations synchronous.
A workaround is to make ServiceAImpl an immediate component which isn't desired as it shouldn't be activated if nothing needs the service. In this case, the activation method is completed when the component is loaded and by the time it is needed and bound to another component there is no problem.
I've tried to recreate this scenario with a small set of test bundles and the ProSyst OSGi FW.
However, if I register a service with DS, I am not able to register an other service from within the activate() method. If I just use DS to obtain services, I can register services as usual. So there is probably really a problem with DS/SCR...
Example:
public class ServiceAImpl implements ServiceA, ServiceB, ManagedService {
public void activate(ComponentContext _context) {
_context.getBundleContext().registerService(
ManagedService.class.getName(),
this,
null);
_context.getBundleContext().registerService(
ServiceB.class.getName(),
this,
null);
}
#Override
public void doA() {
System.out.println("Doing A Stuff");
}
#Override
public void doB() {
System.out.println("Doing B Stuff");
}
#Override
public void updated(Dictionary arg0) throws ConfigurationException {
}
}
This class will register 2 Services (ServiceB, ManagedService) with this bnd. file:
Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl
Bundle-Category: test
but only 1 service (ServiceA) with this sample:#
Private-Package: org.test.impl
Service-Component: org.test.impl.ServiceAImpl;provide:=org.test.ServiceA
Bundle-Category: test
So probably you should/have to try to register the services either via DS/SCR or the "classic way" via bundle context.

Resources