How to use class generic in autowiring interface generic? - java

im trying to realize simple database save logic using java generics in springboot. I create an utility interface with generic which I extend in another interface and implement in class. in classes which use database access I want extend an abstract class with generic which autowires my utility interface. is there any chance to realize this logic?
Main interface:
public interface UtilityService<T> {
T add(T entity);
T getById(long id);
T removeById(long id);
List<T> index();
}
–
public interface FoodService extends UtilityService<Food> {
Food changeQuantity(long id, int quantity);
}
–
Logic I want to realize:
#Component
public abstract class DatabaseSaver<C> {
private UtilityService<C> saver;
#Autowired
public void setSaver (UtilityService<C> saver) {
this.saver = saver;
}
public void save(C c){
saver.add(c);
}
}
–
public class SimpleClass extends DatabaseSaver<Food>{
public void dosmth(Food f){
super.save(f);
}
}

Related

Java Generics initialization of child class in base class

I'm pretty new to java and not particularly sure how to initialize a generic type / child class from the 'base' class.
Essentially I have a bunch of classes that extend the abstract class BaseClass that need to be initialized and added to the instance Map if a key is not present.
The child class is re-used multiple times but is dynamically created based on the key parameter.
I would like to avoid reflection and don't mind changing the template if it's not 'the Java way'.
What I currently have:
public abstract class BaseClass<T> {
protected Map<String, T> instance = new HashMap<String, T>();
public T Get(String key) {
if (this.instance.containsKey(key)) {
return this.instance.get(key);
}
T item = new T(key); // Obviously this line errors but you get the idea
instance.put(key, item);
return item;
}
}
// Example top class which extends my base class
public class TopClass extends BaseClass<TopClass> {
public TopClass(String key) {
// Do unique initialization stuff
}
}
Since generic types are erased at runtime, you cannot do this. You can instead use a Class variable as follows:
public T Get(Class<T> clazz, String key) throws Exception {
if (this.instance.containsKey(key)) {
return this.instance.get(key);
}
T item = clazz.getDeclaredConstructor(String.class).newInstance(key);
instance.put(key, item);
return item;
}
I have another approach to this.
Have an interface MyInterface.
public interface MyIinterface{
public void doSomething();
}
Create an many implementations of this interface.
#Component
public class MyImplementation1 implements MyInterface{
#Override
public void doSomething(){
}
}
Use spring core jars in the dependency.
Annotate all the implementations with #Component.
#Component
public class MyImplementation1 implements MyInterface{
.
.
Have a method in some Util class that will get you the implementation based on a string key.
public static MyInterface getImplementation(String name){
ApplicationContext context;
return context.getBeanByName(name);
}

JAVA: Static Field in multiple classes + common interface

Is there a way to setup the following construct in JAVA:
having a common interface or base class
having a static public field declared by the common interface
each model implementing the common interface should have its own static field (not one shared instance for all models)
Detailed explanation:
I'm working with ORMLite and I need to refresh the ForeignCollections of my models after deserialization. For doing this I need to have a reference to my DAO from the models, which I don't want to.
So, I came up with the following concept:
keep a static field in each of the models of the following Interface:
public interface SerializableObserver {
void onAfterDeserialization(Object object);
}
in my implementation of private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException after reading in all ivars i'am calling the onAfterDeserialization-Method of the static field i'am holding in the model.
In the Dao, I'm setting the static field of the model. So when the deserialization is finished, a method in my Dao is called. Where i can finally refresh the ForeignCollection so it's still valid after deserialization.
So what I'm looking for is some sort of way to make this whole approach a bit more generic so, I don't have to implement this behavior for all of my 20 Models.
And finally, this is going to be an Android-App. so no fancy Java-8 things.
I would use another class that maps Model classes to SerializableObserver implementations.
For example,
DeserializerMap:
public enum DeserializerMap {
INSTANCE;
private Map<Class<? extends Model>, SerializableObserver> modelObserverMap = new HashMap<>();
public void registerSerializableObserver(Class<? extends Model> modelClass, SerializableObserver serializableObserver) {
modelObserverMap.put( modelClass, serializableObserver );
}
public void deregisterSerializableObserver(Class<? extends Model> modelClass) {
modelObserverMap.remove( modelClass );
}
public SerializableObserver getSerializableObserver(Class<? extends Model> modelClass){
return modelObserverMap.get( modelClass );
}
}
Model class:
public class ModelClass implements Model{
private int id;
public ModelClass(int id) {
this.id = id;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{
ois.defaultReadObject();
DeserializerMap.INSTANCE.getSerializableObserver( this.getClass() ).
onAfterDeserialization( this );
}
}
The "Model" interface just extends Serializable and is used in DeserializerMap, but you can just get rid of the interface and use Class<? extends Object> instead of Class<? extends Model> in DeserializerMap,
Model:
public interface Model extends Serializable{
}
DAO Class:
public class DAOClass {
public DAOClass(){
SerializableObserver serializableObserver = new SerializableObserver() {
#Override
public void onAfterDeserialization(Object object) {
System.out.println("After deserialization");
anotherMethod();
}
};
DeserializerMap.INSTANCE.registerSerializableObserver( ModelClass.class, serializableObserver );
}
public void anotherMethod(){
System.out.println("another method");
}
}
if you don't want to do anything additional than just call DAOClass method then you can map ModelClass with DAOClass classes, but I would recommend using DAO just for communicating with your persistence system and register mappings in your main class and not in DAOClass constructor.
Without understanding the details I can offer the following:
Use an Interface to define commonly required behaviour and then a generic abstract base class to define a common structure is something you should consider.

Generic design for custom Table

Forgive me if there are syntax problems. The goal of this is not to get the code perfect but to get the design.
I have an interface ITable<T>
public interface ITable<T> {
public Collection<T> getEntries();
public void add(CustomObj value);
public Collection<CustomObj> getCustomObjects();
}
that is used by two classes:
TableOne<CustomObj> and TableTwo<Pair<CustomObj, CustomObj>>
Then I have an interface that applies these tables using a function
public interface ITableFunction<T> {
public abstract Collection<ITable<?>> execute(Collection<ITable<T>> tables);
}
My dilemma occurs when I try to create a generic Abstract class
public abstract class AbstractTableFunctionCombined<T> implements ITableFunction<T>{
private boolean someBool;
public AbstractTableFunctionCombined(boolean someBool){
this.someBool = someBool;
}
#Override
public Collection<ITable<?>> execute(Collection<ITable<T>> tables){
// What i would like to do, but can't right now:
ITable<T> combinedTable;
if (someBool){
combinedTable = new TableOne();
} else {
combinedTable = new TableTwo();
}
for(ITable<T> table : tables){
combinedTable.addAll(table.getCustomObjects());
}
for(T entry : table.getEntries()){
execute(entry);
}
}
public abstract void execute(T entry);
}
The issue is that I can't guarantee that the type T is the same as the table that I'm trying to instantiate. I thought I had to create some kind of relationship from the Pair<CustomObj, CustomObj> and the regular CustomObj. I tried creating a Entry interface that these both would use, and having ITable<T> be ITable<T extends Entry> but again this runs into the same problem.
I also thought that maybe I can make the TableOne and TableTwo classes use the same Generic i.e. TableTwo<T> implements ITable<T>, but TableTwo has a hard restriction of using Pair<CustomObj, CustomObj>.
Would I have to create two separate classes: AbstractTableFunctionOne<CustomObj> and AbstractTableFunctionTwo<Pair<CustomObj, CustomObj>> ? I would like to avoid this as it would be a lot of duplicated code.
Or am I over forcing this Object oriented design? Should TableOne and TableTwo not even implement the same interface?
This Interface has some issus:
public interface ITableFunction {
public abstract execute(Collection<ITable<T>> tables);
}
You need a return type and a Generic:
public interface ITableFunction<T> {
public abstract void execute(Collection<ITable<T>> tables);
}
and return type of Method
public Collection<ITable<T>> execute(Collection<ITable<T>> tables){
..
should be Collection OR void in declaration AND implementation.

Creating a generic class, with type parameter limited to a certain superclass

I'm trying to create a "CRUD manager" class, performing database operations of objects that extend an abstract superclass I created. The abstract class is fairly simple:
public abstract class IndexedEntity() {
protected Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
if(id == null)
this.id = id;
else throw new UnsupportedOperationException
("The ID cannot be changed once it was set.");
}
}
Now I have a couple of classes that extend this IndexedEntity, and these classes represent my business entities: Car, Customer, Lease
Instead of creating a CRUD manager for each business entity, I figured I'd try creating a common CRUD class that supports their common superclass.
How do I create a generic class, that takes a type parameter when being constructed, and that type parameter is limited to certain types - those who inherit from IndexedEntity?
Something like:
public interface ICrudManager<IndexedEntity> {
public void add(IndexedEntity e);
public IndexedEntity get(long id);
public void update(IndexedEntity e);
public void delete(IndexedEntity e);
public List<IndexedEntity> getAll();
}
Is it possible in Java? Or, is there anything wrong about this idea / do think it's an acceptable design choice?
(I might abandon it first thing tomorrow because it may be too difficult to generalize a lot of behavior, but at the moment I'm curious how can it be done.
Use Bounded Type Parameters
public interface ICrudManager<T extends IndexedEntity> {
public void add(T e);
public IndexedEntity get(long id);
public void update(T e);
public void delete(T e);
public List<T> getAll();
}
and You can create objects like ICrudManager<Car> carManager = new CrudManagerImpl<Car>();
public interface MyInterface<T extends MyClass>
You can either change the interface line to public <T> interface ICrudManager <T exdents IndexedEntity> which will result in an compiler error if you try to insert a class that doesn't match.
If you want your system to be more dynamically you can you an abstract class with an initializer that tests the type during execution.
public abstract <T> class {
{
if(!T instanceof IndexedEntity)
throw new TypeException()
}
}

Java Inheritance and Generics

I have some classes that look like this:
MODEL
public abstract class BaseEntity<O extends Object> { ... }
public class Person extends BaseEntity<Person> { ... }
COMMAND
public abstract class BaseCommand<BE extends BaseEntity<BE>> { ... }
public class PersonCommand extends BaseCommand<Person> { ... }
SERVICE
public interface BaseService<BE extends BaseEntity<BE>> {
public BE create(BaseCommand<BE> command);
}
public interface PersonService extends BaseService<Person> { ... }
SERVICE IMPL
public abstract class BaseServiceImpl<BE extends BaseEntity<BE>> implements BaseService<BE> { }
public class PersonServiceImpl extends BaseServiceImpl<Person> implements PersonService {
public Person create(PersonCommand personCommand) { ... }
}
The PersonServiceImpl class won't compile. It's not recognizing that the create() method is implementing the create() method from the BaseService interface. Can anyone tell why PersonCommand isn't being recognized as a BaseCommand<BE> (in the parameter list)?
When overriding, method parameters are not covariant (that is, subclasses have to accept a type that the superclass also accepts, not anything narrower).
This is because people can use your PersonServiceImpl via the PersonService interface, which will accept an argument of type BaseCommand<Person> that is not necessarily a PersonCommand (imagine if you created a second class that extended BaseCommand<Person>).
If you make your method take a parameter of type BaseCommand<Person>, your code should compile correctly.

Categories