attributes validates to null after using Scatter-Gather - attributes

I have a flow that reads a file, distributes to content to 2 subflows using Scatter-Gather and moves the file upon completion to Output/XML or to Failure/XML on failure.
In both scenarios the expression: attributes.fileName fails because attributes is null. How can I set attributes to be persistent?
<flow name="validateFileContent" doc:id="58c241c9-7227-41a8-a67f-5cf4f52bb4bf" >
<file:listener doc:name="Input changed" doc:id="2e6228a7-e153-489a-b6f6-468f67e76475" config-ref="File_Config" directory="Input/XML" watermarkMode="MODIFIED_TIMESTAMP">
<scheduling-strategy >
<fixed-frequency frequency="5" timeUnit="SECONDS" />
</scheduling-strategy>
</file:listener>
<scatter-gather doc:name="Distribute workload" doc:id="15151949-c61d-4629-9fd4-0a4e16d62eec" >
<route >
<flow-ref doc:name="CategoryToType" doc:id="e5d39afa-3b2a-45ef-81c0-afce77a76aef" name="validateCategoryToType" />
</route>
<route >
<flow-ref doc:name="CategoryToSector" doc:id="d3790ba2-b1ac-4511-b748-91adf255344a" name="validateCategoryToSector"/>
</route>
</scatter-gather>
<file:move doc:name="MoveUponSuccess" doc:id="ee659c03-7af5-4a0e-93b0-edb69aefd3ae" sourcePath='#["Input/XML/" ++ attributes.fileName]' targetPath='#["Output/XML/" ++ now() as String{format: "yyyyMMdd_HHmmss"} ++ attributes.fileName]' config-ref="File_Config"/>
<error-handler>
<on-error-propagate enableNotifications="true" logException="true" doc:name="On Error Propagate" doc:id="16001c58-7609-42a6-9bfa-1cd756998f27" >
<logger level="INFO" doc:name="Logger" doc:id="8ec2af18-3e45-4d15-a373-5e9af74723d7" message="#[error]"/>
<file:move doc:name="MoveUponFailure" doc:id="53653598-1d44-4d9a-903c-e82fa61be842" config-ref="File_Config" sourcePath='#["Input/XML/" ++ attributes.fileName]' targetPath='#["Failure/XML/" ++ now() as String{format: "yyyyMMdd_HHmmss"} ++ attributes.fileName]' />
</on-error-propagate>
</error-handler>
</flow>
I tried setting Metadata for input / output attribute, which failed. I could imagine putting it into a var, but I think that there has to be a better solution.
Stacktrace:
Message : "You called the function '++' with these
arguments: 1: String ("Input/XML/") 2: Null (null)
But it expects one of these combinations: (Array, Array) (Date,
Time) (Date, LocalTime) (Date, TimeZone) (LocalDateTime,
TimeZone) (LocalTime, Date) (LocalTime, TimeZone) (Object,
Object) (String, String) (Time, Date) (TimeZone, LocalDateTime)
(TimeZone, Date) (TimeZone, LocalTime)
1| "Input/XML/" ++ attributes.fileName
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Trace: at ++ (line: 1, column:
1) at main (line: 1, column: 14)" evaluating expression:
""Input/XML/" ++ attributes.fileName". Error type :
MULE:EXPRESSION

No, you must save the attribute to a variable if you want to preserve it. There are no guarantees something else in the flows will not override it. For example using any connectors.
Also, metadata is for design time, not execution time.

Related

auto increment value in liferay

I have 2 modules say module 1 aand module 2 ,
module 1 is using liferay and module 2 is not using liferay.
I have a database say myDatabase.
Both module 1 and module 2 are using the same database for the read and write operations .
module 1 is using the service builder and on a particular table XYZ to insert a value it uses the below mentioned code.
XYZ = XYZLocalServiceUtil.createXYZ(0);
XYZ.setX(x);
XYZ.setY(y);
XYZ.setZ(z);
XYZ = XYZLocalServiceUtil.addXYZ(XYZ);
and the module 2 is using the query :
insert into XYZ(x,y,z) values (x,y,z);
Now the problem occurs when the module 2 inserts a record first.
After a insertion by the module 2 , when the module 1(uses service builder) inserts a record it throws the below mentioned exception.
> 06:04:02,824 ERROR [http-bio-8443-exec-38][JDBCExceptionReporter:82]
> Duplicate entry '143' for key 'PRIMARY' 06:04:02,847 ERROR
> [http-bio-8443-exec-38][ClpSerializer:3279]
> java.lang.ClassNotFoundException:
> org.hibernate.exception.ConstraintViolationException
> java.lang.ClassNotFoundException:
> org.hibernate.exception.ConstraintViolationException at
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
> at
> org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
> at java.lang.Class.forName0(Native Method) at
> java.lang.Class.forName(Class.java:278) at
> com.liferay.portal.kernel.util.ClassResolverUtil.resolve(ClassResolverUtil.java:29)
> at
> com.liferay.portal.kernel.util.ClassLoaderObjectInputStream.resolveClass(ClassLoaderObjectInputStream.java:43)
> at
> java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1861)
> at
> java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1744)
> at
> java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2033)
> at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1566)
> at
> java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2278)
> at
> java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:556)
> at java.lang.Throwable.readObject(Throwable.java:914) at
> sun.reflect.GeneratedMethodAccessor1940.invoke(Unknown Source) at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:606) at
> java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1160)
> at
> java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2169)
> at
> java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2060)
> at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1566)
> at java.io.ObjectInputStream.readObject(ObjectInputStream.java:426)
> at
> com.myproject.ClpSerializer.translateThrowable(ClpSerializer.java:3265)
> at com.myproject.XYZLocalServiceClp.addXYZ(XYZLocalServiceClp.java:1)
> at
> com.myproject.XYZLocalServiceUtil.addXYZ(XYZLocalServiceUtil.java:5)
The database has the auto_increment as 144 at that time , still it shows Duplicate entry '143' for key 'PRIMARY'.
Scenario 2 : When the module 2 inserts two records , and now when module 1 tries to insert it again throws the same excetion for 144 . And on again insert operation for 145 and on third attempt it inserts for 146 as it is the current auto increment value now.
The problem is that it is(module 1 - service builder ) is not picking up the latest auto-increment value.
How can it pick the latest auto_increment value .
here is the structure in service.xml of the module 1 :
<entity name="XYZ" local-service="true" remote-service="false" cache-enabled="false" >
<column name="xyzId" type="long" primary="true"
id-type="increment"></column>
<column name="x" type="long"></column>
<column name="y" type="long"></column>
<column name="z" type="long"></column>
</entity>
You can define id-type as identity. If you have a column having auto incrementing primary key. There are 4 different id types. Normally we use increment. But in your case you have to use identity. Hope this will help. Thanks.
<column name="id" type="Integer" primary="true" id-type="identity" />
I was facing the same problem, i had 2 servers running liferay dxp (7.0) using the same database.
Using the solution posted by Varun Arya the SQL query generated by the insert was changed. Instead of passing a defined id to the query, NULL is passed.
I had to add "AUTO_INCREMENT" to the field for it to work.
IDENTITY is a keyword specifiq of Liferay and not recognized by MYSQL.
Regards.
Also, you can create PrimaryKeys by your own using random UUIDs for example. In this case, your primary-key column wont be a Long column anymore but a Varchar column. But, previous IDs need to be migrated in that case.
In this scenario, both modules can be separated clearly since they dont rely on a incremented value.

'int-jdbc:stored-proc-outbound-gateway' is able to MAP ur Model element(s) by itself - is this a true statement?

Currently I am working with JDBC Spring Integration (to be very specific: <int-jdbc:stored-proc-outbound-gateway>) where the scenario is passing n-number of parameters to a stored procedure (ORACLE) and receive one return variable (with '1' or Error Message) along with n-number of CURSORS (sys_refcursor) which may have n-number of columns.
While working on this above scenario with Spring Framework I noticed the following issue(s):
My logic from front-end was, first read the 'return variable'. If that value is 1 then start reading all the CURSORS data or else through exception by redirecting user to the error page. Now, all my CURSORS were not having same number of columns as well as same length/type of data. And in middle layer I was having only one Model class to deal with all the CURSORS return elements. That was the challenge for me!
Previously I dealt with only one CURSOR. and therefore in middle layer I used Mapper class to map all CURSOR elements to my Model element's (getter and setter) to push data to the front. But then when used same concept to deal with n-number of CURSORS -that was truly a nightmare.
let me share what I did before and what I did later to resolve this situation at my end and then will draw my understanding for which will sick EXPARTS opinion at the later part of this post.
For one return variable (with '1' or Error Message) along with one CURSOR:
I had my Gateway definition as follows:
<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-personalinfo"
request-channel="procedureRequestChannel"
data-source="dataSource"
stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
expect-single-result="false"
ignore-column-meta-data="true">
<!-- Parameter Definitions -->
<int-jdbc:sql-parameter-definition name="firstname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="lastname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_ResultSet" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<!-- Parameter Mappings Before Passing & Receiving -->
<int-jdbc:parameter name="firstname" expression="payload[0]"/>
<int-jdbc:parameter name="lastname" expression="payload[1]"/>
<int-jdbc:returning-resultset name="get_ResultSet" row-mapper="com.support.PersonalinfoMapper"/>
</int-jdbc:stored-proc-outbound-gateway>
And in Mapper class I had the following simple Mapping rule:
...
PersonalInfo personalInfo = new PersonalInfo();
try{
personalInfo.setFirstname(resultSet.getString(DBConstants.FIRSTNAME));
personalInfo.setLastname(resultSet.getString(DBConstants.LASTNAME));
...
I did that because in my Model class i was having getter and setter for all CURSOR return elements.
Now, for one return variable (with '1' or Error Message) along with n-number of CURSORS:
I changed my Gateway definition as follows:
<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->
<int-jdbc:stored-proc-outbound-gateway id="outbound-gateway-storedproc-personalinfo"
request-channel="procedureRequestChannel"
data-source="dataSource"
stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
expect-single-result="false"
ignore-column-meta-data="true">
<!-- Parameter Definitions -->
<int-jdbc:sql-parameter-definition name="firstname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="lastname" direction="IN"/>
<int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_curr_1" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_curr_2" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<!-- Parameter Mappings Before Passing & Receiving -->
<int-jdbc:parameter name="firstname" expression="payload[0]"/>
<int-jdbc:parameter name="lastname" expression="payload[1]"/>
</int-jdbc:stored-proc-outbound-gateway>
And secondly I removed the entire row mapping concept, means I didn't have any Mapper class. The only one thing I had was only one Model class with all the CURSORS element name and their getters and setters.
Also notice that in my 'Parameter Definitions', how added those two CURSORS definition but in 'Parameter Mappings Before Passing & Receiving' I have nothing now.
I ran the App without any exceptions and later through Fiddler observed the following JSON data came with RESPOND, means everything PERFECT! ;)
JSON
- {}
- get_curr_1
- -{}
- - firstname=Faisal
- - lastname=Quazi
- get_curr_2
- -{}
- - country=Bangladesh
- - capital=Dhaka
WHAT THE HACK??? Yes...I had the same feelings ;)
Now, can any one plz help to understand what is going on here. Will it be a true statement that "'int-jdbc:stored-proc-outbound-gateway' is able to MAP ur Model element(s) by itself magically???"
Is there any best practice to deal with such kind of situation(s)?
Thank u guys always :)
:-). I guess that by default Spring JDBC uses ColumnMapRowMapper.
So you end up after that gateway with Map<String, <Map<?, ?>>> or something similar. But it is Map anyway.
Since you further convert your payload to JSON and Jackson can get deal with maps prefectly, you finish with correct result.
I can debug it, of course, but deduction says that it can't be differently.
UPDATE
As I said. The answer is here JdbcTemplate#extractOutputParameters:
....
if (outParam.isResultSetSupported()) {
returnedResults.putAll(processResultSet((ResultSet) out, outParam));
}
else {
String rsName = outParam.getName();
SqlReturnResultSet rsParam = new SqlReturnResultSet(rsName, new ColumnMapRowMapper());
returnedResults.putAll(processResultSet((ResultSet) out, rsParam));
if (logger.isDebugEnabled()) {
logger.debug("Added default SqlReturnResultSet parameter named '" + rsName + "'");
}
}
....

Wso2esb : Error while handling null value in switch case

i'm using wso2esb 4.7.0 and wso2dss 3.1.0.i wish to select some column from table.For that i have used following query in dss :
select roleid,rolename,rolecode from mrole where clientid = ? and ModifiedOn = ?
It's working fine in dss as well as esb also.Output is like :
{"roleid":"1077282521908571","rolename":"adminrole","rolecode":"adminrole"},{"roleid":"1077282521908571","rolename":"adminrole","rolecode":"adminrole"},{"roleid":"1077278842127704","rolename":"everyonerole","rolecode":"everyonerole"},{"roleid":"1077282521908571","rolename":"adminrole","rolecode":"adminrole"}
this is one case.Now in second case if i didn't got modifiedon then obvious it shows error in dss like :
Caused by: javax.xml.stream.XMLStreamException: DS Fault Message: Error in 'SQLQuery.processNormalQuery'
DS Code: DATABASE_ERROR
Source Data Service:-
Name: muser_DataService2.0
Location: /muser_DataService2.0.dbs
Description: N/A
Default Namespace: http://ws.wso2.org/dataservice
Current Request Name: Select_Role_Details_Op
Current Params: {clientid=214057357158656, modifiedon=}
Nested Exception:-
java.lang.NumberFormatException: For input string: ""
To solve that i'm using switch case in esb like :
<switch source="get-property('ModifiedOn')">
<case regex="''">
<property name="ModifiedOn" value="0" scope="default" type="STRING"/>
<log level="custom">
<property name="ModifiedOn in case of null: "
expression="get-property('ModifiedOn')"/>
</log>
</case>
</switch>
it shows warning message in esb like :
[2014-10-08 11:43:54,100] WARN - SwitchCase Provided character sequence for switch case condition is 'null'. Switch case will not be executed.
and without executing switch case it directly move forward and generate fault as well as dss shows error as above.How should i give the null condition in switch case?
use boolean xpath function to verify if your property exist :
<filter xpath="boolean(get-property('ModifiedOn'))">
<then>
...
</then>
<else>
...
</else>
</filter>

Custom error message from entity class

How can I create a custom message for the errors that accour in the field annotation?
#Size(max = 10)
or
#Column(name = "NAME" , length = 10)
Now I see a message
CustomerDetailsForm:customerName: Validation Error: Length is greater than allowable maximum of ''10'' .
How can I change this message?
Use the message attribute of the bean validation annotation.
#Size(max=10, message="May not be more than 10 characters.")
To internationalize it, supply ValidationMessages.properties bundle files in the desired locales and use the {} to specify the bundle key, e.g:
#Size(max=10, message="{validation.max_size}")
Alternatively, you can also just use maxlength on the <h:inputText> field so that the enduser already won't be able to enter too much characters.
<h:inputText ... maxlength="10" />

SharePoint CAML View Elements index

I find it hard to find available elements I can use when creating Views. Also on MSDN they are paginated over 3 pages.
Would be nice if this could be improved with examples like what can we do with these properties, because MS documentation does not provide that.
So here they are:
Aggregations
Batch
Case
Column
Column2
ContentTypes
Counter
CurrentRights
Default
Else
Expr
Expr1
Expr2
Field
FieldPrefix
FieldProperty
FieldRef
Fields
FieldSortParams
FieldSwitch
FilterLink
ForEach
GetFileExtension
GetVar
GroupByFooter
GroupByHeader
HTML
HttpHost
HttpPath
HttpVDir
ID
Identity
IfEqual
IfHasRights
IfNeg
IfNew
IfSubString
Join
Joins
Length
Limit
List
ListProperty
ListUrl
ListUrlDir
LookupColumn
MapToAll
MapToControl
MapToIcon
MeetingProperty
Known selectable properties
<MeetingProperty Select="InstanceID" /> returns 20100908
<MeetingProperty Select="MeetingCount" />
<MeetingProperty Select="StartTimeUTC" /> returns 20100908T073000Z
Method
More
PageUrl
ProjectProperty
ProjectedFields
Property
RightsChoices
RightsGroup
ScriptQuote
SelectionOptions
ServerProperty
SetList
SetVar
Switch
Text
Then
ThreadStamp
URL
UrlBaseName
UrlDirName
UserID
WebQueryInfo
Reference: View Schema Elements A-F G-L M-Z

Resources