Can we use somehow "subflows" in Spring Integration?
I have many different processes which would use the same "subflow". These processes have always the same part which would be good to be put into a separate file.
What would be the corrent way to implement these flows?
I tried to find a solution to use subflows in Spring Integration but I could not find anything.
One simple technique is to put the subflow in a separate file with "well-known" input and output channels (the subflow starts with one channel and ends with another). Then, simply <import/> the subflow and send/consume to/from the input/output channel.
Or, instead of an import you can use the Java DSL to define the subflow and add it to your application contexts that need the subflow...
#Configuration
public class MySubflowDefinition {
#Bean
public IntegrationFlow subflow() {
return IntegrationFlows.from("someInChannel")
.transform(...)
...
.channel("someOutChannel")
.get();
}
}
For a more formal "subflow" definition, see the spring-integration-flow extension. This solution also allows the same subflow to be invoked from multiple places in the same application context.
spring-integration-java-dsl and spring-integration-flow are both available in the spring repo and maven central with (currently) versions 1.0.0.RELEASE.
Related
I am using SpringBoot 2.0 with Spring Integration 5.0.3 and have an issue with my HTTP.inboundGateway. My goal is to validate the JSON posted to the gateway, because the request pojo consists of mandatory fields.
#Bean
public IntegrationFlow notifyUpdateVehicleFlow() {
return IntegrationFlows.from(Http.inboundGateway("/update")
.requestMapping(r -> r.methods(HttpMethod.POST))
.requestPayloadType(RequestPojo.class)
.requestChannel(updateChannel())
.replyChannel(updateReplyChannel()))
.get();
}
Is there an easy way to validate fields in the pojo have been set? What I have already tested is using #NotNull SpringValidation but it seems not to be supported with Spring Integration.
Greetings,
smoothny
There is no such a functionality in the Spring Integration. You can use .filter() downstream that Http.inboundGateway() and really perform Validator.validate() from there on the payload.
If you think it must be done somehow on the Http.inboundGateway() and you have strong requirements and clean description, feel free to raise a JIRA on the matter and we will discuss what can be done from the Framework perspective.
Currently, code similar to the following exists in one of our applications:
#Component
public class ProcessRequestImpl {
private ExecutorService executorService;
public processRequest(...) {
// code to pre-process request
executorService.execute(new Runnable() {
public void run() {
ProcessRequestImpl.this.doWork(...);
}
}
}
private void doWork(...) {
// register in external file that request is being processed
// call external service to handle request
}
}
The intent of this is to create a queue of requests to the external service. The external service may take some time to process each incoming request. After it handles each one, it will update the external file to register that the specific request has been processed.
ProcessRequestImpl itself is stateless, in that all state is set in the constructor and there is no external access to that state. The process() method is called by another component in the application.
If this were to be implemented in a Spring Integration application, which of the following two approaches would be best recommended:
Keep the above code as is.
Extract doWork(), into a separate endpoint, configure that endpoint to receive messages on a channel, and to use configuration to achieve the multi threading in place of the executor service.
Some of the reasons we are looking at Spring Integration are as follows:
To remove the workflow logic from the code itself, so that the workflow and the chain of processing is evident on a higher level.
To simplify each class, enhancing readability and testability.
To avoid threading code if possible, and define that at a higher level of abstraction in configuration.
Given the sample code, could those goals be achieved using Spring Integration. Also, what would be an example of the DSL to achieve that.
Thanks
Something like
#Bean
public IntegrationFlow flow() {
return IntegrationFlows.from(SomeGatewayInterface.class)
.handle("someBean", "preProcess")
.channel(MessageChannels.executor(someTaskExecutorBean())
.handle("someBean", "doWork")
.get();
The argument passed to the gateway method become the payload of the preprocess method, which would return some object that becomes the message payload, which becomes the parameter passed to doWork.
I'm currently building a CQS-style DDD-application. I'm having some doubts on how all 'components' work with each other.
But first I'll give a brief overview about the application's structure:
ApplicationService
-> Receives command objects
-> doesn't return any results
-> Acts on Domain model
-> Speaks with Aggregate repository for domain modifications
QueryService
-> Bypasses domain model; doesn't speak with Aggregate Repositories
-> Executes queries against database to populate view
-> Returns 'Representation' objects
REST Controller
-> Receives HTTP requests and binds 'body content' & request params to Command objects
-> delegates to ApplicationService for POST, PUT & DELETE requests
-> Always returns at least some HTTP code
-> delegates to QueryService for GET requests
Infrastructure
-> Handles persistence to DB
-> Contains some scheduling operations
-> Handles foreign domain events our domain model is 'interested' in
'Open Host'
-> This is mainly a Facade to be used by other domains
-> Facade delegates methods to ApplicationService for domain modifications and to QueryService for data retrieval (bypassing Repositories)
My Questions:
Is it OK that a DomainEventHandler corresponds with a Repository and invokes some methods on a Aggregate? Or should it always correspond with an ApplicationService?
QueryService returns 'Representation' objects. These are used by UI AND by 'Open Host' Facade as return value. Is it OK these objects are reused as return value by Facade? Or should Facade create their own Objects, even the results are basically the same?
ApplicationService takes 'Commands' as input parameters. Is it OK these Commands are also used by the Open Host Facade? Or should the Facade only accept primitive values and convert them to Commands when delegating to ApplicationService?
DomainEventHandlers seem to reside on 'Infrastructure' layer. Is it possible that an ApplicationService or Domain Service also subscribes to an Domain Event? Or is this always an Infrastructure responsibility?
All advice is very welcome!
Is it OK that a DomainEventHandler corresponds with a Repository and invokes some methods on a Aggregate? Or should it always correspond with an ApplicationService?
In my experience, any handlers are application services.
QueryService returns 'Representation' objects. These are used by UI AND by 'Open Host' Facade as return value. Is it OK these objects are reused as return value by Facade? Or should Facade create their own Objects, even the results are basically the same?
There is a lot of discussion here about the differences between Open Host service and Application Service. It is not clear to me who would be using Open Host service, or why it exists.
ApplicationService takes 'Commands' as input parameters. Is it OK these Commands are also used by the Open Host Facade? Or should the Facade only accept primitive values and convert them to Commands when delegating to ApplicationService?
I would pass in primitives on the edges of the application and convert them into commands which are then handled in the Application Services
DomainEventHandlers seem to reside on 'Infrastructure' layer. Is it possible that an ApplicationService or Domain Service also subscribes to an Domain Event? Or is this always an Infrastructure responsibility?
I've always considered my handlers to be Application Services - things that are responsible for orchestrating a user case. So the use case might be "when EventX is received, send an email and update the database". In this example, you would probably consider "the code that sends the email" and "the code that saves to the database" to be infrastructure concerns, but the handler itself would not be.
public class ExampleHandler : IHandle<ExampleEvent>
{
private IRepository _repo;
private ISendEmails _emailer;
public ExampleHandler(Repository repo, ISendEmails emailer)
{
.... set the private fields..
}
public void When(ExampleEvent event)
{
_emailer.Send(event.whatever);
_repo.Save(something);
}
}
To be honest, I don't really think in terms of layers - i prefer a hexagonal architecture style of thinking. In the above example, the event handlers would just have dependencies injected into them and then go about their business.
I need to dynamically assign messages to MessageChannels in my Spring Integration Context.
I can do this by getting the MessageChannel bean from the context when I know the names of the MessageChannel I want.
What I need to do is programatically find the name/id of the message channel(s) that are set in my ChannelAdapter/Service.
However, the MessageChannel API does not have a getName() or getId() method associated with it.
Is there a way to find this piece of information?
Thanks in advance.
Let's take look at this task from other side!
What is the reason to get deal with such low API like channels?
Why just don't use the Router pattern on the matter?
If I understand correctly, you want to have some dinamic routing, where you determine a destination channel by some Message property.
So it might be enough just use an expression router:
<int:router input-channel="input" expression="payload.theChannel"/>
i am adding a new method into CalEventLocalServiceImpl using hook...
my code is ..
public class MyCalendarLocalServiceImpl extends CalEventLocalServiceWrapper {
public MyCalendarLocalServiceImpl(CalEventLocalService calEventLocalService) {
super(calEventLocalService);
// TODO Auto-generated constructor stub
}
public List getUserData(long userId) throws SystemException{
DynamicQuery query=DynamicQueryFactoryUtil.forClass(CalEvent.class)
.add(PropertyFactoryUtil.forName("userId").eq(userId));
List deatils=CalEventLocalServiceUtil.dynamicQuery(query);
return deatils;
}
}
liferay-hook.xml:
<service>
<service-type>
com.liferay.portlet.calendar.service.CalEventLocalService
</service-type>
<service-impl>
com.liferay.portlet.calendar.service.impl.MyCalendarLocalServiceImpl
</service-impl>
</service>
my question is how to use getUserData from jsp file.
Can anybody help me out....
i think u didn't gt my question...i want list of events based on USERID from Calendar ...to achieve this task what i need to do??
I assume getUserData() is not overridden but a new method (can't look up currently). This is not what you can do when overriding a service. Instead you'd have to add a new Service and make it available to the portal.
Remember that a customized ("hooked") jsp is running in the portal classloader, while your overloaded service is running in the hook's classloader. Thus, if you create a new service and make the service.jar available to Liferay (e.g. on the global classpath) you can call it from JSPs. The interface of Liferay services can not be extended through an overloaded service.
In case getUserData() is already in the interface (as I said I can't look up currently), you just need to call the CalendarLocalServiceUtil from your jsp and it will be delegated to your wrapper.
Just to add to Olaf's answer and comments...
if you you want to extend CalEventLocalService service with just "getUsetData" and use it in one jsp than building your own service might be overkill. Simply put your code from "getUserData" in jsp. Otherwise follow Olaf's suggestions.