iPOJO and connection between component ipojo - java

I have an example relating my problem. (files joint: https://drive.google.com/file/d/0B8ThLrV6-uchaFlTZTNGQ1FnT1E/view?usp=sharing )
I have 3 ipojo components (3 bunbles):
CallHello uses a DelayService service which implemented in both HelloDelay or HelloComponentReplace
HelloDelay and HelloComponentReplace use a HelloService service which implemented in HelloPrint.
At deployment, I deploy 5 bundles:
service.hello.service.jar
printer.hello.printer.jar
delay.hello.delay.jar
replace.hello.replace.jar
call.hello.call.jar
Result: DelayService uses always the implementation in HelloDelay.
Finally, I run Main.java to control manually selection between HelloDelay and HelloComponentReplace.
I implemented a function to start/stop or uninstall/install bundles in Main.java (and it works well). However, either HelloDelay or HelloComponentReplace is valid.
In the case both is active and valid, i read on the iPOJO website and I can use “comparator”. But I don’t understand how to apply ‘comparator’ to control selection between 2 components above. Is this to change priority? I know that we can change priority of bundle but I cannot know how to apply to my file (Main.java) and iPOJO.
Could we control connection (binding) between a requiring component and many providing components (same service or interface)?
I hope that you could help my difficulty in this time.
Best regards,

You can manipulate the service binding using interceptors: http://felix.apache.org/documentation/subprojects/apache-felix-ipojo/apache-felix-ipojo-userguide/ipojo-advanced-topics/service-binding-interceptors.html
With interceptors, you can hide services, and / or sort the service providers in order to enforce the provider you want to use.

Related

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.)

Akka constructor wiring via spring

I have read the links
Akka and spring configuration
http://doc.akka.io/docs/akka/2.4.1/java/untyped-actors.html
Spring is no longer available as a module in Akka 2.4.1 but can be created and used as an extension. I also understand that the concept of bean/actor creation being managed by DI-fwk like Spring can cause fundamental conflicts with the Akka Actor parent-child/supervision model. So I still don't understand how to wire these together.
I have a set of actor classes and I have written them to be generic enough for example: properties like "listener", "name", "messageQueueName" etc are configurable. The link above tells me that I provide convenience factory constructors and then create actor with the code snippet
system.actorOf(DemoActor.props(42), "demo");
It is this line that I do not like. What I want to write in my application.conf is something like
deployment {
/demo {
magicNumber : 42
}
}
and then in all my application I simply want to look up the actor (I am okay to use the actorSelection) method.
Am I doing something wrong?
I think you are on the wrong path there, you should have a look at these tutorials:
http://www.lightbend.com/activator/template/akka-java-spring
https://myshittycode.com/2015/08/26/akka-spring-integration/
and for passing arguments via constructors check my answer to this question:
Custom Spring Bean Parameters
The configuration file is used for akka specific parameters (like specifying the dispatcher, mailbox, etc.)

Configure a Service .. with XML ( instead of properties )

i have a ( bnd-annotated ) component that implements a simple api and exposes itself as a service
package com.mycompany.impl;
import com.mycompany.api.IFoo;
#Component(designateFactory=FooImpl.Configuration.class)
class FooImpl implements IFoo {
interface Configuration {
String foo();
// ..
}
Configuration configuration;
#Activate
public void activate(Map properties) {
configuration = Configurable.createConfigurable(Configuration.class, properties);
// ..
}
}
its configuration is loaded from a watched directory by Felix FileInstall and the service is instantiated by the Felix Configuration Service ( at least, i assume thats whats happening - i’m new to OSGi, please bear with me ) This, with the generated MetaType descriptor is working great.
However, as it stands, FooImpl requires structured configuration ( lists of lists, maps of lists..etc ) and i was wondering if there is an elegant ( * ) way to configure instances of the component through a similar workflow; that is to say, configuration discovery and instantiation/deployment remains centralised.
It seems to me that the Configuration Service spec manages maps - will i have to roll my own Configuration Service & FileInstall to be able to present components with xml/json/yaml backed structured configuration?
as opposed to, say, defining the location of an xml configuration file in properties ...confiception ? and doing my own parsing.
Yes and no...
The OSGi Configuration Admin service deals with abstract Configuration records, which are based on flat maps (actually java.util.Dictionary, but it's essentially the same thing). Config Admin does not know anything about the underlying physical storage; it always relies on somebody else to call the methods on the ConfigurationAdmin service, i.e. getConfiguration, createFactoryConfiguration etc.
The "somebody else" that calls Config Admin is usually called a "management agent". Felix FileInstall is a very simple example of a management agent that reads files in the Java properties format. Actually FileInstall is probably too simple and I don't consider it appropriate for production deployment — but that's a separate discussion.
It sounds like you want to write your own management agent that reads XML files and feeds them into Config Admin. This is really not a large or difficult task and you should not be afraid to take it on. Config Admin was designed under the assumption that applications would have very diverse requirements for configuration data storage, and that most applications would therefore have to write their own simple management agent, which is why it does not define its own storage format or location(s).
However, once the configuration data has been read by your management agent, it must be passed into Config Admin as a map/dictionary, which in turn will pass it to the components as a map. Therefore the components themselves do not receive highly structured data e.g. trees or nested maps. There is some flexibility though: configuration properties can contain lists of the based type; you can also use enum values etc.

OSGi DS & deactivating a component manually

Is it valid to deactivate a component in OSGi manually if I am using Declarative Services?
For example, let's say I have a component, with the implementation:
//component
class Overseer(){
List<ServiceReference> serviceRefs = ...//populate
private void doStuff(){
serviceRef = serviceRefs[i];
if(dontNeedThisAnymore){
serviceRefs.remove(serviceRef);
serviceRef.getBundle().stop();
}
}
The best way to do this is from another component in the same bundle, using the ComponentContext API.
You can write a component so that it takes ComponentContext as a param to its activate method. That interface has enableComponent and disableComponent methods that can be used to enable/disable other components in the same bundle.
I call this a "gatekeeper" component because it can be used to setup resources needed by the other components before enabling them. For example, you may have multiple components that need a database to be started up before they can do their job... the gatekeeper would take care of starting the database and then call enableComponent(null) to enable the other components. Similarly if the gatekeeper could detect that the database has shutdown and at that point disable the other components. In order for this to work, all components in the bundle except for the gatekeeper need to be set initially to enabled="false".

Intercept calls to HttpSession in Tomcat 6

What's the recommended approach to intercepting session.getAttribute() and session.setAttribute()? This is in a Spring based application so something AOP-based would be great. I'd like to avoid having to override core Tomcat classes if possible.
Update: I want to store the actual serialized attributes in a web service.
I am not familiar with AOP or Spring (or Tomcat). :) But I am familliar with Java
The way I do it is set up a filter, and replace the request variable with my own object
request = new MyRequest(request);
Then override getSession() and getSession(boolean) to return an instance of MySession
the javax.servlet.HttpServletRequest and javax.servlet.HttpSession classes are Java EE standard and not Tomcat specific.
You could implement your own session org.apache.catalina.Manager and swap it into Tomcat's configuration, although the interface looks rather lengthy - so perhaps look at extending ManagerBase or StandardManager first.
As an alternative, register a HttpSessionAttributeListener to be notified whenever a session attribute is added/removed/updated. This won't change the default storage mechanism - the session data will still be kept in-memory as well - but it would let you persist the data with an alternative mechanism as well.

Categories

Resources