Spring Integration support for the Normalizer EIP - spring-integration

Spring Integration here. I was expecting to see a normalize(...) method off the IntegrationFlow DSL and was surprised to find there wasn't one (like .route(...) or .aggregate(...), etc.).
In fact, some digging on Google and the Spring Integration docs, and I can't seem to find any built-in support for the Normalizer EIP. So I've taken a crack at my own:
public class Normalizer extends AbstractTransformer {
private Class<?> targetClass;
private GenericConverter genericConverter;
public Normalizer(Class<?> targetClass, GenericConverter genericConverter) {
Optional<GenericConverter.ConvertiblePair> maybePair = genericConverter.getConvertibleTypes().stream()
.filter(convertiblePair -> !convertiblePair.getTargetType().equals(targetClass))
.findAny();
assert(maybePair.isEmpty());
this.targetClass = targetClass;
this.genericConverter = genericConverter;
}
#Override
protected Object doTransform(Message<?> message) {
Object inbound = message.getPayload();
return genericConverter.convert(inbound, TypeDescriptor.forObject(inbound), TypeDescriptor.valueOf(targetClass));
}
}
The idea is that Spring already provides the GenericConverter SPI for converting multiple source types to 1+ target type instance. We just need a specialized flavor of that that has the same target type for all convertible pairings. So here we extend AbstractTransformer and pass it one of these GenericConverters to use. During initialization we just verify that all the possible convertible pairs convert to the same targetClass specified for the Normalizer.
The idea is I could instantiate it like so:
#Bean
public Normalizer<Fizz> fizzNormalizer(GenericConverter fizzConverter) {
return new Normalizer(Fizz.class, fizzConverter);
}
And then put it in a flow:
IntegrationFlow someFlow = IntegrationFlows.from(someChannel())
.transform(fizzNormalizer())
// other components
.get();
While I believe this will work, before I start using it too heavily I want to make sure I'm not overlooking anything in the Spring Integration framework that will accomplish/satisfy the Normalizer EIP for me. No point in trying to reinvent the wheel and all that jazz. Thanks for any insight.

If you take a closer look into that EI pattern, then you see:
Use a Normalizer to route each message type through a custom Message Translator so that the resulting messages match a common format.
The crucial part of this pattern that it is a composed one with a router as input endpoint and a set of transformers for each inbound message type.
Since it is that kind of component which is data model dependent and more over the routing and transforming logic might differ from use-case to use-case, it is really hard to make an out-of-the-box single configurable component.
Therefore you need to investigate what type of routing you need to do to chose a proper one for input: https://docs.spring.io/spring-integration/docs/current/reference/html/message-routing.html#router
Then for every routed type you nee to implement respective transformer to produce a canonical data mode.
All of the can be just wrapped into a #MessagegingGateway API to hide the normalize behind so-called pattern implementation.
That's what I would do to follow that EI pattern recommendations.
However if your use-case is so simple as just convert from one type to another, so yes, then you can rely on the ConversionService. You register your custom Converter: https://docs.spring.io/spring-integration/docs/current/reference/html/endpoint.html#payload-type-conversion. And then just use a .convert(Class) API from IntegrationFlowDefinition.
But again: since there is no easy way to cover all the possible domain use-cases, we cannot provide an out-of-the-box Normalizer implementation.

Related

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.

Spring Integration - AMQP Inferred Types In Java DSL?

I have been working on a "paved road" for setting up asynchronous messaging between two micro services using AMQP. We want to promote the use of separate domain objects for each service, which means that each service must define their own copy of any objects passed across the queue.
We are using Jackson2JsonMessageConverter on both the producer and the consumer side and we are using the Java DSL to wire the flows to/from the queues.
I am sure there is a way to do this, but it is escaping me: I want the consumer side to ignore the __TypeID__ header that is passed from the producer, as the consumer may have a different representation of that event (and it will likely be in in a different java package).
It appears there was work done such that if using the annotation #RabbitListener, an inferredArgumentTypeargument is derived and will override the header information. This is exactly what I would like to do, but I would like to use the Java DSL to do it. I have not yet found a clean way in which to do this and maybe I am just missing something obvious. It seems it would be fairly straight forward to derive the type when using the following DSL:
return IntegrationFlows
.from(
Amqp.inboundAdapter(factory, queueRemoteTaskStatus())
.concurrentConsumers(10)
.errorHandler(errorHandler)
.messageConverter(messageConverter)
)
.channel(channelRemoteTaskStatusIn())
.handle(listener, "handleRemoteTaskStatus")
.get();
However, this results in a ClassNotFound exception. The only way I have found to get around this, so far, is to set a custom message converter, which requires explicit definition of the type.
public class ForcedTypeJsonMessageConverter extends Jackson2JsonMessageConverter {
ForcedTypeJsonMessageConverter(final Class<?> forcedType) {
setClassMapper(new ClassMapper() {
#Override
public void fromClass(Class<?> clazz, MessageProperties properties) {
//this class is only used for inbound marshalling.
}
#Override
public Class<?> toClass(MessageProperties properties) {
return forcedType;
}
});
}
}
I would really like this to be derived, so the developer does not have to really deal with this.
Is there an easier way to do this?
The simplest way is to configure the Jackson converter's DefaultJackson2JavaTypeMapper with TypeIdMapping (setIdClassMapping()).
On the sending system, map foo:com.one.Foo and on the receiving system map foo:com.two.Foo.
Then, the __TypeId__ header gets foo and the receiving system will map it to its representation of a Foo.
EDIT
Another option would be to add an afterReceiveMessagePostProcessor to the inbound channel adapter's listener container - it could change the __TypeId__ header.

JAXB XJC options: Alternative to com.sun.tools.xjc.Options which is Java9-friendly and OSGi-friendly

In our framework we have an interface with this method in the public API:
JaxbConfiguration newJaxbConfiguration(Options xjcOpts);
In the implementation, we do something like this:
import com.sun.tools.xjc.ModelLoader;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.model.Model;
...
public JaxbConfiguration newJaxbConfiguration(Options xjcOpts) {
Model model = ModelLoader.load(xjcOpts, ...);
...
}
However, both OSGi and Java 9's jigsaw don't like that we use com.sun.tools.xjc.Options, not in our implementation and especially not in our public API interface.
How can we get rid of it?
The JDeps website lists some of the JDK internal APIs and the recommended way to replace their usage. However, the use of ModelLoader.load() is not mentioned. My guess is that this use case has not come up enough to get the attention of the JDeps team.
My recommendation would be to refactor this method so that
you pass in the data you're using to construct the Options argument, instead of passing in the Options argument
use that data to construct your JaxbConfiguration object instead of converting from the internal Model.
You don't mention what JaxbConfiguration is or what library it's from so it's hard for me to say exactly how to construct it. Anyway, this answer is about how to remove the use of the internal API. How to construct a JaxbConfiguration is probably a different question.

DDD Using Specification pattern for Validation

I am thinking of using Specification pattern for validation purposes. The hard thing is how to tell the user why some Specification was not satisfied. What if the Specification.IsSatisfiedBy() will not only return a bool value, but also the reason of failure. It would look something like this:
interface ISpecification<T>
{
CheckResult IsSatisfiedBy(T candidate);
}
where CheckResult is:
class CheckResult
{
public bool IsSatisfied { get; }
public string FailureReason { get; }
}
In Fowler & Evans work there is a concept of Partially Satisfied Specification whose purpose is to provide explanation what exactly was not satisfied. However in that document, it is implemented as additional method remainderUnsatisfiedBy which returns the Specification which was not accomplished by the Candidate.
So the question is: When using Specification for validation purposes, how to provide feedback to user that a given Specification was not satisfied? Is the solution I've presented above good?
Although you may use your Specifications classes for validation, I would suggest you keep them as separate concepts within your domain. You may find that you need to re-use the same underlying specifications but need to return different "Failure Reasons" depending on purpose and context. See this article for more details.
The author of the post referenced above has also kindly shared code to github and posted the code as NCommon. Review these areas in particular:
Specifications: https://github.com/riteshrao/ncommon/tree/v1.2/NCommon/src/Specifications
Validations: https://github.com/riteshrao/ncommon/tree/v1.2/NCommon/src/Rules (especially the classes for ValidationResult and ValidationError)
I had the same problem. I create Validation decorator for Specification (code is JAVA).
interface Validator<T>{
Respond validate(T t)
}
class abstract ValidationSpecificationDecorator<T> implements Validator<T> {
Specification<T> spec;
ValidationSpecificationDecorator(Specification<T> spec){
this.spec = spec;
}
public Respond validate(T t) {
Respond respond = new Respond();
if(!spec.IsSatisfiedBy(t){
respond.add(error(t));
}
return respond;
)
public abstract Error error(T t);
}
Not sure about your language, but in Scala there is a concept (structure): Either[A,B]
And in calculations you either return right side (B) - for successful validation (object satisfy business rule) or left side (A) to express reason of failed validation for a given business object.
For the Specification purpose, you could return (for A type) e.g. String (as an error message) or some objects/enums (or anything which is appropriate in your language) representing business reason of why specified object didn't satisfy the specification.
It's similar to your solution but more functional and robust.

MEF and Factory Pattern

i am trying to refactor my project to improve testability, therefor i'm introducing an abstract factory.
My application collects data from different sources by using ICrawlers.
These ICrawlers use 3rd party libraries to access different sources, like e.g. twitter.
Example: My TwitterCrawler uses TweetSharp to access twitter data.
My first version strongly coupled the TweetSharp client to the Crawler. Now i abstracted the TweetSharp to a ITwitterClient and a TweetSharpTwitterClient implementation.
Next step is to introduce a ITwitterClientFactory with a DefaultTwitterClientFactory that creates TweetSharpTwitterClients. This should bring me closer to my goal (testability) because i can switch the factory to MockTwitterClientFactory that creates a MockTwitterClient, that delivers some test output.
Now, let me come to my point.
I am using MEF for dependency injection (but i'm rather new to it). What I'm doing is this:
public class TwitterCrawler : CrawlerBase, ICrawler
{
[Import]
public ITwitterClientFactory TwitterClientFactory {get; set;}
public override Process()
{
ITwitterClient twitterClient = TwitterClientFactory.MakeSingletonClient();
// do something with twitterClient
}
}
Whereas my DefaultTwitterClientFactory exports itself to MEF:
[Export(typeof(ITwitterClient))]
public class DefaultTwitterClientFactory: ITwitterClientFactory
{
// implementation of ITwitterClientFactory
// provides methods to create instances of ITwitterClient implementations
}
Now, while this works so far, my question is, how to switch the factory?
How can i create a unit test and use the MockClientFactory instead of the DefaultTwitterClientFactory?
Is my approach good at all? Is it better to manually set the factory that is to be used?
Somewhere something like
... new TwitterCrawler(mockedTwitterClientFactory)
or even
.... new TwitterCrawler(mockedTwitterClient)?
This actually only moves the problem outside of TwitterClient, but still somewhere i have to decide how to construct the ITwitterClient and what factory to use for that purpose.
Should i dive more into the mechanics of MEF (ExportProvider?)
You shouldn't need to use the composer/container in your unit tests - just wire the SUT directly with the Test Doubles.
Something like this:
var sut = new TwitterCrawler();
sut.TwitterClientFactory = new FakeTwitterClientFactory();
However, you should really refactor from Property Injection to Constructor Injection, as the property implies that the dependency is optional.
BTW, your DefaultTwitterClientFactory doesn't export itself, it exports ITwitterClient.

Resources