Null pointer with self injection EJB - java

I am using JEE7, I have a Stateless EJB that is using self injection to solve a problem with transactionality.
When I make the call to the method selfMethod and it is public, everything works. If it is private, the injected components are null.
I guess it is somehow related to the proxy model and the self injection, but do not really understand why.
#Stateless
public class AnEjb {
#Inject
#EJB
private AnEjb self;
#Inject
private AClass anObject;
public void normalMethod() {
self.selfMethod();
}
public/private void selfMethod() {
anObject.anyMethod(); // Null pointer exception if selfMethod is private, no problem if it is public
}
}

The EJB APIs provide a mechanism for self invocation:
#Stateless
public class AnEjb {
#Resource
private SessionContext sessionContext;
private AnEjb self;
#PostConstruct
void initialise() {
self = sessionContext.getBusinessObject(AnEjb.class);
}
public void normalMethod() {
self.selfMethod();
}
public void selfMethod() {
anObject.anyMethod();
}
}
Note that the SessionContext.getBusinessObject method returns the same "view" of the EJB that external clients will see, therefore only its public methods will be accessible.

Related

what is the best way to autowire parent class field in spring?

When I use spring framework, I find something that should be extract, for example, the service component (or member variable that is autowired).
Code show as below:
abstract class Payment {
PaymentService paymentService;
void setPaymentService(OrderPaymentService paymentService) {
this.paymentService = paymentService;
}
}
#Component
public class CancelPayment extends Payment{
private OtherService2 otherSerivce2;
#Autowired
#Override
public void setPaymentService(PaymentService paymentService) {
super.setPaymentService(paymentService);
}
#Autowired
public CancelPayment(OtherService2 s2) {
this.otherSerivce2 = s2;
}
}
#Component
public class CreatePayment extends Payment{
private OtherService1 otherSerivce1;
#Autowired
#Override
public void setPaymentService(PaymentService paymentService) {
super.setPaymentService(paymentService);
}
#Autowired
public CreatePayment (OtherService1 s1) {
this.otherSerivce1 = s1;
}
}
As you can see, I use setter injection in each child class. Is this a better practice than autowire their parent's member variable?
Here are DI guidelines by Spring team:
A general guideline, which is recommended by Spring (see the sections on Constructor-based DI or Setter-based DI) is the following:
For mandatory dependencies or when aiming for immutability, use
constructor injection
For optional or changeable dependencies, use setter injection
Avoid field injection in most cases
Now if you are sure you will use PaymentService I would suggest you to use constructor injection in your abstract class like this so object won't instantiate without dependency, also making it more immutable, clearer and thread safe:
abstract class Payment {
PaymentService paymentService;
public Payment(OrderPaymentService paymentService) {
this.paymentService = paymentService;
}
}
Then you can simply call super on your extended classes like this:
#Component
public class CreatePayment extends Payment{
private OtherService1 otherSerivce1;
#Autowired
public CreatePayment(PaymentService paymentService) {
super(paymentService);
}
}
This simply allows you to inject parent class using constructor (if paymentService is mandatory).

Spring injected beans null in nested class

I have a class with 2 static nested classes that do the same operation on 2 different generic types.
I exposed the 2 classes as beans and added #Autowired for the constructors as I usually do.
Here is the basic setup
abstract class <T> Parent implements MyInterface<T> {
private final Service service;
Parent(Service service){ this.service = service; }
#Override public final void doInterfaceThing(T thing){
T correctedT = map(thing);
service.doTheThing(correctedT);
}
protected abstract T map(T t);
#Service
public static class ImplA extends Parent<A> {
#Autowired ImplA (Service service){ super(service); }
A map(A a){ //map a }
}
#Service
public static class ImplB extends Parent<B> {
#Autowired ImplB (Service service){ super(service); }
B map(B b){ //map b }
}
}
And in another class I have
#Service
public class Doer {
private final List<MyInterface<A>> aImpls;
#Autowired public Doer(List<MyInterface<A>> aImpls){ this.aImpls = aImpls; }
public void doImportantThingWithA(A a){
aImpls.get(0).doInterfaceThing(a);
}
}
When I run the app, everything appears to be injected correctly and when I put a breakpoint in the ImplA and ImplB constructors, I have a not-null value for "service". I also have an ImplA bean in the aImpls list in Doer.
When I call doImportantThingWithA(a) however, "service" is null inside ImplA and I obviously die.
I'm not sure how this is possible because:
I see a nonnull value in my constructors for service which is a final field.
If spring is injecting ImplA and ImplB into another class, it should already have either injected a Service into ImplA or ImplB, or thrown an exception on bean initialization. I have nothing set to lazily load and all bean dependencies are required.
The reason for the nested classes is because the only thing that changes between the 2 implementations is the map() function. Trying to avoid extra classes for 1 line of varying code.
More info:
When I add a breakpoint in Parent.doInterfaceThing(), if I add a watch on "service" I get null as the value. If I add a getService() method, and then call getService() instead of referring directly to this.service, I get the correct bean for service. I don't know the implications of this but something seems weird with the proxying.
It looks like what is causing the issue is Parent.doInterfaceThing();
If I remove final from the method signature, "service" field is correctly populated and the code works as expected.
I don't understand at all why changing a method signature affects the injected value of final fields in my class... but it works now.
What I meant with my "use mappers" comment was something like this:
class MyInterfaceImpl implements MyInterface {
#Autowired
private final Service service;
#Override public final <T> void doInterfaceThing(T thing, UnaryOperator<T> mapper){
T correctedT = mapper.apply(thing);
service.doTheThing(correctedT);
}
// new interface to allow autowiring despite type erasure
public interface MapperA extends UnaryOperator<A> {
public A map(A toMap);
default A apply(A a){ map(a); }
}
#Component
static class AMapper implements MapperA {
public A map(A a) { // ... }
}
public interface MapperB extends UnaryOperator<B> {
public B map(B toMap);
default B apply(B b){ map(b); }
}
#Component
static class BMapper implements MapperB {
public B map(B a) { // ... }
}
}
This does have a few more lines than the original, but not much; however, you do have a better Separation of Concern. I do wonder how autowiring works in your code with the generics, it does look as if that might cause problems.
Your client would look like this:
#Service
public class Doer {
private final List<MapperA> aMappers;
private final MyInterface myInterface;
#Autowired public Doer(MyInterface if, List<MapperA> mappers){
this.myInterface = if;
this.aImpls = mappers; }
public void doImportantThingWithA(A a){
aMappers.stream().map(m -> m.map(a)).forEach(myInterface::doInterfaceThing);
}
}

#Inject failing when injecting in a #Stateless bean

I'm working in a project with Java EE 7 and I need to inject a javax.ejb.#Stateless bean into another. Both beans have a similar structure:
#Stateless
public class OperationRepository extends GenericRepository<Operation> {
#PersistenceContext
private EntityManager entityManager;
public OperationRepository() {
}
/*Implementation of abstract methods, getters/setters, etc*/
}
#Stateless
public class MenuRepository extends GenericRepository<Menu> {
#PersistenceContext
private EntityManager entityManager;
#Inject
private OperationRepository operationRepository;
public MenuRepository() {
}
/*idem OperationRepository*/
public List<Menu> getMenuFromOperation(...) {
// Do something where I need operationRepository
}
}
The GenericRepository<E> is just an abstract class with some common methods and other abstract methods, doesn't matter here.
The problem is that in the getMenuFromOperation() method I get a NullPointerException. Debugging the code I realized that the injected operationRepository is null when requested in the method.
Why does fail the injection point? what am I missing here?
Just to make a little test, I injected manually by instantiating a default OperationRepository in the MenuRepository constructor, but in that case the OperationRepository.entityManager isn't injected (is null)
Thanks in advance for your answers.
Edit #1
As requested by John Ament, here it goes:
All my code is in a single jar file. It's a Maven module that will be deployed together with a web module (a war package) in a Glassfish Server 4.1.
The beans.xml still doesn't exists yet, because the project isn't ready to be deployed (I didn't perform any integration test yet)
The MenuRepository is leveraged from a #Test class because I'm still developing MenuRepository.
The code for the test class is as follows:
public class MenuOperationRepositoryUTest extends BaseTestRepository {
private MenuRepository menuRepository;
private OperationRepository operationRepository;
#Before
public void initTestCase() {
initTestDB();
menuRepository = new MenuRepository();
menuRepository.setEntityManager(em);
operationRepository = new OperationRepository();
operationRepository.setEntityManager(em);
}
#After
public void finalizeTestCase() {
closeEntityManager();
}
/*Some successful tests*/
#Test
public void showMenuFromOperation() {
// Insert some dummy data into the test DB (HSQL)
// This method needs the injected OperationRepository in MenuRepository
List<Menu> menu = menuRepository.getMenuFromOperation(...);
// Assertions
}
}
And the BaseTestRepository is as follows:
#Ignore
public class BaseTestRepository {
private EntityManagerFactory emf;
protected EntityManager em;
// This is a helper class that contains all the boilerplate to begin transaction
// and commit, it's used to insert data in the test DB
protected DBCommandExecutor dbCommandExecutor;
protected void initTestDB() {
// sigeaPU is the name declared in persistence.xml
emf = Persistence.createEntityManagerFactory("sigeaPU");
em = emf.createEntityManager();
dbCommandExecutor = new DBCommandExecutor(em);
}
protected void closeEntityManager() {
em.close();
emf.close();
}
}
I think that's all I got so far. Let me know any clue you can get (or guess)
Because you're testing out of the CDI container you should also set your dependencies manually in the #Before method of the test class.
menuRepository.setOperationRepository(operationRepository)

Spring can't Autowired abstract class with final method

public abstract class BaseLoaneeRepayment implements Repayment {
#Autowired
protected LoanRepository loanRepository;
#Transactional(propagation = Propagation.REQUIRES_NEW)
public final void repay(RepaymentInfo repaymentInfo) {
Loan loan = loanRepository.lockAndLoad(repaymentInfo.getLoan().id());
}
protected abstract void preCheck(final RepaymentInfo repaymentInfo);
protected abstract void updateLoanee(final RepaymentInfo repaymentInfo);
protected abstract void repayment(final RepaymentInfo repaymentInfo);
protected abstract void calcDifference(final RepaymentInfo repaymentInfo);
}
#Service("loaneeNormalRepayment")
public class NormalRepayment extends BaseLoaneeRepayment implements Repayment {
private static final CatLogger logger = CatLoggerFactory.getLogger(NormalRepayment.class);
#Override
public final void preCheck(RepaymentInfo repaymentInfo) {}
#Override
public final void updateLoanee(RepaymentInfo repaymentInfo) {}
#Override
public final void repayment(RepaymentInfo repaymentInfo) {}
#Override
public final void calcDifference(RepaymentInfo repaymentInfo) {}
}
in Junit,
#TransactionConfiguration(defaultRollback = true)
public class NormalRepaymentTest extends ServiceTest {
#Autowired
#Qualifier("normalRepayment2")
private NormalRepayment normalRepayment;
#Autowired
private LoanService loanService;
#Test
public void test() {
normalRepayment.repay(repaymentInfo);
}
}
This normalRepayment.repay(repaymentInfo); in NormalRepayment loanRepository is null. The autowire not work.
The behavior you see is related to proxies. In certain cases, for Spring managed beans, Spring will create a proxy for the target class. In this case, methods are marked as #Transactional, and Spring will create a proxy which implements transaction handling for your service. Depending on the proxy strategy, Spring may proxy by subclass, which means a subclass will override methods of the target class and implement various logic such as transaction handling in those methods. In this case, the dependencies will be injected in the proxy, not the target class.
Java, by design, does now allow overriding final methods, and because of this, the proxy subclass will not be able to override the final methods in your concrete class.
The calling code will, in this case, in fact call the non-proxied target methods, where dependencies are not injected and no transactional handling is present.
Solution: Remove the final modifier from the methods in your concrete class, which will allow Spring to properly proxy your service class.

javax inject on a Resteasy service not working on Jetty

I have this Restful service:
#Service
public class MyRESTServiceImpl implements MyRESTService {
#Inject
private Helper helper;
public MyRESTServiceImpl() {
}
#Override
public List<Something> getThings() {
return helper.getThings(); // NPE here!
}
}
The problem here is that when getThings is accessed through /api/getThings, although the method is invoked the helper is not injected. Whereas on the other parts of the app it injected properly. I am missing some annotation for this MyRESTServiceImpl?

Categories