Get access to methods in child interface when using Spring autowiring - java

I have an interface A:
public interface Parent {
method1()
}
And an interface B:
public interface Child extends Parent{
method2()
}
Of course there is a class that implements interface B:
public class implements B{
#Override
method1(){
}
#override
method2(){
}
}
Now in a concrete class X, I use Spring autowiring to inject the interface "Parent":
public class X{
#Autowired
Parent parentImpl;
someMethod(){
}
)
But when I use the instance parentImpl, I only get access to method1
How can I get access to method2 in this case?
Thanks.

If you inject the interface Parent, there's no way to access method2() because it is only known in interface Child and not in Parent.
But if you inject a variable of interface Child in class X, then method2() would be accessible.
It is not a problem of Spring or Autowiring but of interfaces and implementations.

Field parentImpl has type Parent, so you can invoke only Parent's methods.
If you want to be able to invoke Child's methods you should #Autowired Child interface

This is not really a Spring question but Java question.
If you know that your concrete class can be of the sub interface you can cast it:
((Child)impl).method2();
You should check that your impl class is of the sub interface
if (impl instance of Child) {
((Child)impl).method2();
}
However, I don't think it is a good practice, what are you trying to achieve?

If you ignore Spring and Autowiring, you will have the same problem.
public class X {
private Parent parentImpl; //this is declared as a Parent.
public void someMethod() {
//This will see parentImpl as type Parent
//because that is how it is declared in this class.
}
)
If you want to be able to see parentImpl as a Child type, then it should be declared as such.

Related

EasyMock - Throwing NullPointerexception due to not accessible to parent class private object(i18n)

A)
Class Parent4{
private I18nUtils i18n;
//-----------Here Nullpointerexception occur----------------
public Parent4(){
SetText(i18n.getText("HELLO");
}
}
B)
Class Parent3 extends Parent4{
private I18nUtils i18n;
}
C)
Class ParentParent2 extends Parent3{
private I18nUtils i18n;
}
D)
Class Parent extends ParentParent2{
private I18nUtils i18n;
}
E)
Class Child extends Parent{
protected method_name(){
//.......DO Something......
}
}
My Test Class:
public testclass{
Class cls = Class.forName("Child");
Object obj = cls.newInstance();
Method method = cls.getDeclaredMethod("method_name",Null);
method.setAccessible(true);
method.invoke(obj, null);
So while creating object of child class it called and invoke all dependency of child class and initialize with mock object and called all parent class and its constructor.
While i18n is set null by default.
1) I tried to accessed with reflection. with the help superClass().getDeclared("i18n"). But eventually it only access to its preceding class only. So it not set the value for Parent5() class.
2) Also I have tried to direct access Parent5 class i18n field.
But when invoking the child class. It will create new instance and same as that it will reset parent5() class i18n as null.
I will answer following one of your comments.
Yes, calling another method instead of super and using a partial mock is a correct solution. EasyMock can't mock super.
Then, if you want to mock a method called by a constructor, that's indeed impossible. EasyMock doesn't provide a way to mock before having the mock.
In both cases, modifying the design will probably improve the design.
I probably handle this situation. I read the Easymock documentation. From there I got some similar case to handle this kind of situtation.
Code here:
Objenesis objenesis = new ObjenesisStd(); // or ObjenesisSerializer
child obj_1 = objenesis.newInstance(child.class);
Method method = obj_1.getClass().getDeclaredMethod("method_name",MessageReceiver.class);
method.setAccessible(true);
method.invoke(obj_1, null);
For my case it working fine. As such I did not able to mock parent field anywhere.
NOTE: I did not have any field dependency of parent class on my child class method. Only I need to mock the (i18n) field so it does not cause "nullpointerexception". But eventually I handle with objensis.

How to call method from a reference send to annotation in java

I have a Interface I and a Abstract Class A , I have My custom annotation MyAnnotation which should take parameter as subclass S of A, now while processing annotation I want to call method of concrete class S
public interface I{
void m1();
}
public abstract class A implements I {
public abstract void m1();
}
public #interface MyAnnotation {
public Class< ? extends A> ref();
public Class< ? super A> ref2();
}
public S extends A{
public void m1() {}
}
I am annotating method like
#MyAnnotation(ref= new XX() ) or #MyAnnotation(ref= XX.class )
#MyAnnotation(ref= new yy() ) or #MyAnnotation(ref= yy.class )
whichever works
//In spring aspect before processing I am getting method annotation and trying to call m1()
annotation.ref().m1() //Error
annotation.ref2().m1() //Error
You can't use new XX() in an annotation. Annotations parameters can use a very specific set of types:
primitive
String
Class
an Enum
another Annotation
an array of any of the above
See this answer.
So to accomplish what you're trying to accomplish, you'd have to use a class.
You would then have to use reflection to create an instance and invoke the method.
Class<?> clazz = annotation.ref();
I instance = (I) cls.getConstructor().newInstance();
instance.m1();
See this answer.
Your classes must all have no-argument constructors, else you'll only be able to instantiate some this way but not others (leading you to have to conditionally branch based on the class).
You can't do that simply like that. You need an instance of the class first.
If your A class is a Spring's bean, you can inject ApplicationContext and get the bean from there. Then you can call a method.
#Autowired
private ApplicationContext context;
void test(MyAnnotation annotation) {
A bean = context.getBean(annotation.ref());
bean.m1();
}

How to use Spring Dependency Injection with class inheritance

I have a parent class called BaseService and I have other services that inherit from BaseService as they all need those methods to do their jobs. As always the methods of the superclass are available inside the subclass... However, when I use #Autowired DI to inject the subclass I am not able to use the methods defined by the parent class, I am only able to use what is defined separately in the subclass. How can I inject the subclass and have it properly instantiate the subclass such that the methods of the parent class are available to me?
Ex. Parent Class
#Service
public class BaseService{
public BooleanExpression combineBools(Predicate predicate, BooleanExpression bool){
BooleanExpression result = runupBool.and(predicate);
return result;
}
}
Ex. Child Class
#Service
public class EqServiceImpl extends BaseService implements EqService{
public EqServiceImpl(){
super();
}
#Override
public Iterable getAllData(Map<String, String> params, Predicate predicate) {
// Some Method Specific to Child Class
}
}
Ex. Controller
#RestController
public class EqController {
#Autowired
EqService eqService
...
}
If I wanted to access the method eqService.combineBools() inside the controller I am unable to. Why is this? How can I fix it?
As DarrenForsythe pointed out I am instantiating with EqService as the type so it would not have all of the methods of the BaseService since it does not extend that class, rather it is the EqServiceImpl that extends that class. Therefore I would need the type to be EqServiceImpl. Without making some other changes #Autowired is not the best choice for DI here.

Calling particular child method from abstract class using custom annotation

I have a abstract class containing run() method and few children classes overriding run method with different implementation. There a custom annotation class also, each child class has this annotation with different value to distinguish each child class. I was to call this run method for each child class from abstract class object using these annotations without using child class name. Is it possible or there some other way to do this?
CODE IS HERE-------
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface CustomAnno {
public String name();
}
public abstract class AbstractClass {
abstract void run();
}
#CustomAnno(name="one")
public class ExtendingClassOne extends AbstractClass {
#Override
void run() {
System.out.println("class one extending");
}
}
#CustomAnno(name="two")
public class ExtendingClassTwo extends AbstractClass {
#Override
void run() {
System.out.println("class two extending");
}
}
So having abstract class and annotation values "one" and "two", can I call run method for each child class without using child class name.
We can use ClassPathScanningCandidateComponentProvider spring library to list all the classes that use a particular kind of annotation. Here annotations can be custom or default one. So putting annotations on all child classes that extend that abstract class can give list of only those child classes only. This solved my problem.

Assign weaker access to method overriding from superclass

I have a Class called Module which has a Method onEnable();
Now i have a class called Config and want to make the onEnable(); method private because there is a predefined acting and a class extending Config should'nt be allowed to change the behaviour.
Is there any way to do this?
Example
class Module{
public void onEnable(){
}
}
A class extending Module which is allowed to use onEnable:
class HelloWorldModule{
#Override
public void onEnable(){
System.out.println("Hello, World!");
}
}
Now the config Class, where i want that onEnable is private so that Classes which extend Config cannot! Override onEnable:
class Config{
#Override
private void onEnable(){
}
}
So NOW, a class named ProgrammConfig which extends Config cannot override onEnable.
However, this is not working because you cannot override a public method to a private method.
By declaring a method as public, you are saying that it should be possible to call said method on every instance of this class, including subclasses. Declaring a method as private in a subclass doesn't make sense, and is thus not allowed.
Now, if you're concerned about subclasses overriding the method, you can declare the method as final to prevent this:
class Config extends Module{
#Override
public final void onEnable(){}
//Whatever
}
You cannot solve this using inheritance. If Config is a subclass of Module, then it must provide all functions of Module with (at most) the same access restrictions. Think of a subclass as a specialized version of the superclass: It can do everything the superclass can, likely more, but never less.
Still you can implement a Config class as desired. Just skip subclassing, and instead use a private field of type Module like so:
class Config {
private Module module;
public Config() {
module = new Module();
}
public int SomeFunctionFromModuleYouWantToExpose() {
return module.SomeFunctionFromModuleYouWantToExpose();
}
// ...
}

Categories

Resources