Adding a ServiceListener with Spring DM - java

I am wondering if it possible to do the equivalent of
public void start(BundleContext context)
{
String filter = "filter for my specific service";
context.addServiceListener(new MyServiceListener(), filter);
}
with Spring DM. I have found reference material for adding listeners for lifecycle management. But this relates to the lifecycle of the service being registered. What I need is to be made aware of the lifecycle of any service that is registered/unregistered of a specific service interface.
The bundle that needs to know this is not actually creating the service, but will be using it. Since there will multiple instances of this service that will change at runtime, I cannot simply create a service reference in my Spring configuration.

Spring DM includes support for referencing a collection of services. Unfortunately, as a new user, I can't post links, but this functionality is described in section 7.2.2 of the Spring DM 1.2 documentation. Spring DM automatically updates the contents of this collection at runtime as services are added to and removed from the service registry.
When you declare a reference upon a service, be it as a single reference, or a collection of services, you can also declare a listener bean that will be notified as services come and go. This is documented in section 7.2.3.
I'd recommend making use a List or Set of services, and using a listener bean so that you're notified of changes to the collection's contents.

Related

Jersey 2 - Request scoped binding vs Singleton binding

I'm learning Jersey and trying to build a rest api. But I'm having a hard time understanding the difference between various bindings - bind() , AbstractBinder(), bindFactory() and also the scopes - RequestScoped , Singleton and PerLookup. What are the differences between them and when to use which one?
e.g. Say I have some request specific data passed into the request header. I want to use this data multiple times (say in resource classes, DAOs etc) during the request processing. What I figured is that I'll use a request filter and extract the data using the ContainerRequestContext and store it to some class. But i'm not able to figure out how to bind this class so that I can access it later. Which binding to use in this case?
bind() and bindFactory() are methods in the AbstractBinder class that you use to bind your services in the registry. The AbstractBinder is what you register with Jersey so that it knows to configure all your bindings. You use bind() to bind the service itself. You use bindFactory() to bind the service using a Factory (or Supplier in 2.26+) to create the service.
RequestScoped means that the service is scoped to the request, meaning that it will be the same instance for the lifetime of the request. You would use this scope when the service is dependent on information tied to a request, like request headers.
Singleton scope means that there will only be one instance of the service for the lifetime of the application. You would use this scope when the service can safely be used at anytime without being tied to any request.
PerLookup means that a new instance of the service will be created every time it is looked up, either directly through the ServiceLocator (or InjectionManager in 2.26+) or via an #Inject (or other injection) annotation. Even though this is the default scope, the RequestScope and Singleton scope would be more appropriate for most of the use cases in the context of a Jersey application.
For your use case where you want to get information from the request context and use it in the service, you would use a RequestScoped service and use a bindFactory() with a Factory (or Supplier in 2.26+) and inject the request context into the Factory and use the context to create your service. You can see more explanation in How to inject an object into jersey request context?. If you are using Jersey 2.26+, you'll also want to read Jersey 2.26: register #Inject in ResourceConfig bindFactory cannot convert Factory to Supplier

Dropwizard registering two classes/clients

I have two instances of clients with different configs that I am creating (timeout, threadpool, etc...), and would like to leverage Dropwizard's metric on both of the clients.
final JerseyClientBuilder jerseyClientBuilder = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration());
final Client config1Client = jerseyClientBuilder.build("config1Client");
environment.jersey().register(config1Client);
final Client config2Client = jerseyClientBuilder.build("config2Client");
environment.jersey().register(config2Client);
However, I am getting
org.glassfish.jersey.internal.Errors: The following warnings have been detected:
HINT: Cannot create new registration for component type class org.glassfish.jersey.client.JerseyClient:
Existing previous registration found for the type.
And only one client's metric shows up.
How do I track both clients' metrics or is it not common to have 2 clients in a single dropwizard app?
Never mind, turned out I was an idiot (for trying to save some resource on the ClientBuilder).
2 Things that I did wrong with my original code:
1. You don't need to register Jersey clients, just the resource is enough... somehow I missed the resource part in my code and just straight up trying to register the client
2. You need to explicitly build each JerseyClientBuilder and then build your individually configured clients, then dropwizard will fetch by each JerseyClientBuilder's metrics
In the end, I just had to change my code to the following:
final Client config1Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config1Client");
final Client config2Client = new JerseyClientBuilder(environment)
.using(configuration.getJerseyClientConfiguration()).build("config2Client");
Doh.
environment.jersey().register() has a javadoc listing of Adds the given object as a Jersey singleton component meaning that the objects registered become part of the jersey dependency injection framework. Specifically this method is used to add resource classes to the jersey context, but any object with an annotation or type that Jersey looks for can be added this way. Additionally, since they are singletons you can only have one of them per any concrete type (which is why you are getting a "previous registration" error from Jersey).
I imagine that you want to have two Jersey clients to connect to two different external services via REST/HTTP. Since your service needs to talk to these others to do its work, you'll want to have the clients accessible wherever the "work" or business logic is being performed.
For example, this guide creates a resource class that requires a client to an external http service to do currency conversions. I'm not saying this is a great example (just a top google result for dropwizard external client example). In fact, I think this not a good to structure your application. I'd create several internal objects that hide from the resource class how the currency information is fetched, like a business object (BO) or data access object (DAO), etc.
For your case, you might want something like this (think of these as constructor calls). JC = jersey client, R = resource object, BO = business logic object
JC1()
JC2()
B1(JC1)
B2(JC2)
R1(B1)
R2(B2)
R3(B1, B2)
environment.jersey().register(R1)
environment.jersey().register(R2)
environment.jersey().register(R3)
The official Dropwizard docs are somewhat helpful. They at least explain how to create a jersey client; they don't explain how to structure your application.
If you're using the Jersey client builder from dropwizard, each of the clients that you create should be automatically registered to record metrics. Make sure you're using the client builder from the dropwizard-client artifact and package io.dropwizard.client. (Looks like you are because you have the using(config) method.)

How to programmatically register a service in the SCR using OSGi standard features?

I've spent some time experimenting with and studying the OSGi enRoute site. The Quick Start, and Base tutorials were really good. Now as a learning exercise, I'm creating my own example following the principles in those tutorials.
I've decided to reproduce the StageService from the blog post "Making JavaFX better with OSGi". Rather than using the org.apache.felix.dm and org.apache.felix.dm.annotation.api packages I want to use the OSGi standard SCR packages (org.osgi.service.component.*) along with the enRoute provider template.
So far everything has worked out nicely. But I'm stuck on one point. In the "Making JavaFX better with OSGi" tutorial the service is programmatically registered into the service registry using the org.apache.felix.dm.DependencyManager like this:
#Override
public void start(Stage primaryStage) throws Exception {
BundleContext bc = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
DependencyManager dm = new DependencyManager(bc);
dm.add(dm.createComponent()
.setInterface(StageService.class.getName(), null)
.setImplementation(new StageServiceImpl(primaryStage)));
}
My assumption is that in this example the DependencyManager is an Apache Felix specific feature rather than an OSGi standard. I would like to have my enRoute provider depend only on OSGi standard features.
So my question is simply:
How would one register a service in the service registry programmatically using only OSGi standard features? (I know from following the enRoute tutorials that if my component implements the exported service that SCR will automatically register my component in the service registry when my component is activated. The problem with this solution though is that when my component is activated it has to launch the JavaFX application in a different thread so as to not block the thread in use by the SCR until the JavaFX application terminates. Because of this, my component must programmatically register the service in the service registry. Otherwise it won't be guaranteed to be available upon registration.)
For reference, here is what I currently have:
private void registerService(Stage stage) {
DependencyManager dm = new DependencyManager(bundle().getBundleContext());
dm.add(
dm.createComponent()
.setInterface(StageService.class.getName(), null)
.setImplementation(new StageServiceImpl(primaryStage))
);
}
But instead I want to replace it with this:
private void registerService(Stage stage) {
// How to register service in service registry using only OSGi standard features? (not the apache felix dependency manager)
}
UPDATE 1
Following BJ Hargrave's recommendation I tried to register the service directly from the bundle context as follows:
FrameworkUtil
.getBundle(getClass())
.getBundleContext()
.registerService(StageService.class, new StageServiceImpl(primaryStage), null);
After doing this and trying to resolve the enRoute application project the following error occurs:
org.osgi.service.resolver.ResolutionException: Unable to resolve
<> version=null: missing requirement
com.github.axiopisty.osgi.javafx.launcher.application
-> Unable to resolve com.github.axiopisty.osgi.javafx.launcher.application
version=1.0.0.201608172037: missing requirement
objectClass=com.github.axiopisty.osgi.javafx.launcher.api.StageService]
I have uploaded the project to github so you can reproduce the error.
Update 2
The build tab in the bnd.bnd file in the provider module shows the following warning:
The servicefactory:=true directive is set but no service is provided, ignoring it
Might this have something to do with the application module not being able to be resolved?
In rare cases it is necessary to register a 'service by hand' using the standard OSGi API. Try very hard to avoid this case because if you start to register (and maybe depend) on services that you manually register you get a lot of responsibility that is normally hidden from view. For example, you have to ensure that the services you register are also unregistered.
One of the rare cases where this is necessary is when you have to wait for a condition before you can register your service. For example, you need to poll a piece of hardware before you register a service for the device. You will need to control the CPU but at that moment you cannot yet register a service. In that case you create an immediate component and register the service manually.
To register a service manually you require a BundleContext object. You can get that objectvia the activate method, just declare a Bundle Context in its arguments and it is automatically injected:
#Activate
void activate( BundleContext context) {
this.context = context;
}
You can now register a service with the bundle context:
void register(MyService service) {
Hashtable<String,Object> properties = new Hashtable<>();
properties.put("foo", "bar");
this.registration = context.registerService( MyService.class, service, properties );
}
However, you now have the responsibility to unregister this service in your deactivate. If you do not clean up this service then your component might be deactivated while your service still floats around. Your service is unmanaged. (Although when the bundle is stopped it will be cleaned up.)
#Deactivate
void deactivate() {
if ( this.registration != null)
this.registration.unregister();
}
If you create the service is a call back or background thread then you obviously have to handle the concurrency issues. You must ensure that there is no race condition that you register a service while the deactivate method has finished.
This text has also been added to the DS Page of OSGi enRoute
Reading the OSGi spec would help you understand the service API.
But this should do it:
ServiceRegistration<StageService> reg = bc.registerService(StageService.class, new StageServiceImpl(primaryStage), null);

What are Interceptors in Java EE?

I'm trying to clear my concept about Interceptors in Java EE. I have read Java EE specification but I'm little confused about it. Please provide me some useful link or tutorial which could clear my concept. How, When, Why do we use interceptors?
Interceptors are used to implement cross-cutting concerns, such as logging, auditing, and security, from the business logic.
In Java EE 5, Interceptors were allowed only on EJBs. In Java EE 6, Interceptors became a new specification of its own, abstracted at a higher level so that it can be more generically applied to a broader set of specifications in the platform.
They intercept invocations and life-cycle events on an associated target class. Basically, an interceptor is a class whose methods are invoked when business methods on a target class are invoked, life-cycle events such as methods that create/destroy the bean occur, or an EJB timeout method occurs. The CDI specification defines a type-safe mechanism for associating interceptors to beans using interceptor bindings.
Look for a working code sample at:
https://github.com/arun-gupta/javaee7-samples/tree/master/cdi/interceptors
Java EE 7 also introduced a new #Transactional annotation in Java Transaction API. This allows you to have container-managed transactions outside an EJB. This annotation is defined as an interceptor binding and implemented by the Java EE runtime. A working sample of #Transactional is at:
https://github.com/arun-gupta/javaee7-samples/tree/master/jta/transaction-scope
Interceptors are used to add AOP capability to managed beans.
We can attach Interceptor to our class using #Interceptor annotation.
Whenever a method in our class is called, the attached Interceptor will intercept that method invocation and execute its interceptor method.
This can be achieved using #AroundInvoke annotation ( see example below ).
We can intercept life cycle events of a class ( object creation,destroy etc) using #AroundConstruct annotation.
Main difference between Interceptor and Servlet Filters is We can use Interceptor outside WebContext, but Filters are specific to Web applications.
Common uses of interceptors are logging, auditing, and profiling.
For more detailed introduction, you can read this article.
https://abhirockzz.wordpress.com/2015/01/03/java-ee-interceptors/
I like this definition: Interceptors are components that intercept calls to EJB methods. They can be used for auditing and logging as and when EJBs are accessed.
In another situation, they can be used in a situation where we need to check whether a client has the authority or clearance to execute a transaction on a particular object in the database. Well, this is where Interceptors come in handy; they can check whether the client/user has that authority by checking whether he/she can invoke that method on that database object or EJB.
However, I would still have a look at the following article and the following tutorial to get an idea of how they are used in a Java EE setting/environment.
You can use Interceptor for the places where you want to perform some tasks before sending a request to the Controller class and before sending a request to a responce.
Ex:- Think you want to validate the auth token before sending a request to the Controller class in this case, you can use Intercepters.
Sample code:
#Component
public class AuthInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse
response, Object handler) throws Exception {
//Here you can write code to validate the auth token.
}
}

OSGi services architecture: creation of service at request of consumer

I am developing an application in Eclipse RCP. I need help with a design decision concerning the design of a service.
I have some bundles which are used to provide an REngine object to other modules. The REngine is an interface to a calculation engine, which can be implemented in multiple ways. The bundles provide instances of REngine by connecting to a remote server or starting a local calculation thread. Some bundles require configuration by the GUI (but also need to be available on a headless platform). A client Bundle may request multiple REngine objects for parallel calculations.
I currently register these modules to provide an REngine service. The service is created by a ServiceFactory, which either launches a local calculation instance or a remote (server) instance. The client is responsible for trying out all Service registrations of the REngine class and selecting the right one.
The code to do this can be summarised as follows:
class API.REngine { ... }
class REngineProvider.Activator {
public void start(BundleContext ctx) {
ctx.registerService(REngine.class.getName(), new REngineFactory(), null);
}
}
class REngineProvider.REngineFactory implements ServiceFactory {
public Object getService(Bundle bundle, ServiceReference reference) {
return new MyREngineImplementation();
}
public void ungetService(REngine service) {
service.releaseAssociatedResources();
}
}
class RConsumer.Class {
REngine getREngine() {
ServiceReference[] references = bundleContext.getAllServiceReferences(REngine.class.getName(), null);
for(ServiceReference ref: references) {
try {
return bundleContext.getService(ref);
} catch (Exception e) {} // too bad, try the next one
}
}
}
I would like to keep this model. It is nice that the OSGi service spec matches my business requirement that REngine objects are living objects which should be released when they are not needed anymore.
However, a registered service can only provide one service instance per bundle. The second time the service is requested, a cached instance is returned (instead of creating a new one). This does not match my requirement; a bundle should be able to get multiple REngine objects from the same provider.
I have already looked at other OSGi framework classes, but nothing seems to help. The alternative is the whiteboard model, but it seems strange to register an REngineRequestService that is used by the REngineProvider bundle to give out a live REngine.
How do I implement this in OSGi? As a reminder, here is my list of requirements:
Easy enabling and disabling of REngineProvider bundles. Client code will just use another provider instead.
Configuration of REngineProvider bundles.
Multiple REngine instances per client bundle.
Explicit release of REngine instances
REngine creation can fail. The client module should be able to know the reason why.
Just to add the solution I have chosen as future reference. It seems the OSGi Services platform is not made for "requesting a service". It is the provider bundle that creates a service, and the client bundle that can find and use the services. It is not possible to provide an automatic "Factory" for services per user request.
The solution chosen involves the OSGi whiteboard model. On first sight, this may seem very difficult to manage, but Blueprint can help a lot!
Provider blueprint.xml file:
<reference-list interface="org.application.REngineRequest"
availability="optional">
<reference-listener
bind-method="bind" unbind-method="unbind">
<bean class="org.provider.REngineProvider"/>
</reference-listener>
The class REngineRequest is a shared API class allowing the provider to input his REngine object, or set an Exception explaining why the creation did not work.
For the client, using an REngine is now as easy as doing:
REngineRequest req = new REngineRequest();
ServiceRegistration reg = bundleContext.registerService(req, REngineRequest.class.getName(), engineCreationProperties);
req.getEngine().doSomeStuff();
reg.unregister();
We make the assumption that the provider will never stop while the client is using the REngine. If it does, the REngine becomes invalid.
ComponentFactory from the Declarative Services is what you need. Most of the time you should rather use DS instead of manually registering and looking up the services.
The provider side should register REngine factory service (you don't have to implement the factory itself, DS will do that for you). The consmer should declare one-to-many dependency to the REngine service. At runtime, all available factories will be injected and consumer can go through them to create actual REngine instances.
Two years ago I tried to create Genuine Service Factories what later became Parameterized Services. However, after analysis it turned out that nothing was needed, just register the factory as the service.
However.
I do not know enough about your service but it sounds very much that you could significantly simplify things by removing control from the client bundle, the client bundle should just use whatever REngine service is available in the service registry, maybe with a property signalling its use type if there are multiple bundles that need REngines and they should not share the same REngine (which should rarely be the case).
If that model is possible, it usually significantly simplifies. I generally then use DS with Configuration Admin configurations that drive the instances (one of the most useful aspects of DS, see http://www.aqute.biz/Bnd/Components). With the metatype integration, you even get a user interface to edit your configuration properties.
One solution would be to register the REngineFactory as the service rather than the REngine implementation itself and return the factory from the getService method. That way the clients can look up the factory and, on successfully finding one, use it to get a new REngine implementation.

Categories

Resources