I'm working on a PoC of an ES & CQRS system.
I have defined following classes to represent commands and events that represent an output of command being handled
public class CreateEstateCommand extends Command {}
public class ChangeEstateOwnerCommand extends Command {}
public class EstateCreatedEvent extends DomainEvent {}
public class EstateOwnerChangedEvent extends DomainEvent {}
The commands are being handled in classes that implement the following interface
/**
* Specific command handlers define what logic should be carried out during handling a command of type C.
* Single command execution results in an outcome of domain event of type E
*/
public interface CommandHandler<C extends Command, E extends DomainEvent> {
E handleCommand(C command);
}
public class EstateCreatedCommandHandler implements CommandHandler<CreateEstateCommand, EstateCreatedEvent> {
#Override
public EstateCreatedEvent handleCommand(CreateEstateCommand command) { /***/ }
}
public class ChangeEstateOwnerCommandHandler implements CommandHandler<ChangeEstateOwnerCommand, EstateOwnerChangedEvent> {
#Override
public EstateOwnerChangedEvent handleCommand(ChangeEstateOwnerCommand command) { /***/ }
}
Now there's the part where I want to use those specific handlers. The flow of command handling can be represented as follows:
Command gets into the system through the API, and they are forwarded to CommandServce class for handling
public class CommandService {
private final EventService eventService;
private final CommandGateway commandGateway;
public void handleCommand(CreateEstateCommand command) {
EstateCreatedEvent event = commandGateway.handleCommand(command);
eventService.handleEvent(event);
}
public void handleCommand(ChangeEstateOwnerCommand command) {
EstateOwnerChangedEvent event = commandGateway.handleCommand(command);
eventService.handleEvent(event);
}
}
As you can see, the handleCommand() methods are duplicated for each of the command submitted. The reason behind this is the problem I have with selecting appropriate handler implementation at runtime, depending on Command.commandType:
#Service
public class CommandGateway {
private final Map<String, CommandHandler<?, ?>> commandHandlers;
#Autowired
public CommandGateway(Map<String, CommandHandler<?, ?>> commandHandlers) {
this.commandHandlers = commandHandlers;
}
public EstateCreatedEvent handleCommand(CreateEstateCommand command) {
EstateCreatedCommandHandler handler = (EstateCreatedCommandHandler) commandHandlers.get(command.getCommandType());
return handler.handleCommand(command);
}
public EstateOwnerChangedEvent handleCommand(ChangeEstateOwnerCommand command) {
ChangeEstateOwnerCommandHandler handler = (ChangeEstateOwnerCommandHandler) commandHandlers.get(command.getCommandType());
return handler.handleCommand(command);
}
}
The snippet above is the part I cannot generify. Is it possible, to implement CommandGateway class, so CommandService can look as follows:
public class CommandService {
public <C extends Command, E extends DomainEvent> void handleCommand(C command) {
E event = commandGateway.handleCommand(command);
}
}
And provide type-safe objects?
The root problem is the map, whose values are wildcard typed, ie effectively untyped, and more particularly, not typed to align with the key.
You've already ripped up some typed safety by trusting the injected map's entries, so just take it one step further by using a raw CommandHandler, which will accept any command, and use an unchecked cast for a properly typed return value:
#SuppressWarnings({"unchecked", "rawtypes"})
public <C extends Command, E extends DomainEvent> E handleCommand(C command) {
CommandHandler handler = commandHandlers.get(command.getCommandType());
return (E)handler.handleCommand(command);
}
#SuppressWarnings added so neither your IDE nor build complain.
While this might seem brutal, you haven't actually lost any type safety. That was lost when you typed your map as you did, which unfortunately was unavoidable given that map typing does not bind the value type to the key type.
What if you do something like this:
static abstract class Command {
public abstract String getCommandType();
public abstract Class<? extends DomainEvent> type();
}
And your implementation:
public class CreateEstateCommand extends Command {
#Override
public String getCommandType() {
return null; // whatever here
}
#Override
public Class<EstateCreatedEvent> type() {
return EstateCreatedEvent.class;
}
}
And usage would be:
public DomainEvent handleCommand(Command command) {
return command.type().cast(commandHandlers.get(command.getCommandType()));
}
The difficulty in achieving this end-to-end with generics is that we are mixing runtime type decisions with compile-time type checks. You design is close to an MVC design, where handlers are retrieved at runtime. So, only limited type-safety checks are possible at compile-time.
Let us look at a flow:
An API recieves a command with its inputs
You may have a specific controller method that knows the command and its inputs and can construct one of CreateEstateCommand or ChangeEstateOwnerCommand
Now, at runtime we have to access the map to know the associated CommandHandler. Now, the very reason we have to do this at runtime is because the decision cannot be made at compile time, due to the design of using a Map.
If you have the following method in CommandGateway, it can never be sure if the Command instance passed from the service class is really the specific child that the mapped CommandHandler wants. Hence, it will not compile.
public DomainEvent handleCommand( Command command ) {
CommandHandler<? extends Command, ? extends DomainEvent> cmdHandler = commandHandlers.get(command.getCommandType());
return cmdHandler.handleCommand( command );
}
Hence, you have to do away with either the end-to-end type safety requirement or with the "factory" style map that gives you the CommandHandler instance. Leaving out the latter will mean that the API method, right in the beginning, knows which CommandHandler it needs.
Related
I would like to understand of this issue
public class DogController extends FeedCommonController<DogModel extends CommonAnimalModel, FARMER_1_AUTH> {
// something
// This is working - but there is duplication
#Security.Authenticated(FARMER_1_AUTH.class)
public boolean feed_it() {
// nothing special
DogModel.getRandom().feed_it();
}
}
public class CatController extends FeedCommonController<CatModel extends CommonAnimalModel, FARMER_2_AUTH> {
// something
// This is working - but there is duplication
#Security.Authenticated(FARMER_2_AUTH.class)
public boolean feed_it() {
// nothing special
CatModel.getRandom().feed_it();
}
}
And I want to simplify the code and remove the duplicate methods, but I cannot put Class type to annotation.
public abstract class CommonAnimalController< T extends CommonAnimalModel, XXXXXX> {
#Security.Authenticated(XXXXXX.class) // <-- Here is a problem with declaration
public boolean feed_it() {
T.getRandom().feed_it();
}
}
/**
Get Token From HTTP Request from Actual Thread
*/
public class Security {
#With(AuthenticatedAction.class)
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface Authenticated {
Class<? extends Authenticator> value() default Authenticator.class;
}
}
Concept with Annotation is already created and implemented on hundred classes. So its not possible make huge changes. But Its some Elegant way how to solved this?
You have two problems in one question.
First problem you have is: How to get a class instance of generics type T
This is answered here: How to get a class instance of generics type T
The second problem you have, is how to avoid passing a constant to the annotation. You will have a compliation error "Attribute value must be constant"
For this second problem seems there is no simple way to achieve it in Java. (pheraps I am wrong)
See this answer: How to supply value to an annotation from a Constant java
Solution for problem1
public abstract class CommonAnimalController<T extends CommonAnimalModel, XXXXXX> {
final Class<XXXXXX> typeParameterClass;
public CommonAnimalController(Class<XXXXXX> typeParameterClass) {
this.typeParameterClass = typeParameterClass;
}
#Security.Authenticated(typeParameterClass) // you will have "Attribute value must be constant"
public boolean feed_it() {
return T.getRandom().feed_it();
}
}
I have problem regarding Apache Flink. I want to have an abstract class that consumes a stream. However the pattern applied to this stream should be interchangeable.
public abstract class AbstractVisitConsumer<TEventType>
TEventType marks the type of the event that is generated from the pattern. Every pattern must implement an interface called IEventPattern
public interface IEventPattern<TStreamInput, TMatchedEvent> extends Serializable {
TMatchedEvent create(Map<String, List<TStreamInput>> pattern);
Pattern<TStreamInput, ?> getEventPattern();
The abstract class has a method called applyPatternSelectToStream()
DataStream<TEventType> applyPatternSelectToStream(DataStream<VisitEvent> stream, IEventPattern<VisitEvent, TEventType> pattern) {
DataStream<TEventType> patternStream = CEP.pattern(stream, pattern.getEventPattern()).select(new PatternSelectFunction<VisitEvent, TEventType>() {
#Override
public TEventType select(Map<String, List<VisitEvent>> map) throws Exception {
return pattern.create(map);
}
}).returns(this.typeInformation);
return patternStream;
}
The flink compiler always gives me the error
Exception in thread "main" org.apache.flink.api.common.functions.InvalidTypesException: Type of TypeVariable 'TEventType' in 'class com.felix.AbstractVisitConsumer' could not be determined. This is most likely a type erasure problem. The type extraction currently supports types with generic variables only in cases where all variables in the return type can be deduced from the input type(s)
My class WorkPlaceConsumer extends the aforementioned abstract class to specify the desired event that is generated from the stream.
public class WorkPlaceConsumer extends AbstractVisitConsumer<WorkPlaceEvent> {
public WorkPlaceConsumer(TypeInformation typeInfo) {
super(TypeInformation.of(WorkPlaceEvent.class));
}
public static void main(String[] args) {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
WorkPlaceConsumer consumer = new WorkPlaceConsumer();
DataStream<VisitEvent> visitStream = consumer.getVisitStream(env);
DataStream<WorkPlaceEvent> workPlaceStream = consumer.applyPatternSelectToStream(visitStream, new WorkPlacePattern());
visitStream.print();
workPlaceStream
.keyBy((KeySelector<WorkPlaceEvent, Integer>) event -> event.getUserId())
.filter(new NewWorkPlaceEventFilter())
.print();
try {
env.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
I already tried to implement the ResultTypeQueryable interface and tried to store the type information in the abstract class by passing the type information from the child class at runtime. I also was using .returns for the method to provide manual type information. Maybe I am just doing it wrong. Had anybody similar issues with generic transformations on streams?
All right I had a second look at your problem and you were right it has nothing to do with the lambda expression. The problem is that type erasure was applied to the PatternSelectFunction.
You can manually provide the return type by implementing ResultTypeQueryable interface. You can do it e.g. like that:
public interface InnerPatternSelectFunction<T> extends PatternSelectFunction<String, T>, ResultTypeQueryable<T>{};
public DataStream<T> applyPatternSelectToStream(DataStream<String> stream, IEventPattern<String, T> pattern) {
TypeInformation<T> producedType = this.typeInformation;
return CEP.pattern(stream, pattern.getEventPattern()).select(new InnerPatternSelectFunction<T>() {
#Override
public TypeInformation<T> getProducedType() {
return producedType;
}
#Override
public T select(Map<String, List<String>> map) throws Exception {
return pattern.create(map);
}
});
}
Of course it is just a proposal and I think you can improve the code ;). But you get the general idea of implementing ResultTypeQueryable interface.
Ok, while I tried to find a title that explains the problem I probably have to expand on it.
Recently I implemented a small program that will be used to control a tape library. Knowing it had to work with multiple different types of tape library so the following design was developed.
interface Tapelibrary<T extends TapeDrive> {
List<T> getListofDrives();
void doSomethingWithDrive(T d);
}
class SpecificTapeLibrary implements Tapelibrary<HPDrive> {
private List<HPDrive> driveList;
SpecificTapeLibrary() {
driveList.add(new HPDrive());
driveList.add(new HPDrive());
driveList.add(new HPDrive());
}
#Override
public List<HPDrive> getListofDrives() {
return driveList;
}
#Override
public void doSomethingWithDrive(HPDrive d) {
d.doSomethingHPspecific();
}
}
abstract class TapeDrive {
void doSomething() {
}
}
class HPDrive extends TapeDrive {
void doSomethingHPspecific() {
}
}
The correct tape library is determined by a factory based on command line arguments.
public static void main(String[] args) {
Tapelibrary<? extends TapeDrive> t = new TapeLibraryFabric().get();
List<? extends TapeDrive> listOfDrives = t.getListofDrives();
// the user selects a drive by using a small UI or something
TapeDrive selectedDrive = listOfDrives.get(0);
t.doSomethingWithDrive(selectedDrive); // compiler error
}
This does make sense since the compiler would have to explicitly cast the supertype TapeDrive to the subtype HPDrive which is expected by the doSomethingWithDrive(HPDrive) methods in SpecificTapeLibrary
How would this be solved in a good oop way? I ended up not using generics and casting inside the doSomethingWithDrive method (as suggested here:How to Pass a Child Class into a method requiring Super Class as parameter). But that can't be the optimal solution.
While writing this post another solution popped into my head which is much cleaner. The DriveSelector class encapsulates the selection process.
class DriveSelector {
<T> T selectDrive(List<T> inputList) {
// give the user an UI or something to select a drive
return inputList.get(0);
}
}
// the tape library then uses the selector
public void doSomethingWithSelectedDrive(DriveSelector selector) {
HPDrive t = selector.selectDrive(driveList);
t.doSomethingHPspecific();
}
Any other ideas?
Do all of your work in a generic method:
static <T extends TapeDrive> void doStuff(Tapelibrary<T> t) {
List<T> listOfDrives = t.getListofDrives();
// the user selects a drive by using a small UI or something
T selectedDrive = listOfDrives.get(0);
t.doSomethingWithDrive(selectedDrive);
}
Then call this from your main method:
Tapelibrary<? extends TapeDrive> t = new TapeLibraryFabric().get();
doStuff(t);
Ideone demo
The way this works is that it removes all of the wildcards - the thing about wildcards is that the compiler treats every one as different, even if the values are derived from a single generic instance. By putting things into the generic method like this, you allow the compiler to know that all of the Ts are the same type - thus it can know that the calls are safe.
i have my DTO class that is :
public class EmailResponse {
// Make public to avoid getters and setters
public Email email;
public RequestData reqData;
public EmailResponse() {
super();
}
}
and i want to implement to it this interface:
public interface IAssertionErrorDo {
public void onErrorDo();
}
but i want to do it during execution, i don't want to touch "EmailResponse" because it would not be ok to make it implements that interface due they don't belong to the same layer, i mean, EmailResponse would belong to service layer and IAssertionError would belong to test layer. I am using TestNG.
Do you know how i could do this? Regards
EDIT:
My implementation is this:
EmailResponse emailResponse = emailService.getUserEmail(userId);
And the reason i want to do this "injection" is because i have
public class LoggingAssert
extends Assertion {
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAssert.class);
private IAssertionErrorDo dataE;
#Override
public void onAssertFailure(IAssert a, AssertionError ex) {
LOGGER.info("[ERROR] " + a.getMessage());
if (this.dataE != null) {
this.dataE.onErrorDo();
}
}
public LoggingAssert setOnErrorDo(IAssertionErrorDo object) {
this.object = object;
return this;
}
}
loggingAssert.setOnErrorDo(emailResponse).assertNotNull(emailResponse.getEmail().getId(),
"Checking created email doesn't exists");
So i want to if assert fails execute method onErrorDo() from emailResponse
You could do
public class MyEmailResponse extends EmailResponse implements IAssertionErrorDo {
...
}
implementation calls in interfaces, you can call more than 1 interface if you want by adding commas to separate them..
to call interface methods you simply just use the method's name.
like this:
public class MyEmailResponse implements IAssertionErrorDo
{
public void onErrorDo() {//define it's behavior}
}
if you extend a class you use:
super.MyMethod()
to call the a method inside the extended class, but if you already have an extended class and want a method from another class you have to create an object for that class first then call it, thus:
MyClass mc = new MyClass();
if it is in a different package then
myPackage.MyClass mc = new myPackage.MyClass();
then you call your method from that class using the object you created, which is in this case mc.. so:
mc.MyMethod();
if you want it to return a variable then you will need to add a return statement in that method with the variable you want it to return.
interfaces are usually used for global an changing environments (dynamics), for example if you developed a program and it needs a driver to connect to databases then you will make an interface and send it to the database developers, and each one will fill the codes in that interface and send it back... this guarantees consistency.
when you implement an interface you have to define every method inside it (even if you leave it empty) and you cannot change the interface's methods names nor add... it is used in other areas as well, i don't think you need to use it in your case.
Let's say I have a manufacturing scheduling system, which is made up of four parts:
There are factories that can manufacture a certain type of product and know if they are busy:
interface Factory<ProductType> {
void buildProduct(ProductType product);
boolean isBusy();
}
There is a set of different products, which (among other things) know in which factory they are built:
interface Product<ActualProductType extends Product<ActualProductType>> {
Factory<ActualProductType> getFactory();
}
Then there is an ordering system that can generate requests for products to be built:
interface OrderSystem {
Product<?> getNextProduct();
}
Finally, there's a dispatcher that grabs the orders and maintains a work-queue for each factory:
class Dispatcher {
Map<Factory<?>, Queue<Product<?>>> workQueues
= new HashMap<Factory<?>, Queue<Product<?>>>();
public void addNextOrder(OrderSystem orderSystem) {
Product<?> nextProduct = orderSystem.getNextProduct();
workQueues.get(nextProduct.getFactory()).add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
factory.buildProduct(workQueues.get(factory).poll());
}
}
Disclaimer: This code is merely an example and has several bugs (check if factory exists as a key in workQueues missing, ...) and is highly non-optimal (could iterate over entryset instead of keyset, ...)
Now the question:
The last line in the Dispatcher (factory.buildProduct(workqueues.get(factory).poll());) throws this compile-error:
The method buildProduct(capture#5-of ?) in the type Factory<capture#5-of ?> is not applicable for the arguments (Product<capture#7-of ?>)
I've been racking my brain over how to fix this in a type-safe way, but my Generics-skills have failed me here...
Changing it to the following, for example, doesn't help either:
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy()) {
Product<?> product = workQueues.get(factory).poll();
product.getFactory().buildProduct(product);
}
}
Even though in this case it should be clear that this is ok...
I guess I could add a "buildMe()" function to every Product that calls factory.buildProduct(this), but I have a hard time believing that this should be my most elegant solution.
Any ideas?
EDIT:
A quick example for an implementation of Product and Factory:
class Widget implements Product<Widget> {
public String color;
#Override
public Factory<Widget> getFactory() {
return WidgetFactory.INSTANCE;
}
}
class WidgetFactory implements Factory<Widget> {
static final INSTANCE = new WidgetFactory();
#Override
public void buildProduct(Widget product) {
// Build the widget of the given color (product.color)
}
#Override
public boolean isBusy() {
return false; // It's really quick to make this widget
}
}
Your code is weird.
Your problem is that you are passing A Product<?> to a method which expects a ProductType which is actually T.
Also I have no idea what Product is as you don't mention its definition in the OP.
You need to pass a Product<?> to work. I don't know where you will get it as I can not understand what you are trying to do with your code
Map<Factory<?>, Queue<Product<?>>> workQueues = new HashMap<Factory<?>, Queue<Product<?>>>();
// factory has the type "Factory of ?"
for (Factory<?> factory: workqueues.keySet())
// the queue is of type "Queue of Product of ?"
Queue<Product<?>> q = workqueues.get(factory);
// thus you put a "Product of ?" into a method that expects a "?"
// the compiler can't do anything with that.
factory.buildProduct(q.poll());
}
Got it! Thanks to meriton who answered this version of the question:
How to replace run-time instanceof check with compile-time generics validation
I need to baby-step the compiler through the product.getFactory().buildProduct(product)-part by doing this in a separate generic function. Here are the changes that I needed to make to the code to get it to work (what a mess):
Be more specific about the OrderSystem:
interface OrderSystem {
<ProductType extends Product<ProductType>> ProductType getNextProduct();
}
Define my own, more strongly typed queue to hold the products:
#SuppressWarnings("serial")
class MyQueue<T extends Product<T>> extends LinkedList<T> {};
And finally, changing the Dispatcher to this beast:
class Dispatcher {
Map<Factory<?>, MyQueue<?>> workQueues = new HashMap<Factory<?>, MyQueue<?>>();
#SuppressWarnings("unchecked")
public <ProductType extends Product<ProductType>> void addNextOrder(OrderSystem orderSystem) {
ProductType nextProduct = orderSystem.getNextProduct();
MyQueue<ProductType> myQueue = (MyQueue<ProductType>) workQueues.get(nextProduct.getFactory());
myQueue.add(nextProduct);
}
public void assignWork() {
for (Factory<?> factory: workQueues.keySet())
if (!factory.isBusy())
buildProduct(workQueues.get(factory).poll());
}
public <ProductType extends Product<ProductType>> void buildProduct(ProductType product) {
product.getFactory().buildProduct(product);
}
}
Notice all the generic functions, especially the last one. Also notice, that I can NOT inline this function back into my for loop as I did in the original question.
Also note, that the #SuppressWarnings("unchecked") annotation on the addNextOrder() function is needed for the typecast of the queue, not some Product object. Since I only call "add" on this queue, which, after compilation and type-erasure, stores all elements simply as objects, this should not result in any run-time casting exceptions, ever. (Please do correct me if this is wrong!)