Spring Webflow Flow Registry Configuration - spring-webflow-2

Please bear with me as this is my first question. Let me know what I can do to improve future questions.
I am trying to learn Spring Webflow, and am slowly wrapping my head around it. I am finding that there are a lot of conventions that the programmer is expected to "just know", and the examples online don't seem to work.
I have cobbled together one example that works as expected, but now I am trying to extend my understanding to the next level in another small project, with my long term goal being a much more complex application. The goal of this exercise is to build a login system that supports different types of client (phone, desktop, etc) with different webflows.
As near as I can tell, I am having trouble configuring the flow registry, probably because I am misunderstanding the convention.
The textbook example I am emulating is this:
<!-- The registry of executable flow definitions -->
<webflow:flow-registry flow-builder-services="flowBuilderServices"
id="flowRegistry" base-path="/WEB-INF/flows/">
<webflow:flow-location path="/welcome/welcome.xml" />
</webflow:flow-registry>
My configuration is this:
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry"
flow-builder-services="flowBuilderServices"
base-path="/WEB-INF/pages/">
<webflow:flow-location path="d/login.xml" />
<webflow:flow-location path="d/signup.xml" />
</webflow:flow-registry>
The log states:
DEBUG o.s.w.d.r.FlowDefinitionRegistryImpl - Registering flow definition 'ServletContext resource [/WEB-INF/pages/d/login.xml]' under id 'd'
DEBUG o.s.w.d.r.FlowDefinitionRegistryImpl - Registering flow definition 'ServletContext resource [/WEB-INF/pages/d/signup.xml]' under id 'd'
Since, under the covers, the flow registry is a simple HashMap, only one of the flow files is being registered, and not as what I would expect.
What am I missing?

Change configuration as mentioned below, this might help you:
<webflow:flow-registry id="flowRegistry"
flow-builder-services="flowBuilderServices"
base-path="/WEB-INF/pages">
<webflow:flow-location path="/d/login.xml" />
<webflow:flow-location path="/d/signup.xml" />
</webflow:flow-registry>
also see Spring Webflow - How to Get List of FLOW IDs

Related

Mule 3 retrieving the placeholder value dynamically

I have a use-case that I need to retrieve the value from my properties file but that key should be derived dynamically from my query params.
How to handle this in MEL or Groovy? I am aware it is possible in DW.
Http request
https://localhost:9898/getStore?search=customer.weststore.name
And my placeholders are -
file.properties
customer.weststore.name=TESTING
customer.eaststore.name=IRERRER
So the way I need to access something like this
<set-variable variableName="westDetail" value="#[message.inboundProperites['customer.weststore.name']" doc:name="Variable"/>
<logger message="${westDetail}" level="INFO" /> --> Failed as no placeholder available
When I tried the above it's failing due to no placeholder as "westDetail" available whereas I need the fetch that particular key from the properties file.
This is something related to this article - https://help.mulesoft.com/s/question/0D52T00004mXTQUSA4/dynamically-read-property-values-from-a-properties-file-in-mule but the only solution provided with DW not MEL or Groovy.
How anyone advises, Is it possible?
I understand that the problem is that you want to query the properties by a key that is obtained at execution.
You are doing it incorrectly. ${} is for evaluating the value of a property, which is done at initialization time of the application. You missed that get the actual value in the set-variable.
#[] is for executing a MEL expression, which happens at execution time. flowVars.westDetail is a MEL expression that returns the value of flow variable westDetail. You can't use a MEL expression to evaluate the property placeholder ${}, because they are evaluated at different times.
A solution is to use a Spring bean to store the properties, instead of a configuration properties placeholder. Then you can assign it to a flow variable and access it like a map.
Example:
<spring:beans>
<spring:bean id="myProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<spring:property name="location" value="classpath:items.properties"/>
</spring:bean>
</spring:beans>
<flow name="myFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<set-variable value="#[app.registry.myProperties]" variableName="props"></set-variable>
<logger message="a=#[flowVars.props['a']]" level="INFO"/>
</flow>
items.properties:
a=1
b=2
c=3
Output:
a=1

Can SpEL in Spring Integration Router use Java's String class methods

This is an extension question to How to use SpEL to read payload and header content in a Spring Integration Router
Technologies in my project
Spring Boot 2
Spring Integration (XML style)
Java 8
Tomcat 9.x/Liberty 19.0.0.1
As a part of my Spring Integration project (REST API with an inbound-http-gateway, that takes an XML input and produces an XML output), this is the setup for my question:
There is a Builder-pattern-based Java object (say, MyPOJO) that is the payload in the flow.
MyPOJO has a String property/instance variable (say, String response) along with a getter and setter.
Somewhere in the flow, MyPOJO gets built and response gets set.
Inside response, there is a keyword/specific piece of text that will determine the further course of the flow.
This said, is it possible to write a Router (using XML configuration) that can check if the response inside Message<MyPOJO> contains that keyword/specific piece of text to determine where to go next?
Illustratively, something like this:
<int:router input-channel="inputChannel" expression="payload.getResponse().contains("keyword")">
<int:mapping value="true" channel="oneRoute"/>
<int:mapping value="false" channel="anotherRoute"/>
</int:router>
When I do this and launch the application, the error is:
nested exception is org.xml.sax.SAXParseException; lineNumber: 44; columnNumber: 98; Element type "int:router" must be followed by either attribute specifications, ">" or "/>"
Specifically speaking, the expression="payload.getResponse().contains("keyword")" part seems to be having an issue getting resolved and this could be something to do with the quotation marks around the keyword
Any help on this is greatly appreciated.
Sincerely,
Bharath
OK. I see you have an XML syntax error. The fix is like this:
expression="payload.getResponse().contains('keyword')"
The keyword is in single quotes, not double.
This is definitely how SpEL works: when you would like to specify a literal in the expression, you need to use single quotes: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions-evaluation

Spring Integration jdbc stored procedure custom rowmapper

I am newbie to Spring Integration and am using Spring 4.2.4.
I am trying to invoke stored procedure with jdbc:stored-proc-outbound-gateway. i am already using spring jdbc.
Stored procedure is returning cursor and am using customRowMapper like below
new SqlOutParameter(A_RC, OracleTypes.CURSOR, null, new MyCustomDataExtractor())
MyCustomDataExtractor implements SqlReturnType and it returns custom object.
Now the question is how can I achieve this in SI jdbc stored proc.piece of my code here..
...
<int-jdbc:sql-parameter-definition name="A_RC" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
...
<int-jdbc:returning-resultset name="A_RC" row-mapper="a.b.c.MyCustomDataExtractor"/>
...
Spring expect this as a row mapper. should I use any transformer here? Please advice.
Note : I have to return multiple resultset.
Actually with the CURSOR type you are good to go with just a returning-resultset and RowMapper implementation.
With that you don't need to worry about any SqlReturnType and just map the row to your domain object directly.
I'm even sure you can rework your MyCustomDataExtractor to the RowMapper contract.
Note: with returning-resultset defintion you don't need to
specify the sql-parameter-definition for the same OUT param. The component identifies them correctly as a OutParameter.
And, yes you can have several returning-resultset for CURSOR parameters.
I added the return-type in the sql-parameter-definition and removed returning-resultset.
<int-jdbc:sql-parameter-definition name="A_RC" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT" return-type="ed"/>
and here "ed" is nothing but the bean reference for a.b.c.MyCustomDataExtractor.
<bean id="ed" class="a.b.c.MyCustomDataExtractor"/>

Mule security filter breaking flow

I'm completely at a loss with my knowledge gap.
Mule 3.3.1 CE. I must use that version for now.
I have a flow which works fine until I try to use a security filter with valid credentials.
The Mule code follows. It won't make much business sense as I've pared it down to the minimum that produces the problem. Normally the outbound call is in a separate flow, but I pulled it into the Main flow for the example.
If I have the security filter on the inbound endpoint commented out and execute this, I get the expected response of the logger message and the "foo" return payload.
<https:connector name="HTTPSConnector" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" doc:name="HTTP\HTTPS">
<https:tls-key-store path="/opt/eai/common/keystore/EAIKeystore.jks" keyPassword="${key.password}" storePassword="${store.password}"/>
</https:connector>
<spring:beans>
<ss:authentication-manager alias="authManager">
<ss:authentication-provider>
<ss:user-service id="userService">
<ss:user name="PortalUser" password="password" authorities="ROLE_USER"/>
</ss:user-service>
</ss:authentication-provider>
</ss:authentication-manager>
</spring:beans>
<mule-ss:security-manager>
<mule-ss:delegate-security-provider name="memory-provider" delegate-ref="authManager"/>
</mule-ss:security-manager>
<flow name="Main" doc:name="Main">
<https:inbound-endpoint exchange-pattern="request-response" host="localhost" port="10029" path="sites/r.v1" mimeType="text/xml" encoding="UTF-8" connector-ref="HTTPSConnector">
<mule-ss:http-security-filter realm="mule-realm"/>
</https:inbound-endpoint>
<custom-transformer class="com.ca.eai.esb.transformer.site.StrategySplittingTransformer" doc:name="Split"/>
<collection-splitter/>
<https:outbound-endpoint exchange-pattern="request-response"
address="${https.outbound.account.sap-nameaddress}"
connector-ref="HTTPSConnector"
mimeType="text/xml" responseTimeout="${https.outbound.timeout}"/>
<logger level="INFO" message="GOT HERE"/>
<set-payload value="foo"/>
</flow>
The custom transformer is also pared down to the minimum:
#Override
public Object transformMessage( MuleMessage message, String outputEncoding )
{
MuleMessageCollection collection = new DefaultMessageCollection( message.getMuleContext() );
collection.addMessage( message );
return collection;
}
If I uncomment the security filter and pass in bad credentials, I get the expected security exception.
If, however, I pass in valid credentials, I get an exception that it can't serialize.
Root Exception stack trace:
java.io.NotSerializableException: org.apache.commons.httpclient.ContentLengthInputStream
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1180)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:346)
at java.util.concurrent.CopyOnWriteArrayList.writeObject(CopyOnWriteArrayList.java:857)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
Can someone tell me why adding a security filter causes this?
This is a bug that has been fixed in 3.4.x.
See this answer https://stackoverflow.com/a/17930063/387927 and the comments below it.

Spring transactions - Mixing #Transactional with <tx:advice> into a custom annotation

My goal is to have some way of declaring my service classes as transactional. I dont want to leave it as an explicit declaration in spring configuration. Many times in past we have created new services and forgot to declare transactions around them. Hence my intention is that if i have something like #TransactionalService custom annotation, it should do the following :-
1. provides transactional support
2. declares some default rules for transactional support as spring currently provides as shown below. But unlike spring, i would like the below to be part of my #TransactionService annotation.
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
Any advice would be valuable?
Sure, instead of creating a new annotation, you could just put your transactionnal services in the same package, and then your pointcut (only one for all you transactionnal services) will look like this :
<aop:config>
<aop:pointcut id="transactionnalServiceMethods" expression="execution(* x.y.transactionnalservice.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionnalServiceMethods"/>
</aop:config>
The advice is the same as above :
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>

Resources