How to use Picocontainer Web? - java

I'm trying to use Picocontainer Web (picocontainer-web-core-2.5.1.jar).
I have configured everything and I checked out that everything works just fine, until trying to retrieve anything from container... :p
I though I should use static method getRequestComponentForThread(Class type) from PicoServletContainerFilter class, which looks like this:
public static Object getRequestComponentForThread(Class type) {
MutablePicoContainer requestContainer = ServletFilter.currentRequestContainer.get();
MutablePicoContainer container = new DefaultPicoContainer(requestContainer);
container.addComponent(type);
return container.getComponent(type);
}
But as you can see, in that method, new instance of DefaultPicoContainer is created and type which I'm trying to retrieve is being registered.
if type is a Class - new instance is created and returned, instead of cached one from parent container...
if type is a Interface - runtime exception ("'ExampleInterface' is not instantiable") is being thrown, at 3rd line (addComponent).
And my question is: How to use this library? I was pretty sure that I understand it, but implementation of this one method blows my mind...

Actually you should not use getComponent unless there's a special case.
App/Session/Request containers are created for you when you add pico context listener to the web.xml.
Just configure components for each scope and picocontainer will inject stuff automatically and instantiate components when needed. Also use Startable lifecycle interface.

I figured out one acceptable solution - writing own version of org.picocontainer.web.PicoServletContainerFilter.ServletFilter - and adding one method:
public class MyComponentContainer extends PicoServletContainerFilter {
/*
code from original class PicoServletContainerFilter.ServletFilter
[...]
*/
public static <T> T getComponent(Class<T> clazz) {
return (T) currentRequestContainer.get().getComponent(clazz);
}
}
I'm not sure if it's the best to do, but it work's fine for me. However, if you know better solution I'd be grateful for information :)

Related

Apache Felix - How to guarantee injecting of dynamic references before an activate method

Here is snippet of intrested case:
We have some configuration class it can have multi instances. It suppose that we supply several configurations in one bundle. It's one scope.
#Service
#Component
public class SampleConfigurationImpl implements SampleConfiguration {
// declaration of some properties, init method and etc...
}
Also we have a service which uses these configurations:
#Service
#Component
public class SampleServiceImpl implements SampleService {
#Reference(
referenceInterface = SampleConfiguration.class,
cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
policy = ReferencePolicy.DYNAMIC)
private Map<String, SampleConfiguration> sampleConfigurations = new ConcurrentHashMap<>();
private void bindSampleConfigurations(SampleConfiguration sampleConfiguration) {
sampleConfigurations.put(sampleConfiguration.getName(), sampleConfiguration);
}
private void unbindSampleConfigurations(SampleConfiguration sampleConfiguration) {
sampleConfigurations.remove(sampleConfiguration.getName());
}
#Activate
private void init() {
System.out.println(sampleConfigurations.size());
}
}
So, can I get some guarantees that on invocation of init method all configurations are injected (at least of current bundle)? Maybe there is some alternative way to do this. I understand that another bundles can bring new configurations and it's unreal to get guarantees but it's intrested in case of only one bundle.
On practice it can be case when in init method there are only part of configurations. Especially if it's more difficalt case when you have several types of configuration or one service uses another one which has dynamic references and first service relies on fact that everything is injected.
The most unpleasant is that it can bind/unbind configurations both before and after init method.
Maybe there is some way to guarantee that it bind always after init method...
I'm interested in any information. It will be great to get answer on two questions (guarantees before or after). Probably someone has experience how to resolve such problem and can share with me.
Thanks.
No, not that I know of. What I usually do in that case (depending on your use case, it depends on if your activation code is ok with running multiple times) is to create a 'reallyActivate' method I call both from the regular activate and from the bindSampleConfigurations (+ setting an isActivated flag in activate). Then I can perform some logic every time a new SampleConfiguration gets bound, even if it's after the activation. Does that help for your case?

Design Patterns, override a method without need to re compile / relink

We are building a product that needs to run on production environments. We need to modify some of the functionality of a existing library. The existing library has class's and methods, we need to override 1 or more methods so that the caller uses our overriden methods instead of the original library.
OriginalLibrary
package com.original.library ;
public class OriginalLibrary {
public int getValue() {
return 1 ;
}
public int getAnotherValue() {
return 1 ;
}
}
Original Client
public class MyClient {
private OriginalLibraryClass originalLibraryObject ;
public MyClient () {
originalLibraryObject = new OriginalLibraryClass() ;
System.out.println(originalLibraryObject.getValue()) ;
System.out.println(originalLibraryObject.getAnotherValue()) ;
}
}
Output
1
2
Now, I need to change getValue() to return 3, instead of 1
Needed Output
3
2
package com.original.library.improved ;
public class OriginalLibrary extends com.original.library.OriginalLibrary {
public int getValue() {
return 3 ;
}
public int getAnotherValue() {
return super.getAnotherValue() ;
}
}
If I do the above, I need to tell my Original Client to reorder and use my new com.original.library.improved jar file before com.original.library.
I am almost convinced that this is the most non intrusive way to launch my improved services over and above the OriginalLibrary. I would have preferred a solution where I need to tell the customer to just add my jar file, no need to recompile, relink your client code.
Similar (not same) questions on a google search
here
here
java assist is excellent library for bytecode manipulation. I have modified code below as per your sample code given, You have to explore javaassist more for your actual requirenment
CtClass etype = ClassPool.getDefault().get("com.original.library.OriginalLibrary");
// get method from class
CtMethod cm = etype.getDeclaredMethod("getValue");
// change the method bosy
cm.setBody("return 3;");
etype.rebuildClassFile();
// give the path where classes is placed, In my eclipse it is bin
etype.writeFile("bin");
OriginalLibrary originalLibraryObject;
originalLibraryObject = new OriginalLibrary();
System.out.println(originalLibraryObject.getValue());
System.out.println(originalLibraryObject.getAnotherValue());
Now output of getValue is 3 because I changed body of that method.
A couple of questions -
How is the client getting an instance of your library's class?
If they are using new OriginalLibrary(), then you're pretty much stuck with creating a new subclass of OriginalLibrary and then asking your client to use your new OriginalLibraryImproved class. This is a common problem encountered in projects and is one reason why a library should not allow its clients to instantiate its classes directly using the new operator.
If instead, your client is instantiating OriginalLibrary using a factory method provided by the library (say, OriginalLibrary.getInstance()), you may want to check if there are any hooks into the factory that allow you to change the object being returned.
Do you have full control of the source code of the original library?
If yes, then you definitely should (and I cannot emphasize this strongly enough) provide factory methods for any class in the library that is instantiable. Doing this allows you to change the actual object being returned without modifying the client (as long as the returned object's class is a subclass of the return value from the factory method).
If not, then I suggest you do the following.
Create a subclass of OriginalLibrary (say, OriginalLibraryImproved).
Create a Factory class named OriginalLibraryFactory that has a static method named getInstance(). Write code to return an instance of OriginalLibraryImproved from this method.
Ask your client to replace all occurrences of new OriginalLibrary() with OriginalLibraryFactory.getInstance(). Note that this approach will only involve adding an extra import for the factory class. The client will still refer to the returned instance using the same OriginalLibrary reference as before.
The advantage of this approach is that it gives you complete flexibility to change the implementation details of OriginalLibraryImproved without affecting the client in anyway. You could also swap OriginalLibararyImproved with a newer version like OriginalLibraryImprovedVer2 and the client will be oblivious to the fact that it is using a new class. You'll just have to make sure that OriginalLibraryImprovedVer2 subclasses OriginalLibrary.
An even more flexible approach is to use the Wrapper or Decorator pattern to avoid the pitfalls of inheritance. You can understand more about the Decorator pattern here.
In a nutshell, try to avoid forcing your clients to use new and try to avoid inheritance unless you have very compelling reasons.

Injecting components into a POJO using OSGi

I'm new to OSGi and I'm interested in retrofitting some of my jars as OSGi bundles.
However I do not want to introduce additional dependencies to any osgi-specific libraries.
As such annotations are out of the question as are programmatic calls to bundle contexts and what not.
I have found a near match to my requirements in declarative services which allows me to expose my lower level bundles without impacting dependencies however at the higher level (where i actually need to consume the services) i'm still a bit stuck.
I understand that the component xml can be used to declare implementations of services (which i already use for my lower level jars) but also to inject service instances into a specific POJO.
Now my question: how do I get access to the osgi-managed POJO which has the services injected into it? Is it at all possible without introducing new dependencies or do I have to do it programmatically?
If the latter is the case can someone point me in the direction of some code to do it, in other words the component-equivalent of bundleContext.getServiceReference()?
UPDATE
To clarify, if you take the fifth part of this tutorial: http://www.vogella.com/articles/OSGiServices/article.html
He declares a component.xml file which uses reference binding to inject a service into the object QuoteConsumer.
Great, now how do I get an instance of QuoteConsumer that has the necessary services injected into it, I can't very well do "new QuoteConsumer()" right?
UPDATE2
Currently I am registering the instance created by osgi as a static variable which can be requested, I'm thinking this is not the best method especially because I can't set the constructor to private. (the latter would at least result in a true singleton)
Basically the Factory class has:
private void activate() {
instance = this;
}
UPDATE3
A full example of a factory:
public class Factory {
private static Factory instance;
public static Factory getInstance() {
if (instance == null)
instance = new Factory();
return instance;
}
private MyInterface implementation;
public void setMyInterface(MyInterface implementation) {
this.implementation = implementation;
}
public void unsetMyInterface(MyInterface implementation) {
implementation = null;
}
public MyInterface getMyInterface() {
if (implementation == null) {
ServiceLoader<MyInterface> serviceLoader = ServiceLoader.load(MyInterface.class);
Iterator<MyInterface> iterator = serviceLoader.iterator();
if (iterator.hasNext())
implementation = iterator.next();
else
implementation = new MyInterfaceStub();
}
return implementation;
}
#SuppressWarnings("unused")
private void activate() {
instance = this;
}
#SuppressWarnings("unused")
private void deactivate() {
instance = null;
}
}
Any client code can then do:
Factory.getInstance().getMyInterface();
and receive the OSGi loaded service, the SPI loaded one or a stub.
You can still manually set the service instance if necessary.
UPDATE4
To clarify further: this pattern is not meant for applications that are designed from the ground up to be run in an OSGi container but rather for low level libraries that have to run everywhere and even when on an OSGi container must not assume that all consumers are actually using OSGi.
You sound confused ... :-) A service is a replacement for static factories so your factory should not have to exist.
The whole idea of DS is that for each component:
wait until its dependencies are met
create an instance
bind the instance to its dependencies
call activate on the instance
register the instance as a service
So whenever you get a service managed by DS it already is injected (bound) with its dependencies. So as long as you stay with service dependencies you never need static factories ... The whole idea of service is that you do NOT have static factories and can only work with (injected) instances. One of the best parts of OSGi is that you rarely work with factories.
One remark about the requirement not to use annotations. The OSGi annotations are class time only, they do not create a runtime dependency. I strongly suggest to use them since they make services as lightweight as a class and are typesafe in contrast to XML.
One trick to use the annotations and not clutter your code is to create extend your implementation classes that you want to be an OSGi component and add the annotations on this class.
To access a service, you declare a reference to it from another component:
#Reference
public void setFoo(Foo foo) {
this.foo = foo;
}
You might find the Bndtools tutorial will help to clarify the concepts.
I'd say you are on the right track. You can use a static field if it is convenient.
The important thing is that you make the rest of your code deal with the QuoteConsumer appearing and disappearing. So, put in your activator the code to do what you need to do when the QuoteConsumer is available (register it in some field, call some initialization code, I don't know) and put in your deactivate the code you need to indicate that the QuoteConsumer is no longer available.

Getting the instance when Constructor#newInstance throws?

I'm working on a simple plugin system, where third party plugins implement a Plugin interface. A directory of JARs is scanned, and the implementing classes are instantiated with Constructor#newInstance.
The thing is, these plugins call back into register* methods of the plugin host. These registrations use the Plugin instance as a handle. My problem is how to clean up these registrations if the constructor decides to fail and throw halfway through.
InvocationTargetException doesn't seem to have anything on it to get the instance. Is there a way to get at the instance of an exception throwing constructor?
P.S.: It's typically strongly advised to users that the constructor not do anything, but in practice people are doing it any ways.
What you are in effect asking is whether there is a way to get hold of the (partial) instance when a constructor throws an exception.
The answer is No. But it is not because the instance is "dead". In fact the reference to the instance could still be reachable and usable by other parts of the application ... if it has been "published" before the constructor completed.
The real reason is that neither creating or throwing an exception records the instance associated with the method or constructor doing the creating / throwing.
You will need to solve this some other way. My suggestion is you make it a rule that these plugin classes must only register the instance as the last statement of the constructor; i.e. when no more initialization-related exceptions could be thrown.
Is it possible to do the registration through a holder object which is then used for actual plugin registration after the plugin class has been constructed successfully? I'm thinking of something like this:
public class MyPlugin extends BasePlugin {
public MyPlugin(PluginRegistry registry) {
super(registry);
// here be things which may cause an exception
// to be thrown, among other things
}
}
public interface PluginRegistry {
// method(s) for registration
}
public class PluginRegistryHolder implements PluginRegistry {
// implementations of the required method(s) for registration
// also a method for getting temporary registration data from within the class
}
// Actual usage in your code
public void registerPlugin(final String className) {
PluginRegistryHolder h = new PluginRegistryHolder();
Constructor c = /* acquire correct constructor, omitted for clarity */
try {
Object o = c.newInstance(new Object[] {h});
this.actualRegistry.register(o, h.getRegistrationData());
} catch (Throwable t) { /* die */
}
}
So basically handle the registration gracefully and never let the plugin class register directly but instead through a managed proxy.

Modify a method using Annotations

How can I change what a method is doing in Java ?
I mean, I am trying to use annotations to make the following code
#Anno1(Argument = "Option1")
public class TestClass
{
#Anno2
public void test()
{
}
}
Into
public class TestClass
{
private static StaticReference z;
public void test()
{
z.invokeToAll();
}
}
This is a very simplified example of what I am trying to do. Anno1 will have many possible combinations, but this is not my problem so far. My problem is how to add code to method test()
I am looking for a more generic solution if possible. Eg. A way to add every kind of code in the method (not just a way to .invokeToAll())
So far I am using import javax.annotation.processing.*; and I have the following code, but I don't know how to go on from there
private void processMethodAnnotations(RoundEnvironment env)
{
for (Element e : env.getElementsAnnotatedWith(Anno2.class))
{
//If it is a valid annotation over a method
if (e.getKind() == ElementKind.METHOD)
{
//What to do here :S
}else
{
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,"Not a method!", e);
}
}
}
I have found something about Java Reflection but I have not found any source to help me with what I am doing.
Obviously I extends AbstractProcessor in my code
I have found this tutorial (http://www.zdnetasia.com/writing-and-processing-custom-annotations-part-3-39362483.htm) But this concerns creating a new class, not just changing a method. and the javax.lang.model.elements do not provide any way of editing that element (which in my case represents a Method).
I hope my question is clear and inline with the rules. If not please comment and I will clarify. Thanks.
Annotation processing is the wrong way to go for you, from Wikipedia:
When Java source code is compiled,
annotations can be processed by
compiler plug-ins called annotation
processors. Processors can produce
informational messages or create
additional Java source files or
resources, which in turn may be
compiled and processed, but annotation
processors cannot modify the annotated
code itself.
People suggested to you the right way - AOP. Specifically, you can use AspectJ. "Quick result" way is (if you use Eclipse):
Install AJDT (AspectJ Development Tools)
Create an AspectJ project and add there your classes and annotations
Create Aspect:
public aspect Processor {
private StaticReference z;
pointcut generic()
// intercept execution of method named test, annotated with #Anno1
// from any class type, annotated with #Anno2
: execution(#Anno2 * (#Anno1 *).test())
// method takes no arguments
&& args ();
// here you have written what you want the method to actually do
void around () : generic() {
z.invokeToAll();
}
}
now you can execute a test and you will see that it works ;) AJDT compiles code for you automatically, so do not need any manual work to do, hope that's what you called "magic" ;)
UPDATE:
if your code in the test() method depends on the Anno1 annotation value, then inside aspect you can get class annotation for which it is executed this way:
void around () : generic() {
Annotation[] classAnnotations = thisJoinPoint.getThis().getClass().getAnnotations();
String ArgumentValue = null;
for ( Annotation annotation : classAnnotations ) {
if ( annotation instanceof Anno1 ) {
ArgumentValue = ((Anno1) annotation).Argument();
break;
}
}
if ( ArgumentValue != null && ArgumentValue.equals("Option1")) {
z.invokeToAll();
}
}
where thisJoinPoint is a special reference variable.
UPDATE2:
if you want to add System.out.println( this ) in your aspect, you need to write there System.out.println( thisJoinPoint.getThis() ), just tested and it works. thisJoinPoint.getThis() returns you "this" but not exactly; in fact this is Object variable and if you want to get any propery you need either to cast or to use reflection. And thisJoinPoint.getThis() does not provide access to private properties.
Well, now seems that your question is answered, but if I missed anything, or you get additional question/problems with this way - feel free to ask ;)
It's perfectly possible to do what you ask, although there is a caveat: relying on private compiler APIs. Sounds scary, but it isn't really (compiler implementations tend to be stable).
There's a paper that explains the procedure: The Hacker's Guide to Javac.
Notably, this is used by Project Lombok to provide automatic getter/setter generation (amongst other things). The following article explains how it does it, basically re-iterating what is said the aforementioned paper.
Well, you might see if the following boilerplate code will be useful:
public void magic(Object bean, String[] args) throws Exception {
for (Method method : bean.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(Anno2.class)) {
// Invoke the original method
method.invoke(bean, args);
// Invoke your 'z' method
StaticReference.invokeAll();
}
}
}
As an alternative your might employ aspect oriented programming, for instance you have the AspectJ project.
I'm not sure at all if it is even possible to change the source or byte code via annotations. From what your describing it looks as if aspect oriented programming could provide a solution to your problem.
Your annotations are pretty similiar to the pointcut concept (they mark a location where code needs to be inserted) and the inserted code is close the advice concept.
Another approach would be parsing the java source file into an abstract syntax tree, modify this AST and serialize to a java compiler input.
If your class extends a suitable interface, you could wrap it in a DynamicProxy, which delegates all calls to the original methods, except the call to test.

Categories