Using setProperty variables as input to XSL - jms

I am currently using setHeader variables in an Apache Camel route as input params to an XSL file. This does not work with setProperty variables, however. Is that not supported in Camel?
Thanks!
UPDATE--
Here's my route...
<camel:route>
<camel:from uri="file:/usr/local/jms_support/update"/>
<camel:convertBodyTo type="String" />
<camel:multicast>
<camel:pipeline>
<camel:bean ref="getPidsForUpdate"/>
<camel:setProperty propertyName="work_or_image"><camel:constant>image</camel:constant></camel:setProperty>
<camel:setProperty propertyName="pid"><camel:constant>1234</camel:constant></camel:setProperty>
<camel:setProperty propertyName="work_pid"><camel:constant>1234</camel:constant></camel:setProperty>
<camel:setProperty propertyName="bibid"><camel:constant>1234</camel:constant></camel:setProperty>
</camel:pipeline>
<camel:pipeline>
<camel:to uri="xslt:xsl/test.xsl"/>
<camel:to uri="file:/usr/local/jms_support/update_test"/>
</camel:pipeline>
</camel:multicast>
</camel:route>

What Camel version do you use?
The Xstl components sets the headers and properties as parameters. You can enable TRACE logging on org.apache.camel.builder.xml, and see which parameters is being added.
See the source code for XsltBuilder and the configureTransformer method in the bottom: https://svn.apache.org/repos/asf/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XsltBuilder.java

I ended up storing the content of the message in a variable and setting the message back to that content after it was changed, like so...
<!-- store original content in header variable -->
<camel:setHeader headerName="marc"><camel:simple>${body}</camel:simple></camel:setHeader>
<!-- run some logic, output gets saved as another header variable, message as this point is now that output -->
<camel:bean ref="getPidsForUpdate"/>
<camel:setHeader headerName="pids"><camel:simple>${body}</camel:simple></camel:setHeader>
....set a bunch of variables based on that output, and then
<!-- get original message to run some more logic-->
<camel:setBody><camel:simple>${headers.marc}</camel:simple></camel:setBody>

Related

The camel message exchange property is not being resolved when used in validator uri component

I am trying to validate the xml file against the xsd using the validator component of camel using blueprint DSL.
<to id="validateXML" uri="validator:file:D:/data/schema/flow.xsd" /> --> working
<to id="validateXML" uri="validator:file:${property.flowXsdPath}" /> --> Not working
flowXsdPath is an exchange property which is set to the xsd location defined by the variable xsdPathVar as given below:
exchange.setProperty("flowXsdPath", exchange.getContext().resolvePropertyPlaceholders(xsdPathVar));
I get exception "Failed to create Producer for endpoint: Endpoint[validator://file:$%7Bproperty.flowXsdPath%7D]. Reason: java.io.FileNotFoundException: ${property.flowXsdPath} (The system cannot find the file specified)"
Though I can access the property value in a log message just before validating the xml file, like this
<log message="File ${file:name} XSD Location = ${property.flowXsdPath}" />
2017-10-16 11:48:44,037 | INFO | processXMLFiles] | file-jms-hums-route | ID-ITEM-XXXXX-49898-1508134722113-0-3 | File 20150603-161237-A412-MFSC.xml XSD Location = D:/data/schema/FSC.xsd
Could you please help how can I access this property inside validator file component?
You should use Dynamic To <toD> instead of <to> to send a message to a dynamic computed Endpoint.
See the related section in http://camel.apache.org/message-endpoint.html

Empty Default String for Property in logback.xml

Our project structure regarding the logback.xmls looks like this:
src\main\resources\logback.xml
src\main\resources\config\dev\logback.xml
src\main\resources\config\sjngm\dev\logback.xml
src\main\resources\config\int\logback.xml
src\main\resources\config\local\logback.xml
src\main\resources\config\prod\logback.xml
where the first one references to the environment specific one:
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<contextName>sjngm</contextName>
<jmxConfigurator />
<include resource="config/${extra}${env:-local}/logback.xml" />
</configuration>
Note that extra is not defined most of the times, which is why used this for a while:
<include resource="config/${extra:-}${env:-local}/logback.xml" />
This stopped working at one point, can't remember which version of logback. So we changed it to
<include resource="config/${extra:-./}${env:-local}/logback.xml" />
which also worked for quite a while.
Now we switched to Spring Boot 1.5.4 (contains logback-classic 1.1.11 and logback-core 1.1.11) and it stopped working again. The latest error message is:
11:08:15,020 |-WARN in ch.qos.logback.core.joran.action.IncludeAction - Could not find resource corresponding to [config/./local/logback.xml]
If I go back to
<include resource="config/${extra:-}${env:-local}/logback.xml" />
the message is
11:19:28,778 |-WARN in ch.qos.logback.core.joran.action.IncludeAction - Could not find resource corresponding to [config/extra_IS_UNDEFINEDlocal/logback.xml]
Note that logback still uses "local" as a default string for env, so not all is broken.
What do I do now? Basically I want to tell logback that I want an empty string where extra would be.
This also doesn't work:
<property name="defaultExtra" value="" />
<include resource="config/${extra:-${defaultExtra}}${env:-local}/logback.xml" />
as an empty string seems to always result in an undefined property.
The only working thing I can come up with is this:
<if condition='isDefined("extra")'>
<then>
<include resource="config/${extra}${env:-local}/logback.xml" />
</then>
<else>
<include resource="config/${env:-local}/logback.xml" />
</else>
</if>
plus this into the pom.xml:
<dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
</dependency>
Isn't this nice?! So why did they have to break what was working nicely???
This worked for me:
<property name="extra" value="${logback.myApp.extra:- }" />
Logback seems to trim Whitespace out of the value. So the default value of Space did the trick.
Embedded Whitespace is preserved, which may lead to a FileNotFoundException if Tabs were embedded, but embedded Spaces were ok.
Setting a Property in a Java Initialiser had the desired effect:
System.setProperty("logback.myApp.extra", "\t \tEXTRA_EXTRA_EXTRA\t \t");
The Tabs & Spaces were removed from the Property, which was assigned the value EXTRA_EXTRA_EXTRA
(the Java Initialiser must be invoked before any Logging has taken place & may contain no Logging itself)
You could of course set the Property on the Java Command line.
P.S. if the Property is undefined & you omit the Space (${logback.myApp.extra:-}), it is assigned the value:
logback.myApp.extra_IS_UNDEFINED
...so it may be wise to add a suitable comment:
<property name="extra" value="${logback.myApp.extra:- }" /><!-- N.B. Empty Default value must contain # least 1 Space!! -->

How to integrate legacy executables into Spring Integration application?

I have some legacy programs in C that work based on the input file and the result go to the output file. Both files are specified in the program arguments. So the call looks like the following:
prj.exe a.dat a.out
Based on Artem Bilan suggestion I created the project with the following Spring Configuration file. It works in terms of invoking executable! However, I still have the problem with the outbound channel. First, it contains nothing and I am getting the error "unsupported Message payload type". Second, what is more important, I need to process the output file a.out by a Java program. What is the best way to organize this workflow? Is it possible to substitute the useless in this case inbound-channel-adapter to something useful?
<int-file:inbound-channel-adapter id="producer-file-adapter"
channel="inboundChannel" directory="file:/Users/anarinsky/springint/chem"
prevent-duplicates="true">
<int:poller fixed-rate="5000" />
</int-file:inbound-channel-adapter>
<int:channel id="inboundChannel" />
<int:channel id="outboundChannel" />
<int:service-activator input-channel="inboundChannel" output-channel="outboundChannel"
expression="new ProcessBuilder('/Users/anarinsky/springint/chem/prj', '/Users/anarinsky/springint/chem/a.dat', '/Users/anarinsky/springint/chem/a.out').start()">
</int:service-activator>
<int-file:outbound-channel-adapter
channel="outboundChannel" id="consumer-file-adapter"
directory="file:/Users/anarinsky/springint/chem"/>
Something like this:
<int:service-activator expression="new ProcessBuilder('prj.exe', 'a.dat', 'a.out').start()"/>
?

How to change the header element

I have the following code snippet:
<int-file:inbound-channel-adapter id="filteredFiles"
directory="#{controllerConfig['CYCLE'].params['SEMAPHORE_DIR']}"
channel="semaphoreChannel" filename-pattern="*.xml" prevent-duplicates="false">
<int:poller max-messages-per-poll="1" cron ="#{controllerConfig['CYCLE'].controllerTimer}"/>
</int-file:inbound-channel-adapter>
...
Later in the flow in have a header enricher:
<int:header-enricher id="Channel Name Setter">
<int:header name="channel.id" value="CYCLE"/>
<int:header name="flow.id" overwrite="true" value="#{T(hu.telekom.fdl.util.TimeBasedUUIDGenerator).generateId()}"/>
</int:header-enricher>
The problem is that although I used the overwrite="true" property the flow.id seems unchanged when the inbound-channel-adapter reads the second file.
Thanks,
Expressions with the form #{...} are evaluated once only, during context initialization. You need to use a runtime expression:
<int:header name="flow.id" overwrite="true" expresion="T(hu.telekom.fdl.util.TimeBasedUUIDGenerator).generateId()"/>
i.e. use expression= and remove the #{}.
You only need overwrite="true" if the header is already present on the inbound message to the enricher.

CXF request response logging using log4j: debug

I am trying to enable logging for cxf framework in weblogic application server along with log4j.
I have placed cxf.xml in domain home and have modified setdomainenv to add cxf.xml entry -Dcxf.config.file.url=cxf.xml.
I am setting System.setProperty("org.apache.cxf.Logger", "org.apache.cxf.common.logging.Log4jLogger") before making a webservice call and i have tried configuring all 3 types of configuration specified in http://cxf.apache.org/docs/configuration.html. But nothing seems to work.
I even tried creating org.apache.cxf.Logger file containing value org.apache.cxf.common.logging.Log4jLogger.
my log4j.properties
log4j.rootLogger = DEBUG, FILE
log4j.logger.org.apache.cxf=DEBUG
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=<>/logFile.log
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n
CXF version: 2.7.5
Please suggest if there is change required for me to log both request and response xml?
Make sure your org.apache.cxf.Logger file is under META-INF/cxf. Inspect your war to make sure.
Also, assuming you are defining your services using jaxws, make sure you're defining loggers under the jaxws:inInterceptor and jaxws:outInterceptor
<jaxws:client id="..." serviceClass="..." address="..." >
<jaxws:outInterceptors>
<ref bean="logOut" />
</jaxws:outInterceptors>
<jaxws:inInterceptors>
<ref bean="logIn"/>
</jaxws:inInterceptors>
</jaxws:client>
<bean class='org.apache.cxf.interceptor.LoggingInInterceptor' id='logIn'/>
<bean class='org.apache.cxf.interceptor.LoggingOutInterceptor' id='logOut'/>

Resources