OSGi - How Can OSGi - I create a component that register a different implementation based on a parameter? Factory? - osgi

I've the following bundles:
- GreetingAPI (bundle which defines the greeting() method) (Service)
- GreetingImpl1 (bundle which implements greeting() method for English mode)
- GreetingImpl2 (bundle which implements greeting() method for Italian mode)
- GreetingConsumer (bundle which uses the greeting service)
How Can I create a component (I suppose it's a factory) that based on a given language parameter lets the consumer bundle to use a different implementation of the service.

You're thinking about this the wrong way around. The provider should not register a different service depending on something that the consumer does, because the provider shouldn't know anything about the consumer.
Instead, you can have multiple providers of the same service but annotate them with appropriate metadata. Then the consumer of the service can choose whether or not to filter on specific properties.
For example, when we register a service we can add properties as follows (note that I am using the OSGi Declarative Services annotations, see OSGi Compendium Release 5, section 112.8):
#Component(property = "locale=en_GB")
public class MyGreetingImpl1 implements Greeting {
public String greet() { return "How do you do"; }
}
#Component(property = "locale=en_US")
public class MyGreetingImpl2 implements Greeting {
public String greet() { return "Howdy"; }
}
#Component(property = "locale=fr_FR")
public class MyGreetingImpl3 implements Greeting {
public String greet() { return "Bonjour"; }
}
Now the consumer can choose whichever language it wants using a target filter. Note the use of a wildcard, as the consumer in this case only cares about the language but not the country code:
#Component
public class GreetingConsumer {
#Reference(target = "(language=en*)")
public void setGreeting(Greeting greeting) { ... }
}

One of the possible solutions is to have some kind of a language manager. So your consumer has a language manager and not directly the greetings service
The manager is notified with the registration / deregistration of every language implementation of your GreetingAPI.
Your language manager keeps trace of the diffrent implementations. Your manager provides the right implementation of the target language (using an enum for example)
Example
public class LanguageManagerImpl implements LanguageManager {
//LanguageEnum can be used to distinguish the different languages
private Map<LanguageEnum, GreetingAPI> greetings = new HashMap<LanguageEnum, GreetingAPI>();
public void registerLanguage(GreetingAPI greeting) {
LanguageEnum language = greeting.getLanguageEnum();
//add the greetings to the map
}
public void deregisterLanguage(GreetingAPI greeting){
//remove your greeting from the map
}
public GreetingAPI getGreetingForLanguage(LanguageEnum language) {
return greetings.get(language);
}
}
If you are using blueprint, then you need to add to the language manager blueprint a reference-list with a refence listener on GreetingAPI
Otherwise you use traditional listeners
Example
<bean id="languageManager"
class="your.language.managerimpl.LanguageManagerImpl">
</bean>
<service ref="languageManager" interface="your.language.manager.interface.LanguageManager" />
<reference-list interface="your.greeting.interface.GreetingAPI"
availability="optional">
<reference-listener ref="languageManager"
bind-method="registerLanguage" unbind-method="deregisterLanguage" />
</reference-list>

Related

Spring Cloud Stream messages based on polymorphic class structure

I'm using Spring Cloud Stream with RabbitBinder for pub/sub message processing.
Events emitted from services are sent via the broker. The event class structure is polymorphic, i.e. there is
abstract class OrderEvent {
abstract String type();
}
class OrderCreatedEvent extends OrderEvent {
#Override
String type() {
return "ORDER_CREATED";
}
...
}
abstract class OrderLineEvent extends OrderEvent {
...
}
class OrderLineCreatedEvent extends OrderLineEvent {
...
}
I am publishing events via StreamBridge,
#Override
public void publish(List<OrderEvent> events) {
events.forEach(e -> {
streamBridge.send("order-out-0", e);
});
}
and consuming via reactive consumer
#Bean
public Consumer<OrderEvent> order() {
return orderEvent -> {
System.out.println("got order event" + orderEvent);
};
}
But how to properly deserialize polymorphic types? content-type is set to application/json.
The code above does not work, it throws IllegalArgumentException, can not cast to OrderEvent.
If I restrict the code to publish OrderCreatedEvent (or any other leaf class) only, and adjust the consumer to OrderCreatedEvent the events are received successfully.
Thanks for your help!
Kind regards,
Andreas
There are a couple of disadvantages of using an Event class hierarchy. This is one. The other is that you share event types across distributed components which requires upgrading all dependent components whenever you add a new event type. I prefer using a single type with an event type field as a string.

How to replace a constructor injected object with mocked object in spock

I know that the question is very big but I just want to clear the situation i am into.
I am working on an application that consumes the JMS messages from the message broker.
We are using camel route on the consumer side. All the object required in route builder are injected through constructor injection using spring .
I want to mock the behavior of the actual processing, Once the consumer receives the message from the queue. All the classes gets loaded via the spring configuration.
Below are the three classes:
CustomRouteBuilder.java
public CustomRouteBuilder extends RouteBuilder{
private CustomRouteAdapter customAdapter;
public CustomRouteBuilder (CustomRouteAdapter customAdapter){
this.customAdapter = customAdapter
}
public void configure(RouteDefinition route){
route.bean(customAdapter);
}
}
CustomRouteAdapter.java
public class CustomRouteAdapter {
private Orchestrator orchestrator;
public CustomRouteAdapter (Orchestrator orchestrator){
this.orchestrator = orchestrator;
}
#Handler
public void process(String message){
orchestrator.generate(message) ;
}
}
Orchestrator.java
public class Orchestrator{
private Service service;
public Orchestrator(Service service){
this.service = service;
}
public void generateData(String message){
service.process(message);
}
}
As per our requirement we have to load this configuration file and then write the functional test using spock.
Below is my
CustomRouteBuilderTest.groovy file.
import org.springframework.test.util.ReflectionTestUtils
import spock.lang.Specification
#ContextConfiguration(classes=[CustomRouteBuilderTest.Config.class])
class CustomRouteBuilderTest extends Specification{
private static final String message = "Hello";
Orchestrator orchestrator;
#Autowired
CustomRouteAdapter customRouteAdapter;
def setup(){
orchestrator = Mock(Orchestrator)
ReflectionTestUtils.setField(customRouteAdapter,"orchestrator",orchestrator)
orchestrator.generate(message )
}
private String getMessageAsJson() {
//return json string;
}
private String getMessage() {
// return message;
}
private Map<String, Object> doMakeHeaders() {
//Create message headers
}
private void doSendMessage(){
Thread.sleep(5000)
Map<String,Object> messageHeader = doMakeHeaders()
byte [] message = getMessageAsJson().getBytes()
CamelContext context = new DefaultCamelContext()
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(jmsBrokerUrl)
context.addComponent("activeMQComponent",JmsComponent.jmsComponent(connectionFactory))
ProducerTemplate template = context.createProducerTemplate()
context.start();
template.sendBodyAndHeaders("queueName", message, messageHeader)
}
def "test message consumption"(){
given:
doSendMessage()
}
#Configuration
#Import([FunctionalTestCommonConfig.class,CustomRouteBuilderConfig.class])
#PropertySource(value="classpath:test.properties")
static class Config{
}
}
The problem that here is even though I inject the mocked object to the adapter using ReflectionTestUtils , I am not able to define its behavior correctly.
And when the message is received the orchestrator tries to process it.
My Requirement is that:
Adapter should be called from the camel route automatically which happens but
when the orechestrator.generate is called from the adapter then nothing should happen it should simply return.
But here nothing like that is going on.
Each time I send a message the consumer(RouteBuilder) receives it and calls the handler function which then calls the
orchestrator.generate(message)
function and the orchestrator starts processing and throws an exception from service level.
Any one can please help me on this.
I suppose your beans have been proxified by Spring, and this proxy use cglib (because you see CustomRouteBuilder$$EnhancerBySpringCGLIB$$ad2783ae).
If it's really the case, you didn't #Autowired in your test the real instance of your CustomRouteAdapter but a cglib proxy: Spring creates a new class, extending the realclass, and overriding all the methods of this class. The new method delegate to the real instance.
When you change the orchestrator field, you are in reality changing the orchestrator field of the proxy, which is not used by the real instance.
There are severals ways to achieve what you want to do:
add a setOrchestrator method in CustomRouteAdapter
create the mock in your spring configuration and let spring inject this mock instead of a real instance of Orchestrator
Inject the orchestrator in the real instance (ugly - I didn't recommend you that, it didn't help in the testability of your code!)
customRouteAdapter.targetSource.target.orchestrator = _themock_

Jaxb setting dynamic #XmlRootElement with Spring Web Services

I have a Spring application that consumes a SOAP web services. I have several classes that are quite simple and only differ in the #XmlRootElement. I'm wondering if there's a way to create a more generic class that I can set the root element on dymanically.
Here's a few of the classes with only the root element being different.
#XmlRootElement(name="safetydate")
public class SafetyDateRequest extends Carrier411RequestImpl {
}
#XmlRootElement(name="checkallsafety")
public class SafetyGetAllRequest extends Carrier411RequestImpl {
}
#XmlRootElement(name="checksafetyupdates")
public class SafetyGetUpdatesRequest extends Carrier411RequestImpl {
}
In another class, I'm processing these classes in the following fashion:
private void sendRequest(Carrier411Request request, Carrier411ResponseHandler responseHandler) throws FaultCodeException {
Carrier411Response response = (Carrier411Response) ws.marshalSendAndReceive(registry.get(request.getClass()), request);
checkResponseForFault(response);
responseHandler.handleResponse(request, response);
}
I know there's another version of marshalSendAndReceive that accepts a callback allowing you to modify the request before actually sending it, but I haven't figured out how to achieve what I'm trying to do.

Blueprint Osgi - Service created/destroyed Listener

Is possible add a Listener to know when a Bean Service with a particular Interface is created. And when the bean with the same interface is destroyed???
What is the best way to do it? reading the list of injecting services
<reference-list
id="javoraiConceptProcessList"
interface="com.api.MyTask"
availability="optional"
></reference-list>
What is the way to know when the list values is changed?
I am using Gemini Blueprint(Spring)
See the blueprint documentation at IBM.
This is how to do it (below). So you specify bind and unbind methods on a bean that will be called.
public class ReferenceListener {
public void bind(ServiceReference reference) {
...
}
public void bind(Serializable service) {
...
}
public void unbind(ServiceReference reference) {
...
}
}
<reference-list id=”serviceReferenceListTwo” interface=”java.io.Serializable”
availability=”optional”>
<reference-listener
bind-method=”bind” unbind-method=”unbind”>
<bean class=“org.apache.geronimo.osgi.ReferenceListener”/>
</reference-listener>
</reference-list>

Dependency Injection with Interface implemented by multiple classes

Update: Is there a way to achieve what I'm trying to do in an IoC framework other than Windsor? Windsor will handle the controllers fine but won't resolve anything else. I'm sure it's my fault but I'm following the tutorial verbatim and objects are not resolving with ctor injection, they are still null despite doing the registers and resolves. I've since scrapped my DI code and have manual injection for now because the project is time sensitive. Hoping to get DI worked out before deadline.
I have a solution that has multiple classes that all implement the same interface
As a simple example, the Interface
public interface IMyInterface {
string GetString();
int GetInt();
...
}
The concrete classes
public class MyClassOne : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
public class MyClassTwo : IMyInterface {
public string GetString() {
....
}
public int GetInt() {
....
}
}
Now these classes will be injected where needed into layers above them like:
public class HomeController {
private readonly IMyInterface myInterface;
public HomeController() {}
public HomeController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
public class OtherController {
private readonly IMyInterface myInterface;
public OtherController() {}
public OtherController(IMyInterface _myInterface) {
myInterface = _myInterface
}
...
}
Both controllers are getting injected with the same interface.
When it comes to resolving these interfaces with the proper concrete class in my IoC, how do I differentiate that HomeController needs an instance of MyClassOne and OtherController needs an instance of MyClassTwo?
How do I bind two different concrete classes to the same interface in the IoC? I don't want to create 2 different interfaces as that breaks the DRY rule and doesn't make sense anyway.
In Castle Windsor I would have 2 lines like this:
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>());
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>());
This won't work because I will only ever get a copy of MyClassTwo because it's the last one registered for the interface.
Like I said, I don't get how I can do it without creating specific interfaces for each concrete, doing that breaks not only DRY rules but basic OOP as well. How do I achieve this?
Update based on Mark Polsen's answer
Here is my current IoC, where would the .Resolve statements go? I don' see anything in the Windsor docs
public class Dependency : IDependency {
private readonly WindsorContainer container = new WindsorContainer();
private IDependency() {
}
public IDependency AddWeb() {
...
container.Register(Component.For<IListItemRepository>().ImplementedBy<ProgramTypeRepository>().Named("ProgramTypeList"));
container.Register(Component.For<IListItemRepository>().ImplementedBy<IndexTypeRepository>().Named("IndexTypeList"));
return this;
}
public static IDependency Start() {
return new IDependency();
}
}
I hope you can use service overrides.
Ex.
container.Register(
Component.For<IMyService>()
.ImplementedBy<MyServiceImpl>()
.Named("myservice.default"),
Component.For<IMyService>()
.ImplementedBy<OtherServiceImpl>()
.Named("myservice.alternative"),
Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("myService").Eq("myservice.alternative"))
);
public class ProductController
{
// Will get a OtherServiceImpl for myService.
// MyServiceImpl would be given without the service override.
public ProductController(IMyService myService)
{
}
}
You should be able to accomplish it with named component registration.
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassOne>().Named("One"));
container.Register(Component.For<IMyInterface>().ImplementedBy<MyClassTwo>().Named("Two"));
and then resolve them with
kernel.Resolve<IMyInterface>("One");
or
kernel.Resolve<IMyInterface>("Two");
See: To specify a name for the component
Typically DI containers follow Register, Resolve and Release patterns. During the register phase there are two steps. The first is to specify the mapping as you are doing. The second step is to specify the rules which govern which to inject where.
This problem is very common when we try to address Cross cutting concerns using decorators. In these situations, you have multiple classes(decorators) implementing a single interface.
Briefly, we need to implement IModelInterceptorsSelector which allows you to write imperative code that decides which Interceptor to apply to which types or members.
This is elaborately described in the book Dependency Injection in .Net book by Mark Seemann. Look for chapter 9 interception or search for the above interface.
I am not an expert at this, but was searching for the exact same problem and found the ans in the above book.
Hope this helps.
Regards
Dev1

Resources