I have a rather complicated structure and it does not work properly. This is what I did:
public interface ResultServiceHolder { <M, ID extends Serializable, BO extends BusinessObject<M, ID>> ResultService<M, ID, BO> getService(); } public enum ResultTypes implements ResultServiceHolder { RESULT_TYPE_ONE { @Override public ResultOneService getService() { //unchecked conversion? return serviceInitializer.getResultOneService(); } }, RESULT_TYPE_TWO { @Override public ResultTwoService getService() { //unchecked conversion? return serviceInitializer.getResultTwoService(); } }, RESULT_TYPE_THREE { @Override public ResultThreeService getService() { //unchecked conversion? return serviceInitializer.getResultThreeService(); } }; protected ServiceInitializer serviceInitializer; protected void setServiceInitializer(ServiceInitializer serviceInitializer) { this.serviceInitializer = serviceInitializer; } @Component public static class ServiceInitializer { @Autowired private ResultOneService resultOneService; @Autowired private ResultTwoService resultTwoService; @Autowired private ResultThreeService resultThreeService; @PostConstruct public void init() { for(ResultTypes resultType : ResultTypes.values()) { resultType.setServiceInitializer(this); } } //getters } }
The goal was to summarize an enumeration-based call, but rather just the ability to iterate over an array of enumerations.
for(ResultServiceHolder resultServiceHolder : ResultTypes.values()) { if(resultServiceHolder.equals(post.getPostResultTypeCode())) { return resultServiceHolder.getService().createResultSearchCriteriaResponse(postId); } }
And it works great and dandy. However, if I said
ResultTypes.RESULT_TYPE_ONE.getService().getRepository()
Then it is BaseRepository<Object, Serializable> , and not BaseRepository<ResultTypeOne, Long> . The resultTypeHolder.getService() method returns ResultService<M, ID, BO> , but in the end it becomes Object and Serializable .
What am I doing wrong? How to save common parameter types?
I would like to add that yes, I understand that the problem is somewhere with uncontrolled casting. But services are defined as
public interface ResultTypeOneService extends ResultService<ResultTypeOne, Long, ResultTypeOneBO> { }
And I don't know why types are not inferred.
EDIT . Technically this works if I explicitly do them:
ResultTypes.RESULT_TYPE_ONE.<ResultTypeOne, Long, ResultTypeOneBO>getService().getRepository()
But it has to be automatic, why doesn't it work automatically? Should I provide it with some kind of object that contains a type? Why is return type not enough for this?
EDIT2 : Superclass ResultTypeOne equals
@SuppressWarnings("serial") @EntityListeners(EntityListener.class) @MappedSuperclass public abstract class EntityBase implements Serializable {
But it does not appear anywhere within.
EDIT3 : Thanks a lot @Radiodef! The theoretical solution was as follows: and will work just fine:
public interface ResultServiceHolder<M, ID extends Serializable, BO extends BusinessObject<M, ID>> { ResultService<M, ID, BO> getService(); } public abstract class ResultTypes<M, ID extends Serializable, BO extends BusinessObject<M, ID>> implements ResultServiceHolder<M, ID, BO> { public static ResultTypes<?, ?, ?>[] values() { return new ResultTypes<?, ?, ?>[] {RESULT_ONE, RESULT_TWO, RESULT_THREE}; } public static final ResultTypes<ResultOne, Long, ResultOneBO> RESULT_ONE = new ResultTypes<ResultOne, Long, ResultOneBO>("Result One") { @Override public ResultOneService getService() { return serviceInitializer.resultOneService; } }; public static final ResultTypes<ResultTwo, Long, ResultTwoBO> RESULT_TWO = new ResultTypes<ResultTwo, Long, ResultTwoBO>("Result Two") { @Override public ResultTwoService getService() { return serviceInitializer.resultTwoService; } }; public static final ResultTypes<ResultThree, Long, ResultThreeBO> RESULT_THREE = new ResultTypes<ResultThree, Long, ResultThreeBO>("Result Three") { @Override public ResultThreeService getService() { return serviceInitializer.resultThreeService; } }; protected String name; protected ServiceInitializer serviceInitializer; private ResultTypes(String name) { this.name = name; } protected void setServiceInitializer(ServiceInitializer serviceInitializer) { this.serviceInitializer = serviceInitializer; } @Component static class ServiceInitializer { @Autowired private ResultOneService resultOneService; @Autowired private ResultTwoService resultTwoService; @Autowired private ResultThreeService resultThreeService; @PostConstruct public void init() { for (ResultTypes resultType : ResultTypes.values()) { resultType.setServiceInitializer(this); } } } }
I think, because of how long the solution will be, I stick to the enum approach and just accept this loss of boundaries. I lose more by adding my own implementation of values() than I get from adhering to these boundaries. However, this is an interesting theoretical exercise, and thanks again for your help.