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.
Related
As we know PowerMockito can prepare for test only one final, static, or private class like following:
#RunWith(PowerMockRunner.class)
#PrepareForTest(SomeClassNumber1.class)
public class SomeClassUnderTest{
#Before
public void setUp() throws Exception {
}
#Test
public void testSomeMethod() throws Exception {
}
}
But the method I am going to test uses more than one static classes. The thing I want to do looks like:
#RunWith(PowerMockRunner.class)
#PrepareForTest(SomeClassNumber1.class, SomeClassNumber2.class)
public class SomeClassUnderTest{
But #PrepareForTest has only one argument.
Edit: For instance the method will use singleton, factory or some static methods of different classes.
public class SomeClass {
private Session session;
private Object object;
public void someMethod(int userId) {
Session session = Session.getSession(userId);
Object object = Singleton.getInstance();
}
}
Note: The problem could be solved by using single responsibility principle. e.g. instead of using singleton inside the method that is going to be tested, I can extract it to another method like following, and mock it:
public class SomeClass {
private Session session;
private Object object;
public void someMethod(int userId) {
session = getSession(userId);
object = getInstance();
}
private getSession(userId) {
return Session.getSession(userId);
}
private Object getInstance(){
return Singleton.getInstance();
}
}
But this too doesn't seem good solution for me. It is better if PowerMockito or other testing tools have the feature that can mock several static classes at the same time.
Edit: For instance the method will use singleton, factory or some static methods of different classes.
You should not use static access to class members and methods in the first place, you should also avoid the Java singelton pattern, There are other possibilities to make sure you have only one instance of a class at runtime.
Having written this lets answer your question:
#PrepareForTest has only one argument.
This single argument may be an array:
#PrepareForTest({Class1.class,Class2.class})
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
class A {
public A() {
}
}
class B {
#Inject
#Named("A")
private A a;
public B() {
}
public A getA() {
return a;
}
}
class AModule extends AbstractModule {
#Override
protected void configure() {
}
#Provides
#Singleton
#Named("A")
public A providesA() {
return new A();
}
}
We are doing like this:
AModule module = new AModule();
Injector injector = Guice.createInjector(module);
B b = injector.getInstance(B.class);
System.out.println(sample.getA());
But we have many classes with A as dependency and we don't want to add this code every time we create an instance.
So, is there any way to auto inject instance of A while creating instance of B?
It is (usually) not correct to create as many top-level Injectors as you suggest in your question. Injector creation is expensive, and once Guice has calculated your graph of dependencies, you should not need to calculate it all over again. In general there should be one top-level Injector across your application, and any other Injectors are either "child injectors" or parts of a separate and unrelated object graph.
In order from "worst" to "best":
Keep the Injector statically
If you are introducing DI into a lot of existing or legacy code, then it may be tempting to stash the Injector into a publicly-accessible object.
public class InjectorHolder() {
private InjectorHolder() {} // Not instantiable
private static Injector injector;
public static void initializeInjector() {
injector = Guice.createInjector(new AModule(), new BModule(), andSoOn());
}
public static Injector get() {
return injector;
}
public static B getB() {
return injector.getInstance(B.class);
}
}
At this point you can call InjectorHolder.get().getInstance(B.class) or InjectorHolder.getB() from the parts of the app you've migrated so far. Note that this may be difficult to test, and relies on Guice directly from across your application—both of which are not ideal.
Use Guice static injections
Guice provides a few features for static injection, notably the method call requestStaticInjection(Class... types). With a call to that in your module, Guice will inject static members that have #Inject annotations as soon as the Injector is created.
public class StaticBModule extends AbstractModule() {
#Override public void configure() { requestStaticInjection(BFactory.class); }
}
public class BFactory() {
#Inject #Named("B") private static Provider<B> bProvider;
public B get() {
return bProvider.get();
}
}
Now you can call new BFactory().get() instead of new B(), and it'll all go to the same injector. Naturally, you could also allow new B() instead if you put a static Provider<A> into your B class and request static injection for that instead, or you could keep your BFactory as an instance and replace it during tests to issue the B instances you need. At that point, you might as well just retrofit the classes that call new BFactory() to instead include a static Provider<B>, and have them inject statically, and then migrate those, all the way up until you have a full DI solution (explained below).
You may also consult this SO question, which has an example.
Ideal solution
You've shown us A and B, but presumably some other class C uses many instances of B, and maybe YourApplication (which contains your static main method) uses C. You can use Guice to create an instance of YourApplication or C, and then C can contain an injected Provider<B> bFactory. Then, rather than call new B(), you can call bFactory.get() to create as many B instances as you might need.
This way, your classes depend on exactly what they depend on, with no static state or references to Guice other than at the top level.
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
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();
}