Fix classloading issue with ByteBuddy and Vaadin in OSGi setup - java

I have issues with Vaadin flow in an OSGi setup and it seems to be related to the way some classes are loaded in the internals, when using Polymer Templates.
Here is my issue with some details https://github.com/vaadin/flow/issues/7377.
In TemplateModelProxyHandler:229ff the following code is used to load the Proxy Class
Class<?> proxyType = proxyBuilder
// Handle bean methods (and abstract methods for error handling)
.method(method -> isAccessor(method) || method.isAbstract())
.intercept(MethodDelegation.to(proxyHandler))
// Handle internal $stateNode methods
.defineField("$stateNode", StateNode.class)
.method(method -> "$stateNode".equals(method.getName()))
.intercept(FieldAccessor.ofField("$stateNode"))
// Handle internal $modelType methods
.defineField("$modelType", BeanModelType.class)
.method(method -> "$modelType".equals(method.getName()))
.intercept(FieldAccessor.ofField("$modelType"))
// Create the class
.name(proxyClassName).make()
.load(classLoader, ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
Here, two Class Loaders are important. First, the OSGi Bundle ClassLoader (classLoader) here. Second, the classloader of the Bundle which contains the class TemplateModelProxyHandler, e.g. TemplateModelProxyHandler.class.getClassLoader().
Is there a way to use both classloaders here?
Is there a simple method to achieve that with ByteBuddy?

Have a look into the MultipleParentClassLoader that is shipped with Byte Buddy. It allows you to specify multiple parents to a class loader and define a class within it.

Related

Can we prevent ourself of instanciating a Java class from an imported library

I have a library class, that is, a class that I load from a JAR, the source code is outside of my control. We instanciate it in our project in several places, and a property of the created objects should be always set. Unfortunately there is no central settings for the library, so I have created a subclass:
public class MyClass extends LibraryClass {
public MyClass() {
super();
super.setSomeProperty();
}
}
and then I replaced all instanciation of LibraryClass with MyClass. It works fine, but I want to prevent myself and my collegues to instanciate a LibraryClass in the future.
Is it possible to mark the LibraryClass (or its constructor) as deprecated by Maven or by Eclipse or somehow else? It would be a compile time solution.
Or is it possible to use some Spring/Aop magic to replace all instancieated LibraryClass with MyClass in runtime?
Since you mention to mark the constructor as deprecated (which would not actually forbid it) - if you are using something like sonar, you could create an own rule which marks the usage as error, exept for your subclass.
If you are using Spring in your application and all bean instantiation is done through Spring, on application startup check if a bean exist of type LibraryClass. Throw an exception if it exists. Similar solution can be implemented for any other framework used for bean instantiation.

Dependency injection using guice for a client sdk/library design pattern

I am building a client SDK for a web API and trying to apply dependency injection via guice. This Java client will be used by third parties as a way of accessing our API.
I want to be able to inject my external dependencies(The HTTP client used etc.) and give a way for developers to inject different versions of those dependencies if they wanted or if I ever wanted to change the implementation myself (a good case for dependency injection right?).
However in order to wire the dependencies, I have to make the user of my library create an injector etc. something like so:
Injector injector = Guice.createInjector(new MyAPIClientModule(url, username, password));
this.service = injector.getInstance(MyAPIService.class);
I don't want to push this up to the user of my library, but I still want to give users the ability to choose a different implementation or underlying HTTP library etc.
Am I missing the point of guice or DI here somehow? Is this standard practice when using guice?
Or should I wrap this in another class that does the injection and present the third party user with just a sample Java object?
I want to be able to inject my external dependencies(The http client
used etc.) and give a way for developers to inject different versions
of those dependencies if they wanted or if I ever wanted to change the
implementation myself(a good case for dependency injection right?).
It is highly arguable that this is a good case for DI. External dependencies like HTTP clients usually have concrete interface that is implemented by no one except exactly that dependency. Personally I can't imagine how your program is written given that swapping underlying HTTP client won't affect its architecture, that is, unless you provide your own facade for it, something like
public interface HttpClient {
HttpResponse send(HttpRequest request);
}
where HttpRequest and HttpResponse are also custom classes/interfaces. But providing such kind of extension point to the end user is rarely appropriate, especially if you don't have some reference implementation (this means that the user will have to create this facade for the dependency he/she wants). It is appropriate in rare cases, but chances are this is not your situation.
Different versions of the same dependency is also usually not the case for DI because swapping versions can be done at build/assembly time.
If you want to expose an ability for the user to provide their own implementations of some of your library "moving parts", then first you have to define strict interface for all these moving parts. In other words, provide a set of interfaces which your user must extend and which are injected in your classes.
Then you create your "binding space" consisting of your Guice modules, and in these modules you declare requirements on these interfaces:
public class SomeModule extends AbstractModule {
#Override
protected void configure() {
requireBinding(SomeUserAPI.class);
// Other bindings which probably use SomeUserAPI in implementations
}
}
By stating required bindings you ensure that no one will be able to mix in your module unless they provide some implementation of the given class. Of course, Guice will fail anyway if it can't find the binding, but when you require it explicitly you obtain more concrete error message, as well as clear interface of your modules.
And then you create special "entry point" to your library, sole responsibility of which is to create the injector and provide the user with instances of your classes. This class accepts Guice module from the user and integrates it into the injector.
public class Library {
private final Injector injector;
private Library(Module userModule) {
// SomeModule and AnotherModule are modules defined in the library
// and they are not the part of public interface of your library
this.injector = Guice.createInjector(userModule, new SomeModule(), new AnotherModule());
}
public static Library create(Module userModule) {
return new Library(userModule);
}
public MyAPIService myAPIService() {
return injector.getInstance(MyAPIService.class);
}
}
Then the user uses it like this:
Library library = Library.create(new AbstractModule() {
#Override
protected void configure() {
// recall requireBinding(SomeUserAPI.class) statement we wrote previously,
// here we are "implementing" it
bind(SomeUserAPI.class).to(SomeUserAPIImpl.class);
// other bindings for your exposed interfaces
}
});
MyAPIService service = library.myAPIService();
In this approach you allow the user to extend your library using Guice DI in a neat and controlled way.
You still have to expose Guice to your users, however (because the users have to implement Module interface). I don't think you can avoid that completely unless you do something bizarre like
Library.create(SomeUserAPIImpl.class, SomeUserAPI2Impl.class, ...)
that is, accept class objects representing implementations of extension points (and then bind them in some internal module). But I don't think that eliminating Guice from the library interface really worth it.
You can do module override which is not suggested for production. You can find more here Overriding Binding in Guice
You can use #ImplementedBy which create binding but explicitly binding of the interface will override that annotation binding. So, you will create your framework with #ImplementeBy if is it possible and 3th parties devs will override it with explicitly binding in their module. Find more https://code.google.com/p/google-guice/wiki/JustInTimeBindings
Anyway I'm not familiar with any of these approach. I would suggest to create an abstract ApiClient and let 3th party devs to implement the open points. Maybe you should introduce some annotations like #Client which had to implement ClientApi. Then your module will search the classpath for implementation of ClientApi with #Client annotation. Lets say the annotation would contain a value #Client('apache-http') and you will introduce a configuration property 'api-client' which would be set to default for default implementation or apache-http if you want to use something different. Well, you should consider it because integrity of your ApiClient can be shattered easily with wrong bindings :).

How to use eclipse 4 DI in classes that are not attached to the application model?

I have created a OSGI service with declarative services to inject an object that implements an interface. If I inject the object in a class that is attached to the application model (handler,part,....) it is working fine. If I inject it in a class that is not attached to the application model it is always returning null.
Is it possible to use DI in classes that are not attached to the application model? I looked in the vogella tutorials but somehow I don't find a solution.
I know of three ways of how Eclipse 4 can inject objects in your classes:
During start-up the Eclipse runtime looks for relevant annotations in the classes it instantiates.
Objects injected in 1. are tracked and will be re-injected if changed.
Manually triggering injection using the ContextInjectionFactory and IEclipseContext.
What you want may be possible with the third option. Here is a code example:
ManipulateModelhandler man = new ManipulateModelhandler();
//inject the context into an object
//IEclipseContext iEclipseContext was injected into this class
ContextInjectionFactory.inject(man,iEclipseContext);
man.execute();
The problem is, however; that the IEclipseContext already needs to be injected into a class that can access the object that needs injection. Depending on the number of necessary injections, it might be more useful to use delegation instead (testability would be one argument).
#Inject
public void setFoo(Foo foo) {
//Bar is not attached to the e4 Application Model
bar.setFoo(foo);
}
Therefore, a better solution is probably using the #Creatable annotation.
Simply annotate your class, and give it a no-argument constructor.
#Creatable
public class Foo {
public Foo () {}
}
Using #Inject on that type as in the method above, will let Eclipse instantiate and inject it.
The disadvantage is that you cannot control the object creation anymore, as you would with ContextInjectionFactory.inject(..).
I refactored out some part of e(fx)clipse in order to achieve that. Have a look at this. Sorry for the shameless plug...

Automatic factory registration

i'm just learning java, and i meet some problems.
Here we have simple factory pattern:
public class SomeFactory {
...
public static void registerProduct(String name, Class<? extends IProduct > f)
}
public SomeProduct implements IProduct {
static {
SomeFactory.register("some product", SomeProduct.class);
}
...
}
All products should register themselves at factory.
But before using this code, all Products classes should be loaded.
I can put Class.forName() somewhere, for example in main function.
But i want to avoid such sort of manual classes loading. I want just add new IProduct
implementations, without updating other parts(such as SomeFactory or Main methods, etc.).
But i wonder, is it possible to automatically load some classes(marked with annotation, for example)?
P.S I want to notice, that no other classes will be added at run-time, all IProduct implementations are known before compiling.
UPD#1
Thank for your answering!
But is it possible to make auto-generated property-file with IProduct instances?
I mean is it possible to make some build-time script(for maven for example) that generates property-file or loader code? Are there such solutions or frameworks?
UPD#2
I finished with using Reflections library that provides run-time information, by scanning classpath at startup.
This is possible, but not easily. It would need to scan all the classes in the classpath to see if they have an annotation or implement the IProduct interface. See How do you find all subclasses of a given class in Java? for answers to such a problem.
I would do keep it simple and just have a list of classes to load, either in the factory itself, or in an external file (properties file, for example).
Have each product register itself, using a static block like this:
class MyProduct1{
static{
SomeFactory.register(MyProduct1.getClass());
}
..
..
}
An external property file can keep track of all Products.
Your main method can parse this list of Products and do a Class.forName("..").
This way you wouldnt need to code any specific product, just the property file keeps changing. Ah! yes adding security registration would also be a plus point.
Note: I'm just proposing an idea, I'vent tried it myself :)

Guice Injection Across Modules for Sharing

I have three Modules in Guice:
ReflectionsModule, for providing Metadata (via Reflections)
PersistenceModule, for Data Access Objects and Others
WebModule, for Web Stuff
Simply put, both PersistenceModule and WebModule will fetch a object which is made from Reflections Module. I can not find a very friendly way to do this in guice.
I think PrivateModules will be a suitable way around, but I am not sure how to implement that. Any ideas?
Thank you.
Some additional details
I am using Reflections. It is basically a wrapper to load persistence metadata from a static resource. So basically supposed a parsed XML file into a JavaBean. Thats the concern of the ReflectionsModule.
From this metadata into the javabean, I need to setup the persistence (its a Google App Engine App, using Objectify) and load additional classes and bind them while reading some annotations within. I do not want to load the resource, so I'd like to refer to the resource loaded from the first example.
For now, the ReflectionsModule also binds the two subsequent modules, which I get (correctly) and apply them to the createChildInjector which came when building with just the first module. As os now, it works. I just would like to know which way would be the best one.
Simply speaking, PrivateModules expose only bindings that are explicitly exposed using #Exposed annotation of the .expose() method. Therefore, if PersistenceModule and WebModule are both PrivateModules, you can do the following:
public class WebModule extends PrivateModule {
#Override
public void configure() {
install(new ReflectionsModule());
// do stuff...
expose(SomeClassFromWebModule.class);
}
}
public class PersistenceModule extends PrivateModule {
#Override
public void configure() {
install(new ReflectionsModule());
// do stuff...
expose(SomeClassFromPersitenceModule.class);
}
}
In this way, the bindings from ReflectionsModule will not be exposed further than the two PrivateModules and will therefore not run into each other.
It is generally a good practice to only expose classes that can only be provided by one Module.
EDIT: better answer found: https://stackoverflow.com/a/5504903/105741 - basically use #Provides annotation to get method parameters in your module injected with your dependencies from other modules. Works much nicer. I.e. for the binding that requires the DependencyClass, I move that code into a method, expose it with the #Provides annotation, and add the DependencyClass as a method parameter.
#dyross - I don't think that's what he's asking.
It's not a good idea to create the ReflectionModule more than once, and PrivateModules don't have anything to do with the problem - that of sharing bindings to children modules (if I understand him correctly). I have the same need, and have used the technique of passing in the required object to the children modules ie.
Injector parentInjector = Guice.createInjector(new ParentModule());
DependencyClass dep = parentInjector.getInstance(DependencyClass);
injector = parentInjector.createChildInjector(new ChildModule(dep));
i.e.
Injector reflectionsModule = Guice.createInjector(new ReflectionsModule());
DependencyClass dep = parentInjector.getInstance(DependencyClass);
injector = parentInjector.createChildInjector(
new PersistenceModule(dep),
new WebModule(dep));
Not ideal, but serves the purpose.
It also just occured to me that you could pass in the injector to the child modules too, and getInstance() from directly inside the child modules.

Categories

Resources