Dynamic OSGi service replacement as development aid - java

We are using Apache Felix annotations to handle all the OSGi stuff in our application. I have a provider class that talks to a server. I have a consumer class that does stuff with data from the server. What I want is to create another provider instance (new class implementing interface) that is for debug purposes only that returns canned responses to requests by the consumer. Ideally I would like the consumer to be unaware of this handoff. It's provider service reference would simply be replaced.
The use case: When the developer is running on a machine without access to the actual server, he presses a button in our running app to switch from the real provider instance to our debug provider instance.
What is the recommended way to accomplish this?
Example code:
public interface IProvider{
public String getDataFromServer();
}
#Component
#Service(value=IProvider.class)
public class RealProvider implements IProvider{
#Override
public String getDataFromServer(){
...
}
}
#Component
#Service(value=IProvider.class)
public class DebugProvider implements IProvider{
#Override
public String getDataFromServer(){
return "Hello World";
}
}
#Component
public class Consumer{
private #Reference IProvider provider;
public void doSomething(){
provider.getDataFromServer();
}
}

If the two providers are in separate bundles, you can stop Bundle A and start Bundle B to switch between implementations of the service.
If the two providers are in the same bundle, you'd need to either drop down to the OSGI API and register/unregister the services manually, or create a proxy version of IProvider that has a debugMode flag and delegates to the specific implementation.

Related

REST API Autowire remote or local implementation of a service automatically

I have a REST API built on Spring Boot consisting of 2 seperate web services. I don't know if those two web services will be hosted on the same machine so I want to make remote and local implementation for all services. Example below:
Local service implementation:
public class LocalExampleService implements ExampleService{
public Item getItem(long id){
//Get item using implementation from another local project
}
}
Remote service implementation:
public class RemoteExampleService implements ExampleService{
#Value("${serviceURL}")
private String serviceURL;
public Item getItem(long id){
//Get item calling remote service
}
}
Controller:
public class MyController{
#Autowired
private ExampleService exampleService;
}
Web service has many services with local and remote implementation and I want to let Spring know which type of implementation it should choose for all services.
I've been thinking about putting url in properties file and during intialization the app would check whether properties contain url and then autowire service approprietly. But then I would have to write logic for every service autowiring.
What's the best option to autowire correct service implementation automatically?
You can use Spring profiles to control which version of implementation should be used via spring properties.
In spring properties add below entry
spring.profiles.active=NAME_OF_ACTIVE_PROFILE
Every service implementation needs profile annotation. That's how your services implementation should look like:
#Component
#Profile("local")
public class LocalExampleService implements ExampleService{}
#Component
#Profile("remote")
public class RemoteExampleService implements ExampleService{}
If your project needs to use local implementation of a service then in properties instead of NAME_OF_ACTIVE_PROFILE insert local otherwise remote.
For fully automatic auto-wiring you need to add method running at the startup that checks whether local implementation class exists and then set profile properly. To do this you need to modify code in spring boot main method:
public static void main(String[] args){
String profile = checkCurrentProfile(); //Method that decides which profile should be used
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, profile);
SpringApplication.run(MyApplication.class, args);
}
If you choose this approach then you don't need previous entry in properties file.
My attempt to implement something like this https://github.com/StanislavLapitsky/SpringSOAProxy
The idea is to check if a spring bean cannot be found locally then automatically create a Proxy which uses RestTemplate internally to call the same service remotely.
You need to define contract - services interfaces plus DTO and define URL resolver to specify which URL should be used for each service.

Getting a specific implementation from Felix

I've spent a long time on learning OSGi, but I still feel as though a crucial piece of the puzzle is missing.
This is my use case:
I am using JAX-RS (Grizzly) to create a REST API. I have an interface that has many various implementations. My solution should be able to add new implementations at any time.
Based on some form of input, I have to get a hold of one these specific instances. For example, lets say I register two interface implementations with Felix Interface A and Interface B. A user should be able to ask for Implementation B
By using the command line we get from running felix.jar(Apache Felix Gogo ) I have been able to install and start my own bundles. The problem I now face is how I from one of my controllers is supposed to retrieve any of these implementation.
Here is the code for the activator of one of my implementations.
public class MyClassActivator implements BundleActivator {
#Override
public void start(BundleContext context) throws Exception {
System.out.println("Starting ImplementationA");
Hashtable<String, String> props = new Hashtable<>();
props.put("Identifier", "ImplementationA");
context.registerService(MyInterface.class.getName(), new MyClassA(), props);
}
#Override
public void stop(BundleContext context) throws Exception {
System.out.println("Stopping ImplementationA");
}
private class ImplementationA implements MyInterface {
/*my implementation*/
}
}
From one of my JAX-RS classes, I want to, somehow, do this:
MyInterface myclassA = getBundle("ImplementationA");
The String ImplementationA is the same string I placed in the props map.
What I have tried so far is
BundleContext bc = FrameworkUtil.getBundle(MyInterface.class).getBundleContext();
This however just returns null, it doesn't seem to actually be "talking" to my felix instance.
So my questions are how do I get an interface from Felix? And is what I want to do even possible with OSGi?
Your question is confusing since you mix terms for services and bundles. A bundle is an installable unit which contains code. That code can register and consume services. Services are object which, typically, implement some interface which is shared between the bundle providing the service and the bundles consuming the services.
So the first order of business is to make sure the service interface's package is exported by some bundle and imported by all the bundles which plan to participate in providing and consuming the service. This is necessary to ensure type safety. That is, the consuming bundles can safely cast the service object to the expected type of the service.
Once that is done, as you observer, there can be multiple providers of a service. When a provider registers a service, they can specify some metadata about the service in the form of key/value properties. Your example shows this in the Identifier property. When a consumer looks up a service, a filter string can be specified which can specify information to be checked against a service' metadata to select from among multiple provided services.
public class MyServiceConsumer implements BundleActivator {
#Override
public void start(BundleContext context) throws Exception {
System.out.println("Looking for ImplementationA");
ServiceReference<MyInterface>[] refs =
context.getServiceReferences(MyInterface.class, "(Identifier=ImplementationA)");
MyInterface service = context.getService(refs[0]);
}
}
The above is terrible code; don't actually use it. It does not handle there being no service when the consumer bundle is activated (refs == null), nor does is it prepared for the service to go away. I strongly recommend you use OSGi Declarative Services when writing bundles. It makes service use and dealing with the dynamic super simple.
#Component
public class MyServiceConsumer {
MyInterface service;
#Reference(target="(Identifier=ImplementationA)")
private void bindService(MyInterface s) {
service = s;
}
#Activate
private activate() {
// do work
}
#Deactivate
private deactivate() {
// do work
}
}
This is a component which will only be instantiated when a matching service is present. It will be called at bindService to inject the service instance, the activate will be called to enable to component to do it work. If the injected service goes away, the component will be called at deactivate and then discarded. If later another matching service comes along, a new instance of the component will be activated.
See http://enroute.osgi.org/ for a tutorial on OSGi app dev.

Dynamically add custom functionality to a service / service mediation

I have developed a generic business service using spring framework. this service must be accessed from different channels i.e. web and mobile channels. each channel has its own business rules that must be added dynamically to generic service functionality. for example if web channel do some additional validation and then call generic service. if mobile channel call service A, then service B then generic service.
My question is what's the best design pattern/way to implement such service mediation without using an ESB?
I think you are looking for decorator pattern where you can attach the additional responsibility at run time.What you can do is
Public Class GenricValidationService extends ValidationService{
public void Validate(){
// do stuff here
}
}
Public Class WebChannelService extends ValidationService{
public WebChannelService (ValidationService validationService){
this.validationService= validationService;
}
ValidationService validationService;
public void Validate(){
genericValidationService.validate();
// extra validation
}
}
similarly
Public Class ServiceB extends ValidationService{
public ServiceB (ValidationService validationService){
this.validationService= validationService;
}
ValidationService validationService;
public void Validate(){
validationService.validate();
// extra validation
}
}
see
Decorator Pattern for IO
Decorate Your Java Code

Dependency injeection at runtime in Java

I have read through the dependency capabilities through Java CDI but could not figure out so far how to inject a class by runtime. Let me explain the scenario first.
Lets assume I have a JSF web app with a central Email service.
I am defining an interface
public interface EmailService {
public String sendEmail(Email email);
}
Then next I have a concrete implementation of the EmailService using Smtp:
public class SmtpEmailServiceImpl implements EmailService {
#Override
public String sendEmail(Email email) {
// concrete implementation using Smtp
}
}
Now in my web app I am having a JSF backing bean that should get the EmailService injected in order to sende the e-mail
public class JSFBackingBean {
// This is the EmailService to be injected
private EmailService emailService;
public String sendEmail(){
emailService.sendEmail(new Email());
}
}
Now lets assume the Smtp-Server is down for maintenance. In this scenario I would like to spool all the Emails in a Database and process them later when the Smtp server is up and running. In this case I would like to have a second implementation of the EmailService:
public class DatabaseEmailService implements EmailService {
#Override
public String sendEmail(Email email) {
// concrete implementation writing the email to a database
}
}
Now I understand from CDI that I can use Annotations to inject the proper service implementation but that would mean that I would have to re-build and deploy my classes in case I would like to change the appropriate service. Is there a better solution where I can use e.g. a configuration file in order to change the injection at runtime of the application?
Thanks for your answers in advance
Pred
In cases like this, you could write a custom Producer and Qualifier. Instead of injecting the EmailService, inject for example a "#Failsafe EmailService".
Then write a producer
#Produces
#Failsafe
private EmailService failsafeEmailService() {
// here you can check if the Mail Server is available and then decide
// to return the "real" Service or the DB-Queue.
}
Instead of creating/looking up the Services inside the method body, you could also let CDI inject both alternatives (directly or via Instance<>) and then decide which one to propagate.
#Produces
#Failsafe
private EmailService failsafeEmailService(MailServiceBean bean, DBQueue queue) {
return (check_if_mail_server_is_running) ? bean : queue
}
(of course both DBQueue and Bean have to implement EmailService).
Well, I doubt you want to make it so that every client to this email service is aware that the mail service needs to be switched out, even if you used annotations and instance selectors, e.g.:
#Inject
private Instance<EmailService> emailServiceInstance;
// few lines down
emailServiceInstance.select(new SmtpLiteral()).get();
Which is how you would do it in a CDI fashion. What I would recommend is that this logic belongs in your EmailService and itself injects a reference to some DB class that persist the message to the database until the SMTP server is back online.

How do I provide my own web service implementation instance?

I have a web service (JAX-RPC) that runs on application server (Websphere Application Server 7.0).
Normally the development process looks like this:
I write a class with web service implementation (e.g. MyService.java)
The IDE generates web service endpoint interface (e.g. MyService_SEI.java)
The IDE generates configuration XMLs
When the web service is deployed, MyService_SEI is the declared service interface and the application server instantiates a MyService instance by means of the public no-arg constructor.
But what if I want to do constructor injection (i.e. have MyService class without a no-arg constructor) or if I want to provide a dynamic proxy object which implements MyService_SEI and use that?
Is there a way I can take control of the instantiation procedure (like a filter or interceptor) to achieve this?
You can't do constructor injection as Injection always occur after the default constructor is called. If you try to use an injected reference inside the default constructor it will ALWAYS fail, there's no workaround for this as this is mandate by the specification.
So the first option you mentioned is discarded.
For the second option, using a filter or interceptor, you actually have an option. WebSphere WebServices are build using Axis2 implementation and Axis provide a way of implementing Handlers.
You can add handlers into the JAX-WS runtime environment to perform additional processing of request and response messages.
Here's a handler example, from Axis documentation:
package org.apache.samples.handlersample;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPMessageContext;
public class SampleProtocolHandler implements
javax.xml.ws.handler.soap.SOAPHandler<SOAPMessageContext> {
public void close(MessageContext messagecontext) {
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleFault(SOAPMessageContext messagecontext) {
return true;
}
public boolean handleMessage(SOAPMessageContext messagecontext) {
Boolean outbound = (Boolean) messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outbound) {
// Include your steps for the outbound flow.
}
return true;
}
}
And than you add a handler.xml file like this:
<?xml version="1.0" encoding="UTF-8"?>
<jws:handler-chain name="MyHandlerChain">
<jws:protocol-bindings>##SOAP11_HTTP ##ANOTHER_BINDING</jws:protocol-bindings>
<jws:port-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:MySampl*</jws:port-name-pattern>
<jws:service-name-pattern
xmlns:ns1="http://handlersample.samples.apache.org/">ns1:*</jws:service-name-pattern>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleLogicalHandler</jws:handler-class>
</jws:handler>
<jws:handler>
<jws:handler-class>org.apache.samples.handlersample.SampleProtocolHandler2</jws:handler-class>
</jws:handler>
</jws:handler-chain>
an easy method would be to make two classes. one your class with all the bells and whistles (constructor injection etc lets call it worker). and the actual service. the service would delegate what it needs to the worker class, who it can get by calling some factory method.
The factory can even look at some common db or other config to decide which run time instance (which class, what config, shared or common) so you have good separation and power
Just cause you are using one framework/ method of injection does not mean you cannot mix to make it more powerful

Categories