I am working on some service code that is using JSR-303 validation to test a request object. What I would like to do is throw a custom RuntimeException when the validation fails containing the Set of ConstraintViolations.
All of my request objects ultimately implement the same interface, lets call it Request. I think have an AbstractRequest that implements Request, and then a bunch of implementations of AbstractRequest, for instance MyRequest.
For the exception, what I am trying to do is something like:
public class RequestViolationException extends RuntimeException {
private Set<ConstraintViolation<? extends Request>> violations;
public <T extends Request> RequestViolationException(Set<ConstraintViolation<T>> newViolations) {
this.violations = newViolations;
}
}
And I am calling it like:
Set<ConstraintViolation<MyRequest>> violations = validator.validate(myRequest);
if (violations.size() > 0) {
throw new RequestViolationException(violations);
}
But this is not working. I have tried a few other variations on this theme, like making the constructor take a Set<ConstraintViolation<? extends Request>>, making violations a Set<ContraintViolation<Message>>, making violations a Set<ContraintViolation<Message>>, setting it to a HashSet<ContraintViolation<Message>> then iterating of newViolations, etc. Each has proven to give a myriad of different compiler errors. How can I have a Set of ContraintViolation<T> where <T> is some extension of Request and have it work?
You can't extend an exception with generics:
http://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#cannotCatch
Actually #JGilardi is right, your constructor accepts <T extends Request> but you are trying to assign it to instance variable violations which is <? extends Request> which is illegal. Please refer to
http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html for a detailed explanation.
To parameterize the instance variable with the same <T extends Request> you have to parameterize the class which again extends RuntimeException and thus not parameterizable. :(
Related
Small question regarding Java Spring Webflux and type incompatibility issues please.
I have a very simple Spring Webflux application, where I declare a common interface for all my repositories to save a pojo:
public interface MyInterface {
Mono<MyPojo> save(MyPojo myPojo);
}
Here are example of a concrete implementation, for instance, Redis:
#Repository("redis")
public class MyRedisRepository implements MyInterface {
private final ReactiveRedisOperations<String, String> reactiveRedisOperations;
public MyRedisRepository(ReactiveRedisOperations<String, String> reactiveRedisOperations) {
this.reactiveRedisOperations = reactiveRedisOperations;
}
#Override
public Mono<MyPojo> save(MyPojo myPojo) {
return reactiveRedisOperations.opsForValue().set("someKey", "someValue").map(__ -> myPojo);
}
}
And now an example with Elastic.
#Repository("elastic")
public interface MyElasticRepository extends ReactiveElasticsearchRepository<MyPojo, String>, MyInterface {
}
Please note, the important point is that some are regular classes (like Redis) which needs to implement the save method.
On the other hand, some are interface which implements Reactive___Repository<MyPojo, String> (which already have a save method)
When trying to compile, I am faced with this issue:
types question.MyInterface and org.springframework.data.repository.reactive.ReactiveCrudRepository<question.MyPojo,java.lang.String> are incompatible;
This is a bit strange to me, as my intention is just to have all the repositories under a common MyInterface , with a save method.
May I ask why I am facing this issue, and most of all, how to resolve this (keeping the MyInterface ) please?
Thank you
The return type and parameter type of the save method defined on the two interfaces are different, which makes them incompatible.
The ReactiveCrudRepository that ReactiveElasticsearchRepository extends, specifies that types derived from MyPojo can be passed to and will be returned from the save method.
In your custom interface you limit the passed argument and return type strictly to MyPojo. So the compiler recognizes there is no way to determine which save method is called at runtime and complains.
Try adjusting the return type of your interface to the following and adjusting your implementations:
public interface MyInterface<T extends MyPojo> {
Mono<T> save(T myPojo);
}
I need help with Java Generics.
My model is: I have some classes that extends a Dto (Data Transfer Object) and some classes that extends Entity (The model of my object to DB).
I have
interface Mapper<D extends Dto, E extends Entity>{
//Convert a Entity to Dto.
D toDto(E entity);
And I have some classes that implements this interface (i.e PersonMapper, BookMapper and so far and so on).
#Component
public class PersonMapper implements Mapper<PersonDto, PersonEntity> {
//implementation
}
#Component
public class BookMapper implements Mapper<BookDto, BookEntity> {
//implementation
}
What I want to do is to use Factory Pattern in order to select at runtime my Mapper, that depends from a String that I pass in input.
#Autowired
private PersonMapper personMapper;
#Autowired
private BookMapper bookMapper;
public <D extends Dto, E extends Entity> Mapper<D, E> selectMapper(String entity){
if ("Person".equalsIgnoreCase(entity))
return personMapper;
if("Book".equalsIgnoreCase(entity))
return bookMapper;
...
}
With this situation I have the following compile error:
Type mismatch: cannot convert from PersonMapper to Mapper<D,E>
My solutions:
1)
return (Mapper<D, E>) personMapper;
but I have a Warning:
Type Safety: `Unchecked class from personMapper to Mapper<D,H>`
2)
Using WildCard and castingb
public Mapper<Dto, Entity> selectMapper(String entity){
Mapper<? extends Dto, ? extends Entity> toReturn = null;
if ("Person".equalsIgnoreCase(entity))
toReturn = personMapper;
else if("Book".equalsIgnoreCase(entity))
toReturn = bookMapper;
...
return (Mapper<Dto, Entity>) toReturn;
}
But in this case but I have another time a Warning:
Type safety: Unchecked cast from Mapper<capture#29-of ? extends Dto,capture#30-of ? extends Entity> to Mapper<Dto,Entity>
It works but it doesn't seems to be a clean solution
3) Using wildcard as return type:
public Mapper<? extends Dto, ? extends HistoryEntity> selectMapper(String entity)
but you know, using wildcard as return type is not recommended at all and also doesn't help me because I would like to use this mapper and call mapper.toDto ensuring that the return type is an something that extends Dto.
====================================================================
I don't explain why If I write a class constructor like that
public Service<D extends Dto, E extends Entity>{
public Service(Mapper<D,E> mapper){
this.mapper = mapper;
}
}
and than I inject (for example) bookMapper it works.
If, instead, the Mapper<D,E> is in return type I cannot do such a kind of operation.
====================================================================
The help that I ask to you is:
how can I write a solution using clean code principles (avoiding compile warnings, sonarlint issue etc.) in order to implement this kind of logic?
Thank you very much, I appreciate a lot if you dedicate a little bit of your time helping me to solve my problem.
Those vars (D and E) about the caller and not about your code. The D and E are decided by the caller, so there is absolutely no way to guarantee that PersonDTO fits.
Make that Mapper<? extends DTO, ? extends Entity> (and no variables), and given that those are already the lower bounds, just Mapper<?, ?> - that'll work, you can write your return statements without any casts and without compiler errors or warnings.
Of course, it means the caller has a mostly useless type.
Generics are entirely 'compile time / write time' based. The JVM (java.exe) has no idea what generics are, and in fact most of them don't survive the compilation process. The one and only purpose of generics is to make the compiler flag incorrect code and avoid some casting, that is all.
The nature of turning that string into a Mapper is entirely runtime.
Ergo, if Mapper<?, ?> isn't sufficient, what you want isn't possible. You'd need to write compile/write-time checkable stuff, so the moment you use a String, it's impossible. For example, a method getPersonMapper() can of course return a Mapper<PersonDTO, PersonEntity>, no problem.
More generally (heh) it sounds like you're badly reinventing various wheels here. Look at tutorials of JDBI, JOOQ, and Hibernate to get some ideas about how java code is commonly written to interact with databases.
Factory Pattern is pattern that assemble or create something by factory methods, in you case what you need is just to get corresponding mapper by name, so there is a simple way to do that since the mapper beans are autowired, adding String getName() to Mapper interface then implements it for earch implementation, e.g. in BookMapper
#Override
public String getName() { return "Book"; }
use mapper name as key and mapper bean as value to store mapper beans in a map, then you can retrieve it by its name:
#Service
public class SimpleService {
private BookMapper bookMapper;
private PersonMapper personMapper;
private Map<String, Mapper<? extends DTO, ? extends Entity>> mappers = new HashMap<>();
public SimpleService(BookMapper bookMapper, PersonMapper personMapper) {
this.bookMapper = bookMapper;
this.personMapper = personMapper;
mappers.put(bookMapper.getName(), bookMapper);
mappers.put(personMapper.getName(), personMapper);
}
public Mapper<? extends DTO, ? extends Entity> getMapperByName(String mapperName) {
return mappers.get(mapperName);
}
}
and you can cast it to corresponding mapper without warning.
PersonMapper p = (PersonMapper) simpleService.getMapperByName("Person");
or you can put different mapper in their service and use the service to handle you biz likes codes below, after all, you need specified mappers to do specified operations:
if(personThings){
personService.doSomeThing();
}
if(bookThings){
bookService.doSomething();
}
I'm working with JSON data and converting it into Java POJO class, then I built an interface like this:
public interface DataUtil<T extends DataUtil<T>> {
default T someDefaultFn() { ... };
}
And I used this interface for some POJO data class like:
public MyPoJo extends DataUtil<MyPojo> { ... }
And I get stuck when I to try check the type variable Class<FType> (a FieldType of any fields are declared inside T class) whether FType extends DataUtil<FType extends DataUtil<FType>> or not? I'm also trying to research the java.reflect package but did not find the expected answer. Can anyone help me to resolve this problem or find another design solution for this scenario?
I recently ran across this scenario in code that I didn't write and while there may be some design benefit to this approach, I can't seem to squeeze this rationale out of my own brain. So before I go and look foolish, I'm hoping for some feedback here.
Service interface something like this:
public interface Service {...}
Then, a base class that adds a generic reference to the Service interface where T extends the Service, but then the overall base class also implements the interface. Something like this:
public class ServiceBase<T extends Service> implements Service {...}
Why would you do this? I'm noticing that in practice the extension of ServiceBase always uses the same class name as T as the one that is being declared; so there's not really any magic polymorphic benefit here. Something like this:
public class MyService extends ServiceBase<MyService> {...}
and, the MyService class is never a container for the generic (e.g., I don't believe this is signaling some kind of self-containing list, where MyService could contain a list of MyServices).
Any ideas/thoughts on why someone would do this?
Why would you do this? I'm noticing that in practice the extension of
ServiceBase always uses the same class name as T as the one that is
being declared; so there's not really any magic polymorphic benefit
here.
Generics don't exist to create magic polymorphim. It is mainly a way to add constraints on types at compile time in order to reduce clumsy cast and error type at runtime.
In your case, suppose that ServiceBase class is abstract and has a process() method which needs to create at each call a new instance of the concrete class we declare in the parameterized type.
We call this abstract method createService().
Without using generics, we could declare the method like that public abstract ServiceBase createService().
ServiceBase without generics
public abstract class ServiceBase implements Service {
public abstract ServiceBase createService();
#Override
public void process() {
createService().process();
}
}
With this declaration, the concrete class may return any instance of ServiceBase.
For example, the following child class will compile because we are not forced to change the returned type of createService() to the current declared type.
MyService without generics
public class MyService extends ServiceBase {
#Override
public ServiceBase createService() {
return new AnotherService();
}
}
But if I use generics in base class :
ServiceBase with generics
public abstract class ServiceBase<T extends Service> implements Service {
public abstract T createService();
#Override
public void process() {
createService().process();
}
}
The concrete class has no choice, it is forced to change the returned type of createService() with the parameterized type declared.
MyService with generics
public class MyService extends ServiceBase<MyService> {
#Override
public MyService createService() {
return new MyService();
}
}
I made up an example using your class and interface declarations (except that I made ServiceBase abstract) which should illustrate the use of the generic types:
public interface Service {
int configure(String cmd);
}
public abstract class ServiceBase<T extends Service> implements Service {
private ServiceManager manager;
public ServiceBase(ServiceManager manager){
this.manager = manager;
}
public final void synchronize(T otherService){
manager.configureEnvironment(otherService.configure("syncDest"), configure("syncSrc"));
synchronizeTo(otherService);
}
protected abstract void synchronizeTo(T otherService);
}
public class ProducerService extends ServiceBase<ConsumerService> {
public ProducerService(ServiceManager manager) {
super(manager);
}
#Override
protected void synchronizeTo(ConsumerService otherService) {
/* specific code for synchronization with consumer service*/
}
#Override
public int configure(String cmd) { ... }
}
public class ConsumerService extends ServiceBase<ProducerService> {
public ConsumerService(ServiceManager manager) {
super(manager);
}
#Override
protected void synchronizeTo(ProducerService otherService) {
/* specific code for synchronization with producer service */
}
#Override
public int configure(String cmd) { ... }
}
Imagine we have services managed by a ServiceManager which can configure the environment of the services so that they are ready for synchronization with each other. How a configure command is interpreted is up to the specific service. Therefore a configure() declaration resides in our interface.
The ServiceBase handles the basic synchronization stuff that has to happen generally when two services want to synchronize. The individual implementations of ServiceBase shouldn't have to deal with this.
However ServiceBase doesn't know how a specific implementation of itself synchronizes to a specific other implementation of service. Therefore it has to delegate this part of synchronization to its subclass.
Now generics come into the play. ServiceBase also doesn't know to which type of service it is able to synchronize to. He has also to delegate this decision to its subclass. He can do this using the construct T extends Service
Given this structure now imagine two concrete subclasses of ServiceBase: ProducerService and ConsumerService; The consumer service can only synchronize to the producer service and the other way around. Therefore the two classes specify in their declaration ServiceBase<ConsumerService> respectively ServiceBase<ProducerService>.
Conclusion
Just like abstract methods can be used by superclasses to delegate the implementation of functionality to their subclasses, generic type parameters can be used by superclasses to delegate the "implementation" of type placeholders to their subclasses.
You haven't posted any of the definitions of these classes where the type parameter is used (which would most likely convey the rationale behind this design, or maybe the lack of it...), but in all cases, a type parameter is a way of parameterizing a class, just like a method can be parameterized.
The ServiceBase class implements a Service. This tells us that it implements the contract (methods) of a Service (to be more precise, subclasses of it can act as the implementation).
At the same time, ServiceBase takes a type argument that is a subtype of Service. This tells us that a service implementation probably has a "relationship" with another implementation type (possibly the same type as the current one). This relationship could be anything needed by the specific design requirement, e.g. the type of Service that this implementation can delegate to, the type of Service that can call this service, etc.
The way I read the following declaration
public class ServiceBase<T extends Service> implements Service {...}
is roughly: ServiceBase is a base implementation of a service, which can have a statically typed relationship with some other type of service.
These two aspects are completely independent.
I am trying to create a generic interface for my classes that will satisfy them all. I have created base classes to link them all together but the interface I'm trying to create isn't working like I'd expect it to and I cant find the right words to type into the search to find them.
The interface so far is:
public <T extends SDOBase> T entityToSDO(<? extends BaseEntity> entity, T sdo) throws Exception;
How do I make entity a second generic type?
Try declaring your method this way:
public <T extends SDOBase, E extends BaseEntity> T entityToSDO(E entity, T sdo) throws Exception;
I think you want something more along the lines of:
public interface MyInterface<T extends SDOBase>
{
public T entityToSDO(<? extends BaseEntity> entity, T sdo) throws Exception;
}
You just need
public <T extends SDOBase> T entityToSDO(BaseEntity entity, T sdo) throws Exception;
Anything that is an instance of a subtype of BaseEntity automatically is an instance of BaseEntity.