Passing state between EJB methods / #RequestScoped and #Stateless - ejb

I have a #RequestScoped CDI bean that I want to turn into an EJB to get declarative transactions. (I'm on EJB 3.1, Java EE 6)
Currently, I am passing state between subroutines, under the assumption that the instance is only used in a single request. If I add #Stateless now that assumption would change.
For example, I want to do something like
#Stateless
#Named
#RequestScoped
public class Foo {
private String var1; // can't use instance vars in #Stateless?
private String var2;
public void transactionForRequest() {
var1 = value;
var2 = value;
....
subroutine();
}
}
I assume the above doesn't work- is that correct?
I am contemplating two alternatives:
Use #Stateful instead of #Stateless, along with #Named and #RequestScoped.
Keep #Stateless and use EJBContext.getContextData map to replace instance variables.
Which is better? And is there some other alternative I'm not thinking of? (Besides wait for Java EE 7 or switch to Spring. :-))

While #Stateless, #Singleton and #MessageDriven can have scoped references injected via #Inject, they cannot be #RequestScoped or any other scope. Only the #Stateful model is flexible enough to support scopes. In other words, you can annotate the #Stateful bean class itself as #RequestScoped, #SessionScoped, etc..
In simple terms #Stateless, #Singleton have fixed "scopes" already. #Singleton is essentially #ApplicationScoped and #Stateless would perhaps be some made-up scope like #InvocationScoped, if that existed. The lifecycle of an #MessageDriven bean is entirely up to the Connector that drives it and is therefore also not allowed to have user-defined scope.
See also https://stackoverflow.com/a/8720148/190816

I would go with SFSB instead of SLSB. You want to hold a state, so for me this is the most important information - this is a job for Stateful EJB.
Also I don't think that EJBContext#getContextData() would help you. As far as I remember, it's only valid for a duration of a call. Therefore, each invocation of a method on your EJB will create new context data map (at least it's what I would expect.)

If you are using Stateless beans then you are responsible for any state-management and you would normally do this in the web-app layer using HttpSessions. And yes, you can't use instance variables as stateless beans are pooled.

Related

Why does Spring Boot have #ConditionalOnMissingBean(name = "kafkaListenerContainerFactory")?

about KafkaAnnotationDrivenConfiguration
Why exactly the condition by name? because of this, several bins appear in the context.
The kafkaListenerContainerFactory name is used in the KafkaListenerAnnotationBeanPostProcessor:
/**
* The bean name of the default {#link org.springframework.kafka.config.KafkaListenerContainerFactory}.
*/
public static final String DEFAULT_KAFKA_LISTENER_CONTAINER_FACTORY_BEAN_NAME = "kafkaListenerContainerFactory";.
Since we cannot use a dependency injection for BeanPostProcessor, there is a convention in spring-kafka to just specify a bean name which has some default. So, by convention Spring Boot auto-configures one specific for us.
Not sure what is your concern about several beans, but you indeed can have configured #KafkaListener for specific containerFactory and not rely on a default one.

What does it mean when saying "to be assigned something"| ASP.NET Core

I was reading a book about Learning ASP.NET Core API when I run to a part saying:
We create a private read-only field _repository that will be assigned
the injected MockCommandAPIRepo object in our constructor and used
throughout the rest of our code.
Here is some text I thought you'd better have:
Then there are some explanations related to the picture above:
Add the new using statement to reference ICommandAPIRepo.
We create a private read-only field _repository that will be assigned the injected MockCommandAPIRepo object in our constructor
and used throughout the rest of our code.
The Class constructor will be called when we want to make use of our Controller.
At the point when the constructor is called, the DI system will spring into action and inject the required dependency when we ask for
an instance of ICommandAPIRepo. This is Constructor Dependency
Injection.
We assign the injected dependency (in this case MockCommandAPIRepo) to our private field (see point 1).
And that’s pretty much it! We can then use _repository to make use of our
concrete implementation class, in this case MockCommandAPIRepo. As
I’ve stated earlier, we’ll reuse this pattern multiple times through
the rest of the tutorial; you’ll also see it everywhere in code in
other projects – take note.
Now, According to the highlighted part above in number 2, I got a little confused!
I've heard of "to be assigned by some value" before, but here, it is saying that:
that will be assigned the injected MockCommandAPIRepo object in our constructor
and as you see, there is no "by" added before the injected MockCommandAPIRepo object....
So, I have a question now. What does it mean by the highlighted part above in number 2?
Does it mean the same when we add "by" in the sentence? or not?
This is about dependency injection in Asp.Net Core. After we register service to the IOC Container, How to use it in our controller? We can inject them in controller via Constructor Injection. Once we register a service, the IoC container automatically performs constructor injection if a service type is included as a parameter in a constructor. In your question, An IoC container will automatically pass an instance of ICommandAPIRepo(MockCommandAPIRepo) to the constructor of CommandsController. Now we can use MockCommandAPIRepo in the constructor. But it can only be used in constructor, How can we use it in other method in CommandsController? Here we use:
private readonly ICommandAPIRepo _repository;
to create a global variable in CommandsController, Then in constructor, We use:
_repository = repository
assign the value of repository to _repository. Now _repository and repository has the same value, Because _repository is a global variable, So We can use _repository in other method in CommandsController. The whole process of dependency injection is done.

Injecting logger into middleware dependency

I have a middleware library I intend on using in multiple projects. The middleware itself looks something like:
public SdkMiddleware(RequestDelegate next, ILogger<SdkMiddleware> logger, ISdk sdk)
{
this.next = next;
this.logger = logger;
this.sdk = agentSdk;
this.sdk.Init();
...
}
Thanks to DI, I can simply inject my logger:
// Would rather this class be internal...
public class Sdk: ISdk
{
private ILogger<Sdk> logger;
public Sdk(ILogger<Sdk> logger)
{
this.logger = logger;
}
public void Init() {
this.logger.Info(...) // Do some logging
}
The downside to this is my class needs to be registered in every ASP.Net project's Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ISdk, Sdk>();
Is the best/only route? Every time I want to inject a logger into a class, I need to register that class for DI in my composition root?
There is nothing wrong in having the consumer of your library compose the dependencies for this library in the composition root. That's how dependency injection works. You could of course provide some default implementations and a custom extension method that would register those default implementations into the DI and then let the consumer simply call your extension method.
There are a few things that I feel need clarification here:
Dependency injection/inversion of control
To understand what is the benefit of dependency injection(DI) it is better to look at the principle of inversion of control(IoT) that DI implements.
In your case you want SdkMiddleware class to contain a reference to ILogger implementation. The simplest way to do this is for SdkMiddleware class to create an instance of a class that implements ILogger interface. The downside of such approach is that SdkMiddleware needs to know which class implements ILogger interface and how to instantiate it. In other words, SdkMiddleware has control over the creation of ILogger object. The inversion of control happens when the responsibility of knowing which class implements ILogger and how to create an instance of it is taken away from SdkMiddleware to some other class (dependency container in DI) and the instance if it is given to SdkMiddleware to use (through injection in DI). In this case the control over the creation of ILogger object is outside of SdkMiddleware. Since this changes the direction of control, it is called "Inversion of control".
The benefit of this approach is when you will need to provide another implementation of ILogger or change the way you create an instance of that class, you don't need to change SdkMiddleware at all.
Bootstrapping
So now that we clarified why we are using DI, lets take a look at what do we need to actually use it.
The object that creates all instances, controls which object is injected into which and gives away ready to use objects is usually called DI container or IoT container. In asp.net core "IServiceCollection services" is used as such a container. But it still needs to know how to create objects and which implementation to inject for which interface. This is where bootstrapping comes in.
In a bootstrapper class or method you need to specify how objects are built from classes and how classes relate to interfaces. As an example of the former, imagine that you need to pass a connection string for a database from your configuration to a class that creates a db connection. As for the latter, that is exactly what your line "services.AddTransient()" does.
The answer
I am sorry it took so long to get to the actual answer for your question but I wanted to provide some overview first.
Do you need to specify a relation between a class and an interface to inject logger into your class? No. Your class may not even have an interface to begin with and DI container will inject all the dependencies in it by default if you ask for an object of a class instead of an instance of an interface. You can also use or define some convention over configuration solution so that binding of classes and interfaces will happen automatically.
The bottom line is that registration of a class and the actual injection are not connected. But the code you provided is the default way to do this.

#Specializes for EJB

I'm trying to specialize an EJB. I have
package com.foo.core;
#Stateless
public class MyFacade { }
and
package com.foo.extension;
#Specializes
#Stateless
public class MyFacade extends com.foo.core.MyFacade { }
In my opinion, this should work, because the meaning of #Specializes is, that CDI should forget about the core-class and instead use the specialized class. I also found this bug https://issues.jboss.org/browse/WELD-1451 which indicates, that it is possible to specialize an EJB.
But if i try to deploy my application (I'm using Weblogic 12.1.3), I always get
weblogic.utils.ErrorCollectionException: There are 1 nested errors:
weblogic.j2ee.dd.xml.AnnotationProcessException: Duplicate ejb name
'MyFacade' found: annotation 'Stateless' on bean class
com.foo.core.MyFacade and annoation 'Stateless' on bean class
com.foo.extension.MyFacade
Am I doing anything wrong?
Thanks!
The exception message you quoted is caused by a name conflict, which is not directly related to CDI at all: each EJB can be addressed by a number of different JNDI names, and some of them (e.g. java:module/MyFacade) only include the simple class name, not the package name. So you cannot have two EJBs with the same name in different packages.
Adding CDI and #Specializes may prevent the specialized EJB from showing up in the CDI container, but it is still an EJB.
You can try to rename your derived class - this should solve the duplicate name issue, but I'm not sure it will solve your overall problem.

javax.ejb.EJBException: Illegal non-business method access on no-interface view

I'm using EclipseLink on GlassFish 3.1.1 and I'm trying to understand this exception:
javax.ejb.EJBException: Illegal non-business method access on no-interface view
at org.mycompany.myproject.session.__EJB31_Generated__MyBeanFacade__Intf____Bean__.getEntityManager(Unknown Source)
at org.mycompany.myproject.session.AbstractFacade.edit(AbstractFacade.java:28)
at org.mycompany.myproject.controller.EditMyBeanServlet.doPost(EditMyBeanServlet.java:199)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
Notice that the stack trace indicates that the problem is triggered in the Netbeans generated AbstractFacade.getEntityManager method.
Any idea what the heck is going on or any tips to troubleshoot? I'm guessing that either the transaction or caching state in the EJB is weird when this happens because sometimes calling the edit method works fine. I'm calling the EJB methods from a Servlet. The exception occurs when trying to save changes to an entity.
The error you get most likely indicates that your code is trying to call the protected method anyway. This is not allowed for no-interface views on an EJB. You are only allowed to call public methods.
There's a small mismatch here between the normal Java class rules and the EJB rules. For a no-interface view, a proxy is created based on the original class type (typically a dynamic sub-class of it). This thus means that protected and package private methods are visible for code in the same package, and as far as the Java compiler is concerned, your code is allowed to call those.
But as mentioned, this is not allowed by the EJB rules, and thus an exception is thrown.
You can reproduce this easily by injection a bean like the following:
#Stateless
public class FooBean {
public void callMe() {
}
protected void doNotCallMe() {
}
}
Inject this somewhere (e.g. Servlet in same package) and try to call doNotCallMe(). You'll see the same exception. Call callMe() and everything will be fine.
I think I may have found a solution and possibly a bug in third party software. It seems like GlassFish 3.1.1 / EJB 3.1 / EclipseLink can't handle method overloading correctly. I've got a method defined in my EJB named edit that overloads (not overrides) the method from the parent abstract class. There is a method named edit in the abstract parent of the EJB that takes a generic type and then I've got a method named edit in the EJB which takes a List. If I rename the method to something else so that it is no longer overloading then the exception goes away!
Code:
public abstract class AbstractFacade<T> {
protected abstract EntityManager getEntityManager();
public void edit(T entity) {
...
and
#Stateless
public class MyEntityFacade extends AbstractFacade<MyEntity> {
protected EntityManager getEntityManager() { return em; )
public void edit(List<MyEntity> entities) {
...
Note: I noticed if I make the getEntityManager method public instead of protected I'll get a TransactionRequiredException instead of an EJBException.
What is weird is i had same problme with on inner class of my EJB.
While trying to call private method of parent or accessing on injected EJB, i faced some problems.
I had visibility on most of things but finally a runtie, things goes wrong.
Finally, i decided to retrieve my parent class throught JNDI, thus i could call public method without troubles. Meanwhile i could call still private methods on my parents class, i still have to remember that it will fail.

Resources