OSGi service not implementing interface - java

I am working on a project which uses OSGi which has below code
#Component(policy = ConfigurationPolicy.OPTIONAL, ds = true, immediate = true, metatype = false)
#Service(TestInterface.class)
public class TestInterface{
Here the code doesn't implement the interface in which the service is going to exposed. Also I have verified everywhere this is not referenced anywhere with #Reference.
Does it really need to make it as service instead of only component? In case if i want to use it in another Component i have to make it as a service by implementing interface.
Does OSGI really mandates the service to be exposed should implements interface?

An OSGi service can be registered under any type name not just interfaces. Interfaces are highly recommended since they nicely separate the implementation class from consumers of the service.

Related

Inject multiple remote EJBs in bean

In Java EE, if I have an interface:
#Remote
public interface MetaService {
ServiceData get();
}
And I have, in an ear 2 implementations:
#Stateless
public class Service1MetaService implements Calculator {
#Override
public ServiceData get() {...}
}
#Stateless
public class Service2MetaService implements Calculator {
#Override
public ServiceData get() {...}
}
I can create a bean, where:
#Stateless
public class View {
#Inject
private Instance<MetaService> metaServices;
...
}
And in View, the field metaServices will have the 2 implementations of MetaService.
I'd like similar functionality with remote beans.
So let's say, I have the above interface and implementations, but the packaging is different.
In base.jar I have the MetaService interface. This is packaged will all the subsequent applications mentioned below.
In a.ear I have the Service1MetaService implementation, while in b.ear I have the Service2MetaService implementation and in c.war I have the View class, which would like to use these implementations.
But as you would expect, the injected Instance is empty (not null tho). Is there a way to find the remote bean references in my injected Instance instance, even though these implementations are in separate applications?
One important thing is that in the View class I don't know and don't care about the number of these implementations, nor the names of the applications they are deployed in. So there is no way for me to use specific JNDI strings to get these references.
P.S.: Should I try and use technologies like JMS instead? So that I call the method add on a JMS proxy, which sends out the requests and waits for answers from all the applications that implement said interface?
P.S.: To clarify, the reason I need this is actually so that I can get data of running services on my application server(s). I updated the example interface and implementations, so that it's more clear. Also, it would be nice, if I could get these metadata synchronously, so JMS is not neccessarily prefered, however I can probably make it work.
I managed to convince myself to move away from remote EJBs. Well, it was also thanks to #chrylis-onstrike- as well, however, I'll opt for using JMS for this purpose.
The reason is that I can broadcast a request for the different services I need data from on-demand, enabling me to check for new services going online, or services failing.
Thanks to everyone who spent time trying to help me out.

[Spring-Cloud][Maven][Docker]Should Feign interfaces be put in FeignClients or EurekaClients?

EurekaServer: register/expose services
EurekaClients: provide services
FeignClients: consume services and provide APIs
I'm using Feign for service consumption. I wonder if feign interfaces (interfaces that annotated with #FeignClient) should be put in EurekaClients or FeignClients?
If Feign interfaces are put in EurekaClients.
GOOD: I only need to write only one copy of Feign interfaces, and implement it in the EurekaClients. For any FeignClients that need to use this service, import these interfaces from EurekaClients and just use it.
BAD: Module dependencies could be easily set, but it is hard to do mvn package or using docker for production. As the problem I stated HERE.
If Feign interfaces are put in FeignClients(almost every examples I can find on the internet do like this).
GOOD: Easy to build.
BAD: A lot of duplicated code. Because for every FeignClient I need to re-write #FeignClient annotated interfaces. If there are a lot of nested FeighClients and EurekaClients, it would be too difficult to maintain.
So any suggestions for a good practice of Where should I put Feigh interfaces ?
Here is the pattern we followed in our projects. Each service has two projects, e.g., :
Service A
model
service
All the controllers and other business related classes, e.g, DAOs, service, Repository classes are kept in the service project. While the models used by the controller and exposed to the outside world are kept in the model project. The controller also implements an interface which exposes the REST API. This interface is kept in the model project also.
public interface AuthorService {
#RequestMapping(method = RequestMethod.GET, produces = {
MediaType.APPLICATION_JSON_VALUE}, value = "/authors/{id}")
#ResponseBody
Author getAuthor(#PathVariable("id") Integer id);
}
The AuthorService interface and the model, Author are kept in the model project. The controller, AuthorController which implements the AuthorService is kept in the_service_ project.
Let's say ServiceB uses ServiceA, then the former import's the latter's model project. In ServiceA's service, we create a Feign interface, e.g.,
#FeignClient(name = "author", fallback =
AuthorServiceFallbackClient.class)
public interface AuthorServiceClient extends AuthorService {
}
This pattern helped us to reduce quite a bit of code duplication.

Get an OSGi service instance from blueprint programmatically

I have a java class where I need to have full control the time and place of instantiation - therefore I can't initialize it as blueprint bean.
In the same bundle as that class I have a bean that I export as an OSGi-service. I would need to get access to that very service instance from the previously explained non-blueprint class.
I can't just perform a service lookup as there are other services implementing the same interface aswell. Creating a second (internal) instance of the service class will not work either.
So, as a recap:
Before I used blueprint, I had the service implementation as classic singleton, enabling me to register the same instance as service in the activator class that I could later access from within the bundle. But with blueprint (as far as I know) making the service class a "classic" singleton is not possible because it would not be possible for blueprint to create the service instance
I can't perform a service lookup because there is more than one service registered implementing the service interface.
My current solution is to query all services implementing the interface and looping the list to find the one thats instance of the one class I want.
BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
ServiceReference<?>[] refs = ctx.getServiceReferences(ServiceInterface.class.getName(), null);
ServiceImpl provider = null;
for (ServiceReference ref : refs) {
if (ctx.getService(ref) instanceof ServiceImpl) {
provider = (ServiceImpl) ctx.getService(ref);
}
}
But I do not really like the idea of that approach.
Is there any better way to solve that? Maybe some way to request a service instance direct from the blueprint container? I found the interface BlueprintContainer with a method to get instances by the ID they got - but again the only way to get an instance of the BlueprintContainer I found is to inject the instance in the class - where I hit the initial problem of the class not possible to be a blueprint bean again.
Just set a property when exporting the service. So you can filter for it. This way you can distinguish your service impl from the others.
I also propose to use a ServiceTracker for your service. So you do not have to handle the lookup for every call to the service. If you do not use a ServiceTracker make sure to unget the service after use.

Binding services with Guice

I have written several services that I am glueing together using Guice. For example some abstract service A is described by these interfaces
Response
Request
Service
And the implementation is defined as
ResponseImpl
RequestImpl
ServiceImpl
Would it be better to bind all of the above implementations to their interface in the service's module, or just the Service class itself?
When you seperate contract (interface) and implementation (service-impl), you usually hand only the interfaces (api-jar) to the application-clients. So they will never see (and care about) any implementing beans.
Thus, in your client code, bind the interfaces:
#Provides
public Service lookup() {
return .... whatever you need to do to access the Service
}

Is it best to use type or properties to choose between OSGi Declarative Services?

I'm currently converting a piece of code from plain Java code to OSGi Declarative Services.
Original plain Java code
new AggregateServiceImpl(
new ChildServiceImpl1(),
new ChildServiceImpl2(),
new ChildServiceImpl3()
);
The classes are declared as so:
class AggregateServiceImpl implements Service
class ChildServiceImpl1 implements Service
class ChildServiceImpl2 implements Service
class ChildServiceImpl3 implements Service
So all classes implement Service, but the Aggregate implementation is capable of deferring to child Services when called upon.
AggregateServiceImpl itself does not know of the other implementations' existence. Its constructor is originally declared as:
public class AggregateServiceImpl(Service... children)
Clarification: the interface name 'Service' is intended generically and is not meant to represent an OSGi DS or Service concept.
Converting to OSGi
First I move each implementation into its own bundle. Then I declare my components (service implementations). I happen to be using bnd, so I use service annotations. For example:
#Component
class ChildServiceImpl1 implements Service
In the client class, we can look up the Service using the low level OSGi API or use DS in that bundle to create the object for us.
Problem
What's the best way of looking up a 'Service'? I want the AggregateServiceImpl but I might receive one of the ChildServiceImpls.
Is it best to use a separate service type or add a property to one of the components (e.g. "isRootService") to use as a filter when looking up ServiceReferences?
The best way is to use service registration properties
#Component
#Service
#Property(name = "service.id", value = "<some service unique ID")
class ChildServiceImpl1 implements Service{...}
When you look for some specific services you can use service filter:
bc.getServiceReferences(Service.class.getName(), "(service.id=<some value>)");
or if you like to use it in DS component as service reference:
#Reference(target = "(service.id=<some value>)", cardinality = ...)
private Service service;
If the AggregateServiceImpl is the only Service being used by other bundles, then it should be the only one you register.
From the code you have currently shown, we cannot tell if the AggregateServiceImpl class has dependencies on Service or the actual implementations.
If it has dependencies directly on other implementations, not the Service interface (as you have currently described it) the aggregate bundle should create the other implementation classes it requires directly and then register the AggregateServiceImpl as a Service.
If the other implementations need to be used elsewhere as well, then you should use properties (as you suggested) so consumers can distinguish between them. In this case, you still cannot use DS to construct your aggregate, since it doesn't have a dependencies on Service

Categories

Resources