WeldContainer and SeContainer - java

What is the difference between using:
WeldContainer se = new Weld().initialize();
or
SeContainer se = SeContainerInitializer.newInstance().initialize();
I just want to use #Injection and #Produce annotations, but I have not found the difference between these two ways of initializing an object instance.

Context and Dependency Injection (CDI) is a specification. That means it defines an API only and does not provide an implementation. That's why you have to include an implementation such as Weld in order to actually use the API. The WeldContainer class is vendor-specific whereas the SeContainer interface is part of the specification. The former implements the latter.
The SeContainerInitializer class, which is part of the API, will delegate to the implementation included with the application. So if you use Weld as the implementation then ultimately using SeContainerInitializer and SeContainer is the same as using Weld and WeldContainer "under the hood".
From a purist's perspective it's best to rely only on the specification's interface and never directly depend on the implementation. That way you can swap vendors if and when you need to since you're using functionality common to all implementations. However, often times an implementation provides more functionality than what's required by the specification. In order to use that functionality you have to directly depend on the implementation.
In other words, whether you use Weld / WeldContainer or SeContainerInitialializer / SeContainer depends on the (current and future) requirements of your application. When in doubt, program to the interface.
Note this separation between the API and implementation is not unique to CDI. Pretty much the entire Java EE—or as it's now known, Jakarta EE—API works this way. An example would be the Java Persistence API (JPA) and Hibernate or EclipseLink (two implementations). For an example within Java SE there's the Java Database Connectivity (JDBC) API and the various implementations (i.e. drivers).

Using SeContainerInitializer it will load an instance by ServiceLoader.load(...) and initialize it.
public static SeContainerInitializer newInstance() {
return findSeContainerInitializer();
}
private static SeContainerInitializer findSeContainerInitializer() {
SeContainerInitializer result;
Iterator<SeContainerInitializer> iterator = ServiceLoader.load(SeContainerInitializer.class, SeContainerInitializer.class.getClassLoader()).iterator();
if (!iterator.hasNext()) {
throw new IllegalStateException("No valid CDI implementation found");
}
try {
result = iterator.next();
} catch (ServiceConfigurationError e) {
throw new IllegalStateException("Error while instantiating SeContainerInitializer", e);
}
if (iterator.hasNext())
throw new IllegalStateException("Two or more CDI implementations found, only one is supported");
return result;
}
Weld is one implementation of SeContainerInitializer so if it exists on the classpath SeContainerInitializer.newInstance() method will create a new Weld instance and call initialize() method on this object.
Some hints which is a good choice
SeContainerInitializer.newInstance() is a factory method. If you want to create a vendor-independent application it would be good. But Weld is the reference implementation of CDI specification. Honestly I don't think choosing another implementation is necessary.
new Weld().initialize() will create a WeldContainer (which is an implementation of SeContainer). Using this method you will get a vendor-lock but you can use a lot of useful extra features (e.g. add alternatives or interceptors programmatically).
My opinion is: In this case vendor-lock doesn't matter anithing.
Conclusion
If you're planning to change CDI implementation anything else than Weld use independent SeContainerInitializer.newInstance() otherwise just create a Weld instance.
If I were you I would use new Weld() way.

Related

CDI 1.X asynchronous events

I was looking at this project https://github.com/MSzturc/cdi-async-events-extension/,
which provides async events in CDI 1.X (built-in async came from 2.0).
Now I'm questioning this piece of code inside the custom Extension:
public <X> void processAnnotatedType(#Observes ProcessAnnotatedType<X> event, final BeanManager beanManager) {
final AnnotatedType<X> type = event.getAnnotatedType();
for (AnnotatedMethod<?> method : type.getMethods()) {
for (final AnnotatedParameter<?> param : method.getParameters()) {
if (param.isAnnotationPresent(Observes.class) && param.isAnnotationPresent(Async.class)) {
asyncObservers.add(ObserverMethodHolder.create(this.pool, beanManager, type, method, param));
}
}
}
}
public void afterBeanDiscovery(#Observes AfterBeanDiscovery event) {
for (ObserverMethod<?> om : this.asyncObservers) {
event.addObserverMethod(om);
}
}
Basically, while each Bean is being registered, it is looking at each method to see if a parameter has the #Async annotation.
Then, after the discovery step, it is registering the #Observes #Async methods.
Looking inside the addObserverMethod() method, provided by JBoss Weld 2, I see:
additionalObservers.add(observerMethod);
My question then is, wouldn't those methods be called twice? I mean, they may be registered twice, first by the container itself, then by calling the addObserverMethod() method.
I am not familiar with project, but from the first look it seems pretty outdated and not maintained.
As for the extension - it basically adds the "same" observer method (OM) again, with it's own OM implementation. So I would say the behaviour depends on CDI implementation as the spec does not guarantee what happens when you register "the same" OM again - is it replaced or is it just added like you say?
And by "the same" I mean the exact same underlying Java method although wrapped in a fancier coat.
Ultimately, you can easily try it and see for yourself, but I would advise against using that project as any problems you bump into are unlikely to be resolved on the project side.

Modifying annotation value in superclass and dynamically instantiating child classes with new value

We are using Spring Cloud Stream as the underlying implementation for event messaging in our microservice-based architecture. We wanted to go a step further and provide an abstraction layer between our services and the Spring Cloud Stream library to allow for dynamic channel subscriptions without too much boilerplate configuration code in the services themselves.
The original idea was as follows:
The messaging-library provides a BaseHandler abstract class which all individual services must implement. All handlers of a specific service would like to the same input channel, though only the one corresponding to the type of the event to handle would be called. This looks as follows:
public abstract class BaseEventHandler<T extends Event> {
#StreamListener
public abstract void handle(T event);
}
Each service offers its own events package, which contains N EventHandlers. There are plain POJOs which must be instantiated programmatically. This would look as follows:
public class ServiceEventHandler extends BaseEventHandler<ImportantServiceEvent> {
#Override
public void handle(ImportantServiceEvent event) {
// todo stuff
}
}
Note that these are simple classes and not Spring beans at this point, with ImportantServiceEvent implementing Event.
Our messaging-library is scanned on start-up as early as possible, and performs handler initialization. To do this, the following steps are done:
We scan all available packages in the classpath which provide some sort of event handling and retrieve all subclasses of BaseEventHandler.
We retrieve the #StreamListener annotation in the hierarchy of the subclass, and change its value to the corresponding input channel for this service.
Since our handlers might need to speak to some other application components (repositories etc.), we use DefaultListableBeanFactory to instantiate our handlers as singleton, as follows:
val bean = beanFactory.createBean(eventHandlerClass, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
beanFactory.registerSingleton(eventHandlerClass.getSimpleName(), bean);
After this, we ran into several issues.
The Spring Cloud Stream #StreamListener annotation cannot be inherited as it is a method annotation. Despite this, some mechanism seems to be able to find it on the parent (as the StreamListenerAnnotationBeanPostProcessor is registered) and attempts to perform post-processing upon the ServiceEventHandler being initialized. Our assumption is that the Spring Cloud Stream uses something like AnnotationElementUtils.findAllMergedAnnotations().
As a result of this, we thought that we might be able to alter the annotation value of the base class prior to each instantiation of a child class. Due to this, we thought that although our BaseEventHandler would simply get a new value which would then stay constant at the end of this initialization phase, the child classes would be instantiated with the correct channel name at the time of instantiation, since we do not expect to rebind. However, this is not the case and the value of the #StreamListener annotation that is used is always the one on the base.
The question is then: is what we want possible with Spring Cloud Stream? Or is it rather a plain Java problem that we have here (does not seem to be the case)? Did the Spring Cloud Stream team foresee a use case like this, and are we simply doing it completely wrong?
This question was also posted on on the Spring Cloud Stream tracker in case it might help garner a bit more attention.
Since the same people monitor SO and GitHub issues, it's rather pointless to post in both places. Stack Overflow is preferred for questions.
You should be able to subclass the BPP; it specifically has this extension point:
/**
* Extension point, allowing subclasses to customize the {#link StreamListener}
* annotation detected by the postprocessor.
*
* #param originalAnnotation the original annotation
* #param annotatedMethod the method on which the annotation has been found
* #return the postprocessed {#link StreamListener} annotation
*/
protected StreamListener postProcessAnnotation(StreamListener originalAnnotation, Method annotatedMethod) {
return originalAnnotation;
}
Then override the bean definition with yours
#Bean(name = STREAM_LISTENER_ANNOTATION_BEAN_POST_PROCESSOR_NAME)
public static StreamListenerAnnotationBeanPostProcessor streamListenerAnnotationBeanPostProcessor() {
return new StreamListenerAnnotationBeanPostProcessor();
}

Is it a good idea to replace java.net.URL URLStreamHandlerFactory using reflection?

In Java we can register a custom protocol handler in at least two ways:
by setting system property 'java.protocol.handler.pkgs'
using URL.setURLStreamHandlerFactory
For more details please check http://accu.org/index.php/journals/1434
I can not go with the first option, as i would have to add a lot of jar files to the server (tomcat) classpath, to make the handler implementaion visible for bootstrap classloader. Moreover some initialization is needed, which has to be done in an application context.
The problem with the second option is that the Factory can be registered only once (check java.net.URL#setURLStreamHandlerFactory), and unfortunately it is done by Tomcat.
What i can do is to create a decorator factory which will extend the existing one by my protocol handler. Than using relfection set the static field URL#factory to null and register (again?) my "decoratorFactory" in a standard way using URL#setURLStreamHandlerFactory. I'm just wondering if it is a good idea to use the reflection here...? How about the security?
I would like to do something like that:
try {
Field factoryField = URL.class.getDeclaredField("factory");
factoryField.setAccessible(true);
// get current factory
Object currentFactory = factoryField.get(null);
// define a decorator factory
MyFactoryDecorator mfd = new MyFactoryDecorator(currentFactory);
// set the factory to null and register MyFactoryDecorator using URL#setURLStreamHandlerFactory.
factoryField.set(null, null);
URL.setURLStreamHandlerFactory(mfd);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Idk if this would work, but what if you create a new URLStreamHandlerFactory that doesn't actually contain the implementation? It just sits there and then instantiates the real implementation at runtime when it is called via an app context lookup. Then in theory you can instantiate this new proxy handler via the system property at the beginning, but also use the one you want when it is actually called.
UPDATE:
Actually, I think your link above mentions this strategy:
Another approach is to use the factory registration, but to provide a factory class that itself supports registration of multiple different stream handlers using different names.
This approach supports code using the java.net.URL class but it does require a registration call for each protocol and so hence changes are needed to an application before it can make use of the new URLs. However the approach gets around the problems discussed above with multiple class loaders since the factory is loaded by the user code class loader rather than by the class loader for the URL class.
I'm not super familiar with what all you're doing and how the registration works, so this could be more or less complicated depending on what you're doing. Idk if you even need the extra registration or not, but it sounds like it might solve the .jar/app context problem.

Simple Dependency injection not working

It's the first time I have to use Dependency Injection and I'm a little confused.
I don't really understand how it works.
I have tried on a simple example :
public class StockResponse extends Response
{
#Inject BrandService $brand;
public List<StockResponseItem> stock;
public StockThresholdResponse()
{
stock = new ArrayList<>();
}
public static StockThresholdResponse create(List<DataItem> data)
{
StockResponse stock= new StockResponse();
for (ThresholdCheckAggregate data: d)
{
StockResponseItem item = new StockResponseItem();
item.id = d.thresholdId;
item.brand = str.$brand.byId(d.brand);
str.stockThresholds.add(item);
}
return str;
}
}
But when I use my create() method, I get a null pointer exception for $brand.
I think I have misunderstood how DI works but I can't find my error.
I had similar difficulties to understand how DI (Guice out of Java EE) works. In simple words Guice must have chance to modify You object, for example:
assist by construction usually.
You ask Guice "can You create my object" injector.getInstance(cls), then Guice is creating object for You, solving field or constructor annotation
In normal (non Java EE) environment Yoy never call classic constructor, You ask by second hand.
other method.
Few library / frameworks have integration with Guice (Apache Wicket I personally like) with "creation listeners" on some types of objects. Hard work of DI is hidden for Your eyes, but is executed.
Java EE lets say better EE programmers than me :(
In consequence Yoy don't give chance to inject anything, is null
Professionals sorry that I say at blondie level. That is way like I discovered DI few years ago
Correction to code. Not
StockResponse stock= new StockResponse();
but
mod = .... // Module
injector = Guice.createInjector(mod); // global or almost global
...
injector.getInstance(StockResponse.class);
EDIT: intentionally I don't answer "how to write Guice module", assume this is other, long story
This could work, assuming BrandService is either a concrete class or if it's an interface, you have provided a binding for it to a concrete class elsewhere in your DI configuration (say a module in Guice or Spring #Configuration). I do see one obvious NullPointerException with str variable. Did you mean to do this?
item.brand = stock.$brand.byId(d.brand);

Java, how to using expression language in pure java

I have a JavaEE web application, as it will be deployed to some kind of application servers such as weblogic websphere tomcat etc. so the EL api will be avaiable for me, but I don't need to care about what EL implementation is used.
I want to use EL in my java code, not jsp pages, to translate some simple expression to value constants, like this:
public static void main(String[] args) {
// TODO Auto-generated method stub
ExpressionFactory ef = new ExpressionFactoryImpl();
SimpleContext ec = new SimpleContext();
ec.setVariable("value", ef.createValueExpression("0", String.class));
ValueExpression ve = ef.createValueExpression(ec, "${value == \"1\" ? \"enabled\" : \"disabled\"}", String.class);
System.out.println(ve.getValue(ec));
}
however, in this example, I used JUEL library, so I need to access JUEL implementation classes. my question is how Can I do the same thing but just use classes in javax.el package ?
Do I need to implement my own ELContext and VariableMapper and other abstract classes ?
I believe you don't need to hack EL together with your code, I think in some cases that might be problemmatic.
There are quite a lot of libraries offering similar functionalities (known as Template Engines), try Velocity or FreeMarker for example. They are extremely easy to use and have quite a lot of options.
MVEL solve my problem, it's flexible and powerful!

Categories

Resources