I have an abstract class that contains common methods:
public abstract class AbstractDAO<T> implements IFindTradeDAO {
#Autowired
private JdbcTemplate jdbcTemplate;
#Override
public List<Trade> findOne(final int eventId) {
return jdbcTemplate.query(getOneQuery(), new Object[]{eventId}, new RowMapper());
}
#Override
public List<Event> getAll() {
return jdbcTemplate.queryForList(getAllQuery(), Event.class);
}
protected abstract String getOneQuery();
protected abstract String getAllQuery();
}
The derived class which provides type specific queries:
#Repository
public class TypeA extends AbstractDAO implements IFindTradeDAO {
private static final String FIND = "sql/findA.sql";
private static final String GET = "sql/getA.sql";
#Override
protected String getOneQuery() {
return FIND;
}
#Override
protected String getAllQuery() {
return GET;
}
#Repository
public class TypeB extends AbstractDAO implements IFindTradeDAO {
private static final String FIND = "sql/findB.sql";
private static final String GET = "sql/getB.sql";
#Override
protected String getOneQuery() {
return FIND;
}
#Override
protected String getAllQuery() {
}
}
Given I have this class structure, I want to invoke the getAllQuery() for all the derived class sql e.g. for TypeA and TypeB on schedule using
org.springframework.scheduling.annotation.Scheduled;
#Component
public class GetAllEvents {
#Scheduled
public void processUnprocessedEvents() {
//invoke getAllQuery for all DAOS and combine results
}
}
I am not quite sure how I can derive a Component that will invoke all? Is there technique or example I can use to achieve this?
I'm not a Java programmer, but in .NET you'd need to put them all into some type of list or array, and call the function on each item.
So maybe create a method called Add(IFindTradeDAO dao) which adds each one to a list. And then call the method on each of those items.
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?
// Domain Class
public class Actor {
private int id;
private String firstName;
private String lastName;
private Date lastUpdate;
// getters and setters
}
// DAO Interface
public interface IDao<T> {
void save(T t);
}
// Concrete Class
public class ActorDao implements IDao {
#Override
public void save(Actor actor) {
// Error: The method save(Actor) of type ActorDao must override or implement a supertype method
}
}
Why is the overridden save() not accepting Actor when IDao has the param as T?
You need to specify what class that T is, like so :
public class ActorDao implements IDao<Actor> {
Let me introduce my code then I will ask a question.
This is just an example. I would like to learn something new if it is possbile.
BaseClass.java
public class BaseClass {
private String baseName;
BaseClass(String baseName){
this.baseName = baseName;
}
//getters and setters
}
MyClass.java
public class MyClass extends BaseClass {
private boolean isTest;
private String name;
MyClass(){
}
MyClass(String baseName){
super(baseName);
this.isTest = true;
}
//getters and setters
}
MyClassController.java
#Controller
public class MyClassController {
#GetMapping(value="/")
#ResponseBody
public String myClassController(#RequestBody MyClass myClass) {
return "index";
}
}
JSON request:
{
"name": "Name for BaseClass"
}
So, I send name e.g.: Name for BaseClass. I want to set this name for variable BaseName in BaseClass through constructor. #RequestBody needs no atribute constructor so I cannot use there this second constructor with arguments. I can handle this e.g. for using additional method:
Additional method in MyClass.java
public MyClass setValues(String baseName){
super(baseName);
this.isTest = true;
return this;
}
New MyController.java
#Controller
public class MyClassController {
#GetMapping(value="/")
#ResponseBody
public String myClassController(#RequestBody MyClass myClass) {
myClass.setValues(myClass.getName());
//more uses for myClass
return "index";
}
}
Is there any better way to do something like this in more "professional" way?
If you're married to the current inheritance structure, you can use HttpMessageConverter to customize the way Spring deserializes HTTP requests.
public class MyClassConverter extends AbstractHttpMessageConverter<MyClass> {
public MyClassConverter() {
super(new MediaType("text", "myClass"));
}
#Override
protected boolean supports(Class<?> clazz) {
return MyClass.class.isAssignableFrom(clazz);
}
#Override
protected MyClass readInternal(Class<? extends MyClass> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
// Deserialize JSON request
MyClass inputObject = new MyClass(name);
return inputObject;
}
#Override
protected void writeInternal(MyClass myClass, HttpOutputMessage outputMessage) {
// Serialize MyClass object
}
}
Detailed example
Although it's not clear I'm assuming name and baseName are meant to be the same value. In that case it might make sense for BaseClass to be an abstract class or interface.
abstract class:
public class MyClass extends BaseClass {
private String name;
// constructors
#Override
String getName() {
return name;
}
// setters
}
public abstract class BaseClass {
abstract String getName();
}
interface:
public class MyClass implements DtoWithName {
private String name;
// constructors
#Override
String getName() {
return name;
}
// setters
}
public interface DtoWithName {
String getName();
}
Also, I can't tell much about your use-case from the given example, but you should read into Composition over inheritance to make sure you're going about it the right way. With DTOs in particular usually simple is best.
public interface A extends C {
String getCh();
String getId();
String getReview();
}
public interface B extends C {
String getCh();
String getId();
String getReview();
}
#Data
#Builder
public class AImpl implements A{
private String ch;
private String id;
private String review;
}
#Data
#Builder
public class BImpl implements B{
private String ch;
private String id;
private String review;
}
so now to use the builders of these I do:
return AImpl.builder()
.ch("ch")
.id("id")
.review("somerview");
For B I do:
return BImpl.builder()
.ch("ch1")
.id("id1")
.review("some new review");
Is there a way where I can make this builder part into a function? I dont like the idea of repeating the same code again. Like where I can pass id channel and review in a function and I can the object?
Disclaimer: I have never really dealt with builders so there might be a really much better option :D
This approach writes builders for each interface individually.
This does require that the interfaces provide a setter method.
Using generics, the methods of the RootBuilder and BaseABuilder return an instance of the ImplABuilder so that the chain can continue properly.
This is a very simple implementation of the Thistype generic which in other languages exists by default. This implementation also relies on casting to the actual Thistype but if you set the generics properly, that shouldnt be an issue.
public class Test
{
public static void main(String[] args)
{
ImplA implA = ImplA
.builder()
.id("id")
.description("description")
.valueA("a")
.build();
}
}
public interface Root
{
String getId();
void setId(String id);
String getDescription();
void setDescription(String description);
}
public class RootBuilder<Thistype extends RootBuilder<Thistype, Instance>, Instance extends Root>
{
protected final Instance object;
RootBuilder(Instance object)
{
this.object = object;
}
public Thistype id(String value)
{
object.setId(value);
return (Thistype)this;
}
public Thistype description(String value)
{
object.setDescription(value);
return (Thistype)this;
}
public Instance build()
{
return object;
}
}
public interface BaseA extends Root
{
String getValueA();
void setValueA(String valueA);
}
public class BaseABuilder<Thistype extends BaseABuilder<Thistype, Instance>, Instance extends BaseA> extends RootBuilder<Thistype, Instance>
{
protected Instance object;
BaseABuilder(Instance object)
{
super(object);
}
public Thistype valueA(String value)
{
object.setValueA(value);
return (Thistype)this;
}
}
public interface BaseB extends Root
{
String getValueB();
void setValueB(String valueB);
}
public interface BaseC extends Root
{
String getValueC();
void setValueC(String valueC);
}
public final class ImplA implements BaseA
{
private String id;
private String description;
private String valueA;
private ImplA() { }
public static ImplABuilder builder()
{
return new ImplABuilder(new ImplA());
}
private static class ImplABuilder extends BaseABuilder<ImplABuilder, ImplA> // assuming ImplA is final
{
ImplABuilder(ImplA object)
{
super(object);
}
// additional methods for ImplA class
}
}
I am trying to use inheritence and generics to create my application, but it doesn't seem to work the way I expect it to. I'll show you what I mean (TL;DR at the bottom):
public interface IModel extends Serializable {
public int save();
public void update();
public void delete();
}
// <T> is a JPA annotated entity/class
#SuppressWarnings("serial")
public abstract class Model<T> implements IModel {
private final Repository<T> _repository;
protected T _entity;
public Model(T entity, Repository<T> repository) {
this._entity = entity;
this._repository = repository;
}
public int save() {
return _repository.save(_entity);
}
...
}
This is implemented in for example my AccountModel, which is a Model with generic Account (which is a JPA entity) and which implements IAccount.
public class AccountModel extends Model<Account> implements IAccount {
private static final AccountRepository REPOSITORY = new AccountRepository();
public AccountModel(Account entity) {
super(entity, REPOSITORY);
}
// Method implementations...
}
My generic Repository looks like this:
public abstract class Repository<T> implements Serializable {
private static SessionFactory SESSION_FACTORY;
private final Class<T> _repositoryClass;
private static boolean _initiated = false;
public Repository(Class<T> repositoryClass) {
if (!Repository._initiated)
setup();
this._repositoryClass = repositoryClass;
}
private void setup() {
// logics
Repository._initiated = true;
}
public final Model<T> getById(int id) {
Session session = SESSION_FACTORY.openSession();
try {
session.beginTransaction();
T t = session.get(_repositoryClass, id);
return new Model<T>(t, this); // As suggested by #Vlad
}
finally {
session.close();
}
}
}
The account implementation of this abstract Repository is:
public class AccountRepository extends Repository<Account> {
public AccountRepository() {
super(Account.class);
}
public Model<Account> getByEmail(String emailAddress) {...}
}
So far so good, this is all working as expected. But I cannot use a Model<T> as a TModel.
TL;DR
I would like use the following line of code:
AccountModel account = new AccountRepository().getById(1);
Since AccountModel inherits Model<Account> and new AccountRepository().getById() always returns Model<Account> I expect this to work, but it doesn't.
What am I missing?