Handling private write methods on singleton EJBs - java

I have a singleton EJB whose business methods are all #Lock(READ). However, on special ocassions, some of them call a private method that persists stuff on a database. What's the best way to handle this situation? Should I:
Use #Lock(WRITE) for that private method even though it's not a business method? If so, is this a reliable behaviour?
Do the synchronization on the private method myself? If so, is it safe to synchronize over the EntityManager?
Do something completely different?

This only partially answers your question, but here goes.
You could put the private methods in a "private" businness interface and call them via the container like this:
TestEJB.java:
#Stateless
public class TestEJB implements PrivateIface, PublicIface {
SessionContext ctx;
public void doBusiness() {
PrivateIface businessObject = ctx.getBusinessObject(PrivateIface.class);
businessObject.doPrivateBusinness();
}
#SomeContainerAnnotation
public void doPrivateBusinness() {
}
}
#Local
interface PrivateIface {
void doPrivateBusinness();
}
PublicIface.java:
#Local
public interface PublicIface {
void doBusiness();
}

Related

Java: calling public transactional method from a private method

I have two classes
public class MyTest {
#Autowired
private MyService myService;
private void test() {
myService.writeToDb();
}
}
#Service
public class MyService {
#Transactional
public void writeToDb() {
// do db related stuff
}
}
I want to know if calling a method test() (which is a private method) from MyTest class would create a transaction.
P.S
I'm using Spring Boot. And Java 17.
It will work, whether you call the method of another object from a public or private method inside yours is an implementation detail. From callee's point of view, it's the same, it is not even aware of the caller's context.
Spring AOP uses the Proxy pattern to handle those scenarios. It means you are not directly receiving a MyService bean, but a MyServiceSpringCreatedProxy (not the actual name, check in debug mode and you'll see), which is actually handling transactions around methods.
So as long as the call passes through the Spring's proxy, the #Transactional will be accounted for as expected. Bear in mind that it doesn't mean a new transaction is open, it depends if another already exists and your configuration.
However, any self call (to a public or a private method) would not pass through the proxy and then #Transactional would not be working.
#Service
public class MyService {
// can be private, public or whatever
public void callRelatedStuff() {
//self call, no transactional work done
writeToDb();
}
#Transactional
public void writeToDb() {
// do db related stuff
}
}

Should I never use #PostConstruct in Spring Boot when I have All Args Constructor?

In out project we don't use setter or filed injection, we use only constructor injection, and I know that both options 1. and 2. may work.
Is it unsafe to work with beans in constructor in that case?
Or spring boot 2+ makes something, and I should better use option 1. instead of 2. I can't imagine case when option 1 will go wrong
#Component
#ConfigurationProperties("config")
public class ServiceConfigProperties {
// .... some code
}
Can be unsafe? - but it looks better
#Component
public class Service {
private boolean skipCheck;
public Service(ServiceConfigProperties configProps) {
this.skipCheck = configProps.isSkipCheck();
}
}
Can't be unsafe?
#Component
public class Service {
private boolean skipCheck;
private ServiceConfigProperties configProps;
public Service(ServiceConfigProperties configProps) {
this.configProps= configProps;
}
#PostConstruct
public void initConfig() {
this.skipCheck= configProps.isSkipCheck();
}
}
With a couple of caveats, interacting with constructor-injected beans inside the constructor is completely safe.

How to invoke a stateless bean method if it is not declared in interface implementing the business logic

I am not so experienced in EJBs, especially EJB 3.0 and thus, I faced out with a question I would like to resolve. A similar issue I have found here, but the suggested solution did not help.
I have a remote stateless EJB with its business methods declared in interface and the bean which implements those methods has also other methods which are not declared in interface.
As an example here is the business interface:
public interface BusinessLogic {
Object create();
void delete(Object x);
}
A BusinessLogicBean which implements the business logic:
#Stateless
#Remote(BusinessLogic.class)
public class BusinessLogicBean implements BusinessLogic {
/** implemented method */
public Object create() {
Object x = new SomeDBMappedObject();
// create an object in DB and return wrapper class
...
return x;
}
/** implemented method */
public void delete(Object x) {
// deleting object from DB
...
}
/** The method that performs some extra logic */
public void aMethod() {
// do extra logic
}
}
I need to write unit tests for that EJB using Arquillian framework including for the bean methods which are not declared in the business interface.
Example:
#RunWith(Arquillian.class)
public class BusinessLogicTest {
/** will be injected during the test run */
#EJB
private BusinessLogic businessLogic;
#Deployment
public static Archive createDeployment() {
WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war")
// add needed libraries and classes
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
return war;
}
#Test
public void aMethodTest() {
businessLogic.aMethod();
// Write appropriate assertions
}
}
My questions are:
how can I call aMethod() in my test?
I cannot call it like businessLogic.aMethod();, since it will result in a compilation error.
I cannot call it like ((BusinessLogicBean) businessLogic).aMethod();, as it will result in a ClassCastException since the actual object is a com.sun.proxy.$ProxyXXX type.
or
Is there a way to inject BusinessLogicBean object directly instead of BusinessLogic?
You can annotate BusinessLogicBean with #javax.ejb.LocalBean
#Stateless
#LocalBean
#Remote(BusinessLogic.class)
public class BusinessLogicBean implements BusinessLogic {
...
}
and inject it by its class name:
#EJB BusinessLogicBean businessLogicBean;
See also:
Docs
A useful related question

Performance: Utility class vs. CDI bean

I want to externalize commonly used applicationlogic into a "utility class" called Helper. The applicationlogic needs other CDI beans to work.
Two possibilities:
a)
#SessionScoped
class ControllerWithCdiBean {
#Inject
Helper helper;
public void doIt() {
Object result = helpder.calculate();
}
}
#RequestScoped
class Helper{
#Inject
Service anyService;
public Object calculate() {
return anyService.calc();
}
}
b)
#SessionScoped
class ControllerWithStaticCallsViaDeltaspike {
public void doIt() {
Object result = Helpder.calculate();
}
}
class Helper{
private static Service anyService = BeanProvider.getContextualReference(Service.class);
public static Object calculate() {
return anyService.calc();
}
What about performance? Are there any notable differences? Both solutions are possible for me, is one solutions better than the other?
One disadvantage:
Helpder gets initialized for every Request.
Mark your Helper class as #ApplicationScoped. With this, you will have a single instance per application context.
Still, if it's just an utility class, it shouldn't be a managed bean at all. I would instead mark it as final, define a private constructor and mark all the methods as static. This is because since it's an utility class, it doesn't need to maintain any state.

Stateful bean doesn't keep state

I have a stateful bean:
#Stateful
public class ClientContext {
private Band band;
public Band getBand() {
return band;
}
public void setBand(Band band) {
this.band = band;
}
}
I have Arquillian test.
public class RequestTest extends Arquillian {
...
#Inject
private ClientContext context;
#Inject
private RequestProcessor processor;
#Test
public void test() {
context.setBand(new Band());
Assert.assertNotNull(context.getBand());
processor.doSomething();
}
}
And Processor code:
#Stateless
#LocalBean
public class RequestProcessor {
...
#Inject
private ClientContext context;
public void doSomething() {
System.out.println(context.getBand());
}
}
I expect RequestProcessor to print out the Band. But actually I get null every time. What can be wrong or may be I don't understand Stateful beans correctly?
You are answering the question yourself, the main basis about the stateful is the keep just one instance per injection, which will live as long the injecting bean does.
so in you need to share a state between beans, you could use a #SessionBean
To clarify, the #Stateful means one instance are going to be created for each place where you are injecting it, this is useful when you need to bind some actions and their state to ONE component, so, if you need to create some info and then share between other classes you need to pick how you want to share it:
#Singleton: There will be just one instance for the entire app.
#SessionScoped: There will by one instance per client.
#Stateless: Will create one if there is no other available, after it will be release for use of other clients
If you are managing views the you can use too:
#RequestScoped: Will create one instance for each request and then destroys it.
#ViewScoped: The bean will remain as long the client keep making updates within the same view

Categories

Resources