Suppose I have two real implementations A and B of some interface. And there is also a Delegate-implemenation of that interface that delegates to either A or B dependending on some logic.
I want to have the Delegate injected into my client class so I marked A and B as #Alternatives to make that unambiguous. However, now the injection into the Delegate does not work since A and B are alternatives.
Any suggestions on how to solve this?
import org.jglue.cdiunit.AdditionalClasses;
import org.jglue.cdiunit.CdiRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.enterprise.inject.Alternative;
import javax.inject.Inject;
#RunWith(CdiRunner.class)
#AdditionalClasses({ CdiTest.A.class, CdiTest.B.class, CdiTest.Delegate.class })
public class CdiTest {
public interface Service {
void run();
}
#Alternative
public static class A implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from A");
}
}
#Alternative
public static class B implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from B");
}
}
public static class Delegate implements CdiTest.Service {
int counter = 0;
#Inject A a;
#Inject B b;
#Override
public void run() {
System.out.println("Hi from Delegate");
if ((counter++) % 2 == 0) a.run();
else b.run();
}
}
#Inject
private Service service;
#Test
public void test() {
service.run();
}
}
I think tha you need qualifiers instead of alternatives.
Have you tried using two qualifiers ServiceA and ServiceB? You could inject in the delegate both implementations and in real test the delegate.
EDIT
I don't think you should replace the delegate with a producer (from your example I understood that the delegate has some functional role in your application and is not only a
test/production switch).
I think that you could create another class with a producer method like this:
public class ServiceProducer {
private static final String SERVICE_A = "service-a";
private static final String SERVICE_B = "service-a";
private static final String SERVICE_DELEGATE = "service-delegate";
#Produces
#Chosen
public CdiTest.Service getService(#SystemProperty("service.choose.key") String chosenKey,
#ServiceA Instance<Service> a,
#ServiceB Instance<Service> b,
#ServiceDelegate Instance<Service> delegate) {
switch(chosenKey) {
case SERVICE_A:
return a.get();
case SERVICE_B:
return b.get();
case SERVICE_DELEGATE:
return delegate.get();
default:
throw new IllegalStateException("No Service implementation for type " + chosenKey);
}
}
}
The #SystemProperty is a useful solution to inject system properties found at http://juraj.blahunka.eu/2014/05/17/inject-jboss-system-properties/
So you example code could be changed in:
public class CdiTest {
public interface Service {
void run();
}
#ServiceA
public static class A implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from A");
}
}
#ServiceB
public static class B implements CdiTest.Service {
#Override
public void run() {
System.out.println("Hi from B");
}
}
#ServiceDelegate
public static class Delegate implements CdiTest.Service {
int counter = 0;
#Inject #ServiceA Service a;
#Inject #ServiceB Service b;
#Override
public void run() {
System.out.println("Hi from Delegate");
if ((counter++) % 2 == 0) a.run();
else b.run();
}
}
#Inject
#Chosen
private Service service;
#Test
public void test() {
service.run();
}
}
This way you inject implementations A and B inside the delegate (without using the producer) and the produced one in your test class (choosing the correct implementation with a system property named "service.choose.key").
Related
I am working on a spring boot application, where I have an interface I as follows:
public interface I {
String getType();
void f1();
}
There are two classes implementing interface I as follows:
#Component
class A implements I {
private final MyRepo1 myRepo1;
private final Helper helper;
public A(MyRepo1 myRepo1, Helper helper) {
this.myRepo1 = myRepo1;
this.helper = helper;
}
#Override
public String getType() {
return "type1";
}
#Override
public void f1(String type) {
int response = helper.f1(type);
if(response != -1) {
return;
}
//Add type1 specific handling here
}
}
One more class B implementing interface I as follows:
#Component
class B implements I {
private final MyRepo2 myRepo2;
private final Helper helper;
public B(MyRepo2 myRepo2, Helper helper) {
this.myRepo2 = myRepo2;
this.helper = helper;
}
#Override
public String getType() {
return "type2";
}
#Override
public void f1(String type) {
int response = helper.f1(type);
if(response != -1) {
return;
}
//Add type2 specific handling here
}
}
Helper is as follows:
#Component
class Helper {
public int f1(String type) {
...
}
}
I have a factory class as follows, that is used to fetch an object of the appropriate type:
#Component
public class ServiceFactory {
private final Map<String, I>
typeToClassMap = new HashMap<>();
public ServiceFactory(List<I> components) {
for(I component : components) {
typeToClassMap.put(component.getType(), component);
}
}
}
This ServiceFactory is basically used to get objects according to the type.
Now, the problem is, here for sake of simplicity I have just shown two classes implementing the interface. But actually, I have a lot more classes than this, implementing the interface I.
Some of the classes may have the same implementation of f1(), resulting in duplicate code.
I cannot make f1() as the default method in interface I as this requires the dependent bean.
I cannot understand what is the best way to handle this.
Could anyone please help here?
I'm new in java, I want to call method class from implemented Class with interface without know class name "ClassA", which only know Object c and I have 2 file.
File (1) CobaInterface.java
package cobainterface;
public class CobaInterface {
public static void main(String[] args) {
ImplementedClass implementedClass = new ImplementedClass();
ClassA clsA = new ClassA();
implementedClass.myMethodFromClassA(clsA);
}
}
class ClassA{
public Integer getTwo(){
return 2;
}
}
interface MyInterface {
public void myMethod();
//here interface
public void myMethodFromClassA(Object c);
}
File (2) : ImpementedClass.java
package cobainterface;
public class ImplementedClass extends CobaInterface {
public void myMethodFromClassA(Object c) {
//System.out.println(c.getTwo()); <- wrong when call method c.getTwo()
}
}
How about if I want to call method getTwo() from ClassA without know Class Name, which only know Object c from file (2) as describe in code above. Thanks for advance.
You should use generic types so the implementation knows what the object will be,
interface MyInterface<T> {
public void myMethod();
//here interface
public void myMethodFromClassA(T c);
}
The impl becomes,
package cobainterface;
public class ImplementedClass Implements MyInterface<ClassA> {
public void myMethodFromClassA(ClassA c) {
//System.out.println(c.getTwo()); <- wrong when call method c.getTwo()
}
}
All together,
class Scratch {
public static void main(String[] args) {
ImplementedClass implementedClass = new ImplementedClass();
ClassA clsA = new ClassA();
implementedClass.myMethodFromClassA(clsA);
}
}
class ImplementedClass implements MyInterface<ClassA> {
#Override
public void myMethod() {
}
#Override
public void myMethodFromClassA(ClassA c) {
System.out.println(c.getTwo());
}
}
class ClassA {
public Integer getTwo() {
return 2;
}
}
interface MyInterface<T> {
void myMethod();
void myMethodFromClassA(T c);
}
You could also do a cast
System.out.println((MyClass)c.getTwo());
but you will lose all benefit of type saftey.
I am using the Mocktio library to write some test cases, since I have an elaborate inhertance structure, I have a few objects which are instantiated in the parent class, and I would like to mock one of its function call. Does Mockito library provide any way to spy on a already initialized object?
Also, the object is not directly instantiable.
Similar to the following -
public class A {
protected static MyObject a;
public static void someMethod() {
a = myObjectBuilder.createObj();
}
}
And another class B looks something similar to
class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
// now mock behavior of some method of MyObject a
// Missing line to spy object a.
Mockito.doReturn(false).when(a).xyz();
/* Now call some method that triggers a.xyz()
again, it is not a direct call,
there are multiple layer of abstraction
*/
}
}
Edit: I have tried the following and it does not work
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
Basically, don't do initialisation in BeforeClass, it runs only once but
you need to have new spy in each test, or you must "reinitialise" spy object
before each test.
Please examine this code:
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import static org.assertj.core.api.Assertions.assertThat;
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected static MyObject a;
public void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#Before
public void setUpBeforeTest() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(mock_object.xyz()).isTrue();
}
}
If you want it your way, please change:
public void someMethod() {
a = myObjectBuilder.createObj();
}
into:
public static void someMethod() {
a = myObjectBuilder.createObj();
}
You can't call non static method from static initialiser #BeforeClass:
class A {
protected static MyObject a;
public static void someMethod() {
a = new MyObject("cccc");
}
}
public class B extends A {
#BeforeClass
public static void setUpBeforeClass() {
someMethod();
}
#Test
public void mockTest() {
MyObject mock_object = Mockito.spy(a);
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(mock_object.xyz()).isFalse();
}
#Test
public void mockTest2() {
MyObject mock_object = Mockito.spy(a);
// Here we replace original object with our spy
A.a = mock_object;
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(a.xyz()).isFalse();
}
}
Another example (in this case we replace object a with mock (spy is not needed):
class MyObject{
public String cos;
public MyObject(String cos) {
this.cos = cos;
}
public boolean xyz() {
return true;
}
}
class A {
protected MyObject a;
public A() {
a = new MyObject("ggggg");
}
public String doSomethingWithA(){
if(a.xyz()){
return a.cos;
}
else{
return "aaaa";
}
}
}
#RunWith(MockitoJUnitRunner.class)
public class B {
#Mock
MyObject mock_object;
#InjectMocks
A systemUnderTest = new A();
#Test
public void mockTest1() {
Mockito.doReturn(false).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isEqualTo("aaaa");
}
#Test
public void mockTest2() {
Mockito.doReturn(true).when(mock_object).xyz();
assertThat(systemUnderTest.doSomethingWithA()).isNull();
}
}
I have a pojo class where in I have to call multiple ejbs based on the input string. For example , if the input is a x, I have to call XServiceBean, and if it is Y, I have to call YServiceBean.
I am planning to parameterise the input string x and the respective service bean in the database or xml. I do not want to put multiple if conditions or switch cases to call the service bean based on the input string.
Is there any simple pattern that i can use to achieve this. would be helpful if you can give some example
thank you
Main class where you can run as java for testing purpose
package stack;
public class ServiceInit
{
public static void main(String[] args)
{
new ServiceInit();
}
public ServiceInit()
{
ServiceBeanInterface xbean = ServiceFactory.getInstance().getServiceBean("X");
xbean.callService();
ServiceBeanInterface ybean = ServiceFactory.getInstance().getServiceBean("Y");
ybean.callService();
}
}
Service Factory which returns the bean that you want to call
package stack;
public class ServiceFactory
{
/*
* you can do it with factory and class reflection if the input is always the prefix for the service bean.
*/
private static ServiceFactory instance;
// the package name where your service beans are
private final String serviceBeanPackage = "stack.";
private ServiceFactory()
{
}
public static ServiceFactory getInstance()
{
if (instance == null)
{
instance = new ServiceFactory();
}
return instance;
}
#SuppressWarnings("unchecked")
public ServiceBeanInterface getServiceBean(String prefix)
{
ServiceBeanInterface serviceBean = null;
try
{
Class<ServiceBeanInterface> bean = (Class<ServiceBeanInterface>) Class
.forName(serviceBeanPackage + prefix + "ServiceBean");
serviceBean = bean.newInstance();
}
catch (ClassNotFoundException | InstantiationException | IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return serviceBean;
}
}
The interface which is implemented by your service classes
package stack;
public interface ServiceBeanInterface
{
void callService();
}
XServiceBean class
package stack;
public class XServiceBean implements ServiceBeanInterface
{
#Override
public void callService()
{
System.out.println("I am X");
}
}
YServiceBean class
package stack;
public class YServiceBean implements ServiceBeanInterface
{
#Override
public void callService()
{
System.out.println("I am Y");
}
}
Is it possible to define following in Java:
public interface IGenericRepo<T> {
void add();
void delete();
void attach();
}
public interface IGenericRepo<Book> {
default String bookSpecificMethod(){
return "smthn";
}
}
public class NHGenericRepo<T> implements IGenericRepo<T>{
/* implementation */
}
public class NHUnitOfWork implements UnitOfWork{
#Autowired
public void setBookRepo(NHGenericRepo<Book> bookRepo) {
this.bookRepo= bookRepo;
}
public NHGenericRepo<Book> getBookRepo() {
return bookRepo;
}
private NHGenericRepo<Book> bookRepo;
}
And to be able somewhere in code to have:
{
#Autowired
public void setNhuw(NHUnitOfWork nhuw) {
this.nhuw = nhuw;
}
private NHUnitOfWork nhuw;
/**/
{
String st = this.nhuw.getBookRepo().bookSpecificMethod();
}
}
In .net this is possible by using Extension Method with "this IGenericRepo<Book>" as a first method parameter.
The closest you can come is:
public interface IBookGenericRepo extends IGenericRepo<Book> {
void BookSpecificMethod();
}