Is it possible to forbid annotation inheritance? - java

I have a controller superclass and its subclass:
public class SuperController {
#Resource
private A resourceA;
}
public class SubController extends SuperController {
#Resource
private B resourceB;
}
I don't use resourceA field in Subcontroller, but Subcontroller acts as SuperController and has the same methods. So how can I forbit the inheritance of #Resource annotation, just like that:
public class SuperController {
**private** #Resource
private A resourceA;
}

Sounds like you need a common abstract class if the sub-class doesn't use some of the fields of the parent class.
public abstract class AbstractController {
// common fields.
// common methods.
}
public class SuperController extends AbstractController {
#Resource
private A resourceA;
}
public class SubController extends AbstractController {
#Resource
private B resourceB;
}

Related

How to get the class of the genereric parameter of a Interface from the interface

I have this Interface:
public interface Test<T> {
default Class<?> getT() {
return T.getClass(); < --error
}
}
next i have a class that implements it:
static class ItemService implements Test<Item>{
}
And i want to get the 'Item' class from the 'ItemService' class
static ItemService service = new ItemService();
private static void k() {
System.out.println(service.getT());
}
Now one way to do it is this:
public interface Test<T> {
default Class<?> getT() {
return Type.type;
}
class Type {
public static Class<?> type;
}
}
Service:
static class ItemService implements Test<Item> {
public ItemService() {
Type.type = Item.class;
}
}
And it works fine but there is a problem,
When another class implement the interface:
static class OrderService implements Test<Order> {
public OrderService() {
Type.type = Order.class;
}
}
And i try:
static ItemService service = new ItemService();
static OrderService orderservice = new OrderService();
private static void k() {
System.out.println(service.getT());
}
I get the Order class and not the Item class
How can i make it work?
Classes inside interfaces are static, You can remove the default from the function and every class will need to implement this. example:
public interface Test<T> {
public Class<T> getT();
}
static class ItemService implements Test<Item> {
public Class<Item> getT() {return Item.class;}
}
static class OrderService implements Test<Order>{
public Class<Order> getT() {return Order.class;}
}
An alternative could be an abstract class.
public interface Test<T> {
public Class<T> getT();
}
abstract class AbstractTest<T> implements Test<T> {
private final Class<T> type;
AbstractItemService(Class<T> type) { this.type = type }
public Class<T> getT() {return type;}
}
class ItemService extends AbstractTest<Item> {
ItemService() { super(Item.class); }
// implement other things
}
class OrderService extends AbstractTest<Order>{
OrderService() { super(Order.class); }
// implement other things
}
Here is another option, if your implementation has an instance of T.
interface Test<T>{
T getT();
default Class<?> getClassOfT(){
return getT().getClass();
}
}

How to mock all the classes that implement the same interface while using autowire for Set in spring?

Having the following classes :
public class A {
#Autowired
private Set<IClient> clients;
}
public class B implements IClient { }
public class C implements IClient { }
#RunWith(MockitoJUnitRunner.class)
public class Atest {
#InjectMocks
A a;
#Mock
IClient clients;
}
How I can use mocks for the Set of interfaces that will include both class B and C?
Use constructor injection insted of field injection, then create two mocks, put them in a set, and call your constructor with that set. For example:
public class Atest {
private A a;
#Mock
private IClient mockAClient;
#Mock
private IClient mockBClient;
#Before
public void prepare() {
a = new A(new HashSet<>(Arrays.asList(mockAClient, mockBClient));
}
}

Using Generics and extending Abstract classes

I've researched this issue a great deal, but have not been very successful in finding a solution close to my situation. I apologize if I am redundant.
Anyway, I am new to generics and so I'm not entirely clear on the syntax. But here is my situation:
I have an Interface (let's call it IService) and an implementation (ServiceImpl). The implementation class has an abstract method that is to be overridden by an extending class (ServiceExt).
I have an abstract bean (let's call it AbstractBean) which has a few fields and is meant to be extended by another bean (BeanExt) in order to add some more fields.
Ok, now that the situation is laid out, here is my abbreviated code:
Interface:
public interface IService <B extends AbstractBean> {
B method(B bean, Object data) throws Exception;
}
Implementation:
public abstract class ServiceImpl <B extends AbstractBean> implements IService<B> {
public abstract B method(B bean, Object data);
}
Abstract Bean:
public abstract class AbstractBean{
private String fname;
private String lname;
[getters and setters]
}
Extended Bean:
public class BeanExt extends AbstractBean{
private String phoneNum;
[getter and setter]
}
Extending Class: aka Class giving me issues
public class ServiceExt <B extends AbstractBean> extends ServiceImpl <B> {
#Override
public <B> BeanExt method(Bbean, Object data) {
if(beaninstanceof AbstractBean){
BeanExt beanExt = (BeanExt) session;
beanExt.setFname("John");
beanExt.setLname("Doe");
beanExt.setPhoneNum("123456789");
return beanExt;
}else{
return null;
}
}
}
Ok, so now eclipse is giving me all kinds of non-descriptive issues and I don't know what to do. I've played around with the extending class methods a ton but have not found success. Above is how it looks after my last tinkering.
The issues currently presented by my IDE within the class ServiceExt are:
The method method(B, Object) of type ServiceImpl must override or implement a supertype method
The type ServiceExt must implement the inherited abstract method [some other non-abstract method in the interface]
Edit: For further clarification, what I am ultimately trying to do is:
Create a bean which extends the AbstractBean and add another field
Define the abstract method inside the class ServiceExt
Within the method, set some values in the extended bean
Return the extended bean with its new values
Update - I've taken all of your input and the changes are reflected below. The issue currently presented by my IDE within the class ServiceExt is:
The type ServiceExt must implement the inherited abstract method [some other non-abstract method in the interface]
Interface:
public interface IService <B extends AbstractBean> {
B method(B bean, Object data) throws Exception;
B otherMethod(HttpServletRequest request) throws Exception;
}
Implementation:
public abstract class ServiceImpl <B extends AbstractBean> implements IService<B> {
public abstract B method(B bean, Object data);
#Override
public final B otherMethod(HttpServletRequest request) {
return [something];
}
}
Abstract Bean:
public abstract class AbstractBean{
private String fname;
private String lname;
[getters and setters]
}
Extended Bean:
public class BeanExt extends AbstractBean{
private String phoneNum;
[getter and setter]
}
Extending Class: aka Class giving me issues
public class ServiceExt extends ServiceImpl <BeanExt> {
#Override
public BeanExt method(BeanExt bean, Object data) {
BeanExt beanExt = (BeanExt) session;
beanExt.setFname("John");
beanExt.setLname("Doe");
beanExt.setPhoneNum("123456789");
return beanExt;
}
}
You are not really overriding the method in super class. Here's the overridden method:
#Override
public BeanExt method(BeanExt bean, Object data) {
BeanExt beanExt = (BeanExt) session;
beanExt.setFname("John");
beanExt.setLname("Doe");
beanExt.setPhoneNum("123456789");
return beanExt;
}
Since you're extending from ServiceImpl<BeanExt>, the type parameter B is replaced with BeanExt type, so does the return type and parameter of the method.
Also note that I've removed the instanceof check, as it is really not needed. bean will always be an instance of AbstractBean, because that is enforced by the bound you gave to the type parameter declaration of ServiceImpl class.
I did not entirely understand what you're trying to do, but is this acceptable/working?
public class ServiceExt <B extends BeanExt> extends ServiceImpl <B> {
#Override
public B method(B bean, Object data) {
bean.setFname("John");
bean.setLname("Doe");
bean.setPhoneNum("123456789");
return bean;
}
}
I just corrected all the errors:
interface IService <B extends AbstractBean> {
B method(B bean, Object data) throws Exception;
}
abstract class ServiceImpl <B extends AbstractBean> implements IService<B> {
public abstract B method(B bean, Object data);
}
abstract class AbstractBean{
String fname;
String lname;
}
class BeanExt extends AbstractBean {
String phoneNum;
}
class ServiceExt <B extends AbstractBean> extends ServiceImpl <B> {
#Override public B method(B bean, Object data) {
if (bean instanceof BeanExt) {
BeanExt beanExt = (BeanExt) bean;
beanExt.fname = "John";
beanExt.lname = "Doe";
beanExt.phoneNum = "123456789";
return bean;
}else{
return null;
}
}
}

#Inject in abstract class based on subclass

let imagine I have per entity a repository class (spring data jpa) for database access and a service class. The dependencies are managed by spring framework. Every service method does in most cases the same, so there is mainly code duplication:
public class NewsService {
#Inject
private NewsRepository newsRepository;
public void add(News news) {
// do some validation
newsRepository.save(news);
}
}
public class UserService {
#Inject
private UserRepository userRepository;
public void add(User user) {
// do some validation
userRepository.save(user);
}
}
Now i thought about creating an abstract class like this:
public abstract class AbstractService<T> {
private UnknownRepository unknownRepository;
public void add(T entity) {
// do some validation
unknownRepository.save(entity);
}
}
public class NewsService extends AbstractService<News> {
}
public class UserService extends AbstractService<User> {
}
My problem: How can i overwrite the repository used inside the abstract class based on my entities?
You can replace the UnknownRepository field with an abstract method and a type parameter:
// R is the type of the repository
public abstract class AbstractService<T,R extends BaseRepository> {
protected abstract R getRepository();
public void add(T entity) {
getRepository().save(entity);
}
}
And inject the specific repository to the implementations of this class:
public class NewsService extends AbstractService<News, NewsRepository> {
#Inject private NewsRepository newsRepository;
#Override
public NewsRepository getRepository() {
return newsRepository;
}
// the inherited add() method works now
}

Inject a bean as a constructor argument in a child class

How to inject a bean as a constructor argument in a child class when the parent class constructor takes a list of that type.
#Service
public class Parent{
private List<MyObject> myObjectList;
public Parent(List<MyObject> myObjectList){
this.myObjectList = myObjectList;
}
}
#Service
public class Child extends Parent {
#Autowired
public Child(MyObject myObject){
super( ???? );
}
}
What about this ?
super(Arrays.asList(new MyObject[] {myObject}));

Categories