Can CDI #Producer method take custom parameters? - cdi

I think i understood how CDI works and in order to dive deep in it, i would like to try using it with something real world example. I am stuck with one thing where i need your help to make me understand. I would really appreciate your help in this regard.
I have my own workflow framework developed using Java reflection API and XML configurations where based on specific type of "source" and "eventName" i load appropriate Module class and invoke "process" method on that. Everything is working fine in our project.
I got excited with CDI feature and wanted to give it try with workflow framework where i am planning inject Module class instead of loading them using Reflection etc...
Just to give you an idea, I will try to keep things simple here.
"Message.java" is a kind of Transfer Object which carries "Source" and "eventName", so that we can load module appropriately.
public class Message{
private String source;
private String eventName;
}
Module configurations are as below
<modules>
<module>
<source>A</source>
<eventName>validate</eventName>
<moduleClass>ValidatorModule</moduleClass>
</module>
<module>
<source>B</source>
<eventName>generate</eventName>
<moduleClass>GeneratorModule</moduleClass>
</module>
</modules>
ModuleLoader.java
public class ModuleLoader {
public void loadAndProcess(Message message){
String source=message.getSource();
String eventName=message.getEventName();
//Load Module based on above values.
}
}
Question
Now , if i want to implement same via CDI to inject me a Module (in ModuleLoader class), I can write Factory class with #Produce method , which can do that. BUT my question is,
a) how can pass Message Object to #Produce method to do lookup based on eventName and source ?
Can you please provide me suggestions ?
Thanks in advance.

This one is a little tricky because CDI doesn't work the same way as your custom solution (if I understand it correctly). CDI must have all the list of dependencies and resolutions for those dependencies at boot time, where your solution sounds like it finds everything at runtime where things may change. That being said there are a couple of things you could try.
You could try injecting an InjectionPoint as a parameter to a producer method and returning the correct object, or creating the correct type.
There's also creating your own extension of doing this and creating dependencies and wiring them all up in the extension (take a look at ProcessInjectionTarget, ProcessAnnotatedType, and 'AfterBeanDiscovery` events. These two quickstarts may also help get some ideas going.

I think you may be going down the wrong path regarding a producer. Instead it more than likely would be much better to use an observer especially based on what you've described.
I'm making the assumption that the "Message" transfer object is used abstractly like a system wide event where basically you fire the event and you would like some handler defined in your XML framework you've created to determine the correct manager for the event, instantiate it (if need be), and then call the class passing it the event.
#ApplicationScoped
public class MyMessageObserver {
public void handleMessageEvent(#Observes Message message) {
//Load Module based on above values and process the event
}
}
Now let's assume you want to utilize your original interface (I'll guess it looks like):
public interface IMessageHandler {
public void handleMessage(final Message message);
}
#ApplicationScoped
public class EventMessageHandler implements IMessageHandler {
#Inject
private Event<Message> messageEvent;
public void handleMessage(Message message) {
messageEvent.fire(message);
}
}
Then in any legacy class you want to use it:
#Inject
IMessageHandler handler;
This will allow you to do everything you've described.

May be you need somthing like that:
You need the qualifier. Annotation like #Module, which will take two paramters source and eventName; They should be non qualifier values. See docs.
Second you need a producer:
#Produces
#Module
public Module makeAmodule(InjectionPoint ip) {
// load the module, take source and eventName from ip
}
Inject at proper place like that:
#Inject
#Module(source="A", eventName="validate")
Module modulA;
There is only one issue with that solution, those modules must be dependent scope, otherwise system will inject same module regardles of source and eventName.
If you want to use scopes, then you need make source and eventName qualified parameters and:
make an extension for CDI, register programmatically producers
or make producer method for each and every possible combinations of source and eventName (I do not think it is nice)

Related

FakeItEasy in C# on a servicereference

I have a servicereference with a method I need to use in a test.
The servicereference class is defined as:
public class MyServiceReference : Clientbase<IMyServiceReference>, IMyServiceReference
{
public MyServiceReference()
{
}
..... methods is then defined
}
From my testmethod I have tried both
private MyServiceReference myServiceReferenceFake = A.Fake<MyServiceReference>();
// And
private MyServiceReference myServiceReference = new MyServiceReference();
For both of these is crashes in the constructor with the message:
System.InvalidOperationException: Could not find default endpoint element that references contract.
All I need is to have a callto definition from a method in that class.
How can this be solved?
I've no experience with Clientbase, which I assume to be a System.ServiceModel.ClientBase<TChannel>,but I can make some general comments.
Since you tried first to fake a MyServiceReference, I'll assume that you're not testing that class, and you want to use it as a collaborator for the system under test. In that case, your best bet is to try faking IMyServiceReference. interfaces are very easy to fake, since they don't bring along any behaviour or baggage like faking a class does.
If you feel you really need to fake a MyServiceReference, then we have to contend with the fact that FakeItEasy will eventually call MyServiceReference(), which will call ClientBase<IMyServiceReference>(), whose documentation says
Initializes a new instance of the ClientBase<TChannel> class using the default target endpoint from the application configuration file.
Based on the error you reported, I assume that the application configuration file is not found or does not include the configuration required to create a MyServiceReference. The fact that you get the same error when you just try to instantiate a MyServiceReference directly strengthens my belief.
So I think your paths forward are either to try faking IMyServiceReference or to provide the configuration that ClientBase<IMyServiceReference> needs.

Spock- Capture method arguments in private method call of class under test

I am trying to test my Service class below
#Service
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
public class TaskTemplateService {
#NonNull
TaskTemplateRepository taskTemplateRepository;
public void doStuff() {
List<MyObject> list;
doOtherStuff(list)
}
private void doOtherStuff(List <MyObject>) {
//do stuff
}
}
When I am testing the real TaskTemplate, how can I capture what is passed to doOtherStuff?
You cannot and why would you?
Good testing means to specify the behaviour of a unit's public interface. Private methods ought to be covered via testing this way indirectly. If this is not possible then either you have dead, unreachable code or a design problem and should refactor.
BTW, the technical reason that you cannot mock/stub private methods is that most mocking tools, also the built-in feature of Spock, use dynamic proxies (DP) in order to implement mocking. DP technically are subclasses, but private methods can never be extended or even seen by subclasses or being called by them or from other classes, hence the term "private". Consequently, a mock subclass cannot check interactions with private methods.
How exactly you ought to redesign your class in order to make it testable really depends on why you want to "capture" the method argument, as you say. Do you need to replace it by a mock? Do you need to modify or verify the content of the original object?
If the object has a central meaning and you need to replace or verify it, why not make it injectable instead of creating it as a local variable, hermetically sealing it off from the outside world and making it untestable?
Or maybe in your case you could make the private method protected or package-scoped in order to make it testable. Then at least a mock could be created for it and you could capture the argument or stub the result.
I am mostly speculating here because the answer really depends on what is behind //do stuff, i.e. the very information you are hiding in your sample code.

How to use the strategy pattern with managed objects

I process messages from a queue. I use data from the incoming message to determine which class to use to process the message; for example origin and type. I would use the combination of origin and type to look up a FQCN and use reflection to instantiate an object to process the message. At the moment these processing objects are all simple POJOs that implement a common interface. Hence I am using a strategy pattern.
The problem I am having is that all my external resources (mostly databases accessed via JPA) are injected (#Inject) and when I create the processing object as described above all these injected objects are null. The only way I know to populate these injected resources is to make each implementation of the interface a managed bean by adding #stateless. This alone does not solve the problem because the injected members are only populated if the class implementing the interface is itself injected (i.e. container managed) as opposed to being created by me.
Here is a made up example (sensitive details changed)
public interface MessageProcessor
{
public void processMessage(String xml);
}
#Stateless
public VisaCreateClient implements MessageProcessor
{
#Inject private DAL db;
…
}
public MasterCardCreateClient implements MessageProcessor…
In the database there is an entry "visa.createclient" = "fqcn.VisaCreateClient", so if the message origin is "Visa" and the type is "Create Client" I can look up the appropriate processing class. If I use reflection to create VisaCreateClient the db variable is always null. Even if I add the #Stateless and use reflection the db variable remains null. It's only when I inject VisaCreateClient will the db variable get populated. Like so:
#Stateless
public QueueReader
{
#Inject VisaCreateClient visaCreateClient;
#Inject MasterCardCreateClient masterCardCreateClient;
#Inject … many more times
private Map<String, MessageProcessor> processors...
private void init()
{
processors.put("visa.createclient", visaCreateClient);
processors.put("mastercard.createclient", masterCardCreateClient);
… many more times
}
}
Now I have dozens of message processors and if I have to inject each implementation then register it in the map I'll end up with dozens of injections. Also, should I add more processors I have to modify the QueueReader class to add the new injections and restart the server; with my old code I merely had to add an entry into the database and deploy the new processor on the class path - didn't even have to restart the server!
I have thought of two ways to resolve this:
Add an init(DAL db, OtherResource or, ...) method to the interface that gets called right after the message processor is created with reflection and pass the required resource. The resource itself was injected into the QueueReader.
Add an argument to the processMessage(String xml, Context context) where Context is just a map of resources that were injected into the QueueReader.
But does this approach mean that I will be using the same instance of the DAL object for every message processor? I believe it would and as long as there is no state involved I believe it is OK - any and all transactions will be started outside of the DAL class.
So my question is will my approach work? What are the risks of doing it that way? Is there a better way to use a strategy pattern to dynamically select an implementation where the implementation needs access to container managed resources?
Thanks for your time.
In a similar problem statement I used an extension to the processor interface to decide which type of data object it can handle. Then you can inject all variants of the handler via instance and simply use a loop:
public interface MessageProcessor
{
public boolean canHandle(String xml);
public void processMessage(String xml);
}
And in your queueReader:
#Inject
private Instance<MessageProcessor> allProcessors;
public void handleMessage(String xml) {
MessageProcessor processor = StreamSupport.stream(allProcessors.spliterator(), false)
.filter(proc -> proc.canHandle(xml))
.findFirst()
.orElseThrow(...);
processor.processMessage(xml);
}
This does not work on a running server, but to add a new processor simply implement and deploy.

Jhipster override entity (keep existant + add behaviour)

I like the jhipster entity generator.
I often get to change my model and regen all entities.
I wish to keep the generated stuff and override for my needs.
On angular side, it is quite easy to create a new service extending the default entity service to do my stuff.
On java side, it is more complicated.
For example, I override src/main/java/xxx/web/rest/xxxResource.java with src/main/java/xxx/web/rest/xxxOverrideResource.java
I have to comment #RestController in xxxResource.java. I tried to give it a different bundle name from the overrided class but it is not sufficient : #RestController("xxxResource")
In xxxOverrideResource.java, I have to change all #xxxMapping() to different paths
In xxxOverrideResource.java, I have to change all method names
This allow me to keep the CRUD UI and API, and overload it using another MappingPath.
Some code to make it more visual. Here is the generated xxxResource.java
/**
* REST controller for managing WorldCommand.
*/
// Commented to prevent bean dupplicated error.
// #RestController
#RequestMapping("/api")
public class WorldCommandResource {
private final WorldCommandService worldCommandService;
public WorldCommandResource(WorldCommandService worldCommandService) {
this.worldCommandService = worldCommandService;
}
#PutMapping("/world-commands")
#Timed
public ResponseEntity<WorldCommand> updateWorldCommand(#Valid #RequestBody WorldCommand worldCommand)
throws URISyntaxException {
log.debug("REST request to update WorldCommand : {}", worldCommand);
...
}
Here is my overloaded version : xxxOverrideResource.java
/**
* REST controller for managing WorldCommand.
*/
#RestController("WorldCommandOverrideResource")
#RequestMapping("/api")
public class WorldCommandOverrideResource extends WorldCommandResource {
private final WorldCommandOverrideService worldCommandService;
public WorldCommandOverrideResource(WorldCommandOverrideService worldCommandService) {
super(worldCommandService);
log.warn("USING WorldCommandOResource");
this.worldCommandService = worldCommandService;
}
#PutMapping("/world-commands-override")
#Timed
public ResponseEntity<WorldCommand> updateWorldCommandOverride(#Valid #RequestBody WorldCommand worldCommand)
throws URISyntaxException {
throw new RuntimeException("WorldCommand updating not allowed");
}
With the xxxResource overrided, it is easy to override the xxxService and xxxRepository by constructor injection.
I feel like I am over thinking it. As it is not an external component but code from a generator, maybe the aim is to use the tool to write less code and then do the changes you need.
Also, I fear this overriding architecture will prevent me from creating abstract controller if needed.
Do you think keeping the original generated code is a good pratice or I should just make my changes in the generated class and be carefull when regenerating an entity ?
Do you know a better way to override a Spring controller ?
Your approach looks like the side-by-side approach described here: https://www.youtube.com/watch?v=9WVpwIUEty0
I often found that the generated REST API is only useful for managing data in a backoffice and I usually write a complete separate API with different endpoints, authorizations and DTOs that is consumed by mobile or end-users. So I don't see much value in overriding REST controllers, after all they are supposed to be quite thin with as little business logic as possible.
You must also consider how long you want to keep this compatibility with generated code. As your app grows in complexity you might want to refactor your code and organize it around feature packages rather than by technical packages (repository, rest controllers, services, ...). For many reasons, sooner or later the way the generated code is setup will get in your way, so I would not put too much effort into this compatibility goal that has no real business value especially when you know that the yearly released major version may break it because of changes in the generator itself or more likely because of changes in underlying frameworks.

What is the recommended way to avoid repeated code in ManagedBeans?

As for good user feedback, I am using messages on multiple sites in my webapplication.
To add a message, I simple use:
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(type, "", message));
I added variables for type and message, because it depends on different validation.
Well, I am using different ManagedBeans for different sites, this is just normal.
It came to my mind, what is the best practice for adding those messages in different ManagedBeans.
Currently, I am always using the above code snippet like over 30 times (and it will become more and more for sure).
Should I create a Bean with SessionScopedannotated or #ApplicationScoped? Do you have any other hints, that should I know?
Just hide away repeated static code into a reusable static method to make it more DRY ("Don't Repeat Yourself").
Design the static method in such way that you can ultimately refactor from this,
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(type, "", message));
to something like this,
Messages.addGlobalInfo(message);
or even with an import static com.example.Messages.*; (Eclipse: Ctrl+Shift+M the line):
addGlobalInfo(message);
It doesn't need to be a managed bean as it doesn't hold any state. Moreover, you should make the default constructor of such an utility class private, so Java/JSF can in first place already not construct it via new operator or Class#newInstance() in reflection. If you're using CDI, annotate it if necessary with #Typed with an empty value to prevent it from being registered as managed bean candidate via Bean<T>.
#Typed
public final class Messages {
private Messages() {}
// ...
}
JSF utility library OmniFaces has exactly this utility class: org.omnifaces.util.Messages.
May be just move this code to some utility class:
public void static addMessage(FacesMessage.Severity type, String message){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(type, "", message));
}
Also you can create several methods with one argument: addInfoMessage, addErrorMessage, ...

Resources