Is it possible to get file name while reading a file using WSO2 ESB File Connector 2 - file

I am doing a simple file read using WSO2 ESB File connection 2. I try to read a .OUT file from the given directory. It reads the first file (alphabetical order?) well but I have no idea which file is read. Is there a (transport?) property that gets populated when a file is read?
Here is my code in a proxy service
<fileconnector.read>
<source>file:///D:/temp</source>
<filePattern>.*\.OUT</filePattern>
<contentType>text/plain</contentType>
</fileconnector.read>
<log level="full"/>
I get the following response
INFO - LogMediator To: /services/SampleProxy.SampleProxyHttpSoap12Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:f5737693-6a51-4044-9134-95cd61eaeaa4, Direction: request, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><text xmlns="http://ws.apache.org/commons/ns/payload">abc,123
qwe,456
</text></soapenv:Body></soapenv:Envelope>

Give it a try like this. (Just a suggestion. I didn't try.)
<log level="custom">
<property name="FileName" expression="$trp:FILE_NAME" />
</log>

If you want to read a particular file, you can pass the full path as a value in source and you can skip the file pattern value.
<fileconnector.read>
<source>file:///D:/temp/abc.OUT</source>
<filePattern></filePattern>
<contentType>text/plain</contentType>
</fileconnector.read>

This is a valid requirement. We will consider this in our future release. Please use [1] to track the progress.
[1] https://wso2.org/jira/browse/ESBCONNECT-192

Related

How to get file uploaded time in wso2 esb sequence

I am using WSO2 inbound endpoint to fetch a file from an FTP server. And I know how to get the file name back. Now my question is how to get the file uploaded time back (or the last modified time)?
This is the code to get the file name.
<property expression="get-property('transport', 'FILE_NAME')" name="ftp.var.filename"
xmlns:ns="http://org.apache.synapse/xsd"
xmlns:ns2="http://org.apache.synapse/xsd"/>
I think there should be a similar code to get the timestamp of the file.
With the following property, you will be able to get the last modified time of the file polled from the inbound endpoint.
`<property expression="get-property('transport', 'LAST_MODIFIED')" name="ftp.var.last.modified.time" xmlns:ns="http://org.apache.synapse/xsd"/>`
Add this to the relevant sequence to further process and following is a sample sequence in which the file name and the last modified time is logged.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="fileSequence" onError="fault" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property expression="get-property('transport', 'FILE_NAME')"
name="ftp.var.filename" xmlns:ns="http://org.apache.synapse/xsd"/>
<property
expression="get-property('transport', 'LAST_MODIFIED')"
name="ftp.var.last.modified.time" xmlns:ns="http://org.apache.synapse/xsd"/>
</log>
</sequence>
Please check whether this meets your requirement and please refer [1] to further clarify this.
[1]-https://github.com/wso2/wso2-synapse/blob/master/modules/transports/core/vfs/src/main/java/org/apache/synapse/transport/vfs/VFSTransportListener.java#L767

Camel reverse proxy - no response stream caching

I am trying to implement a memory efficient http reverse proxy that is only working on streams. The Jetty consumer places the input stream into the exchange and I can hook it up with a http producer to forward the request. No problem there.
However, all http producers that I am aware of (Jetty, http4, netty-http) read the response stream into heap memory and place its contents into the exchange in some form or another instead of a handle to the stream. And none of them seem to offer an option to make them do so.
I found this thread which describes the same problem and also suggests a solution. But looking at the code of the http4 HttpProducer in Camel 2.13.1, it does not look like the proposed change made it into the Camel code base after all.
Is there any way to achieve the stream-only approach with Camel? So, with a minimal memory footprint I could do something along the line of this:
<route id="reverse_proxy" streamCache="false">
<from ref="jetty.http.server"/>
<bean ref="streamHolder" method="enableCaching"/>
<bean ref="streamHolder" method="parsePayloadHeaderInfoAndDoStuff"/>
<bean ref="streamHolder" method="resetStream"/>
<to ref="http.client"/> <!-- Register completion synchronization hook to close stream. -->
<bean ref="streamHolder" method="enableCaching"/>
<bean ref="streamHolder" method="parsePayloadResponseHeaderAndDoStuff"/>
<bean ref="streamHolder" method="resetStream"/>
</route>
EDIT - Additional info on where exactly the input stream ends up in memory:
http4: Everything happens in org.apache.camel.component.http4.HttpProducer::process() -> populateResponse(..) -> extractResponseBody(..) -> doExtractResponseBodyAsStream(); and here the original stream is copied into an instance of CachedOutputStream.
Jetty: org.eclipse.jetty.client.AsyncHttpConnection::handle() -> org.eclipse.jetty.http.HttpParser::parseNext() will fill a byte array in org.eclipse.jetty.client.ContentExchange which is a CachedExchange which is a HttpExchange.
netty-http: Builds a pipeline that assembles the HttpResponse content as a composite ChannelBuffer. The wrapped channel buffers make up the complete response stream.
I have debugged all three clients and did not stumble across a branch not taken that would leave me with the original input stream as the exchange body.
This is reproducible with a route as simple as this:
<camelContext id="pep-poc">
<endpoint id="jetty.http.server" uri="jetty:http://{{http.host.server}}:{{http.port.server}}/my/frontend?disableStreamCache=true"/>
<endpoint id="http.client" uri="jetty:http://{{http.host.client}}:{{http.port.client}}/large_response.html?bridgeEndpoint=true&throwExceptionOnFailure=false&disableStreamCache=true"/>
<route id="reverse_proxy" startupOrder="10" streamCache="false">
<from ref="jetty.http.server"/>
<to ref="http.client"/>
</route>
</camelContext>
I have an Apache2 return a 750MB file as large_response.html.
EDIT 2
Indeed this is a problem with all available HTTP producers. See this thread on the Camel mailing list and the corresponding JIRA ticket.
They do not read the stream into memory unless you access the message body on demand, and tell Camel to read it into memory as a String type etc.
See this cookbook example how to do a stream based proxy
http://camel.apache.org/how-to-use-camel-as-a-http-proxy-between-a-client-and-server.html

Camel Processor And .cfg File

Does anybody know if there is a chance to read a .cfg file directly in a camel processor?
My .cfg looks like:
key=value
key=value
...
And I want to get a specific value after its key, but I want to do that in a processor!
Thank you!
Just use plain old Java:
Reader reader = new FileReader("myprop.cfg");
Properties prop = new Properties();
prop.load(reader);
Also have a look at Read contents of a file containing key value pairs without normal parsing. As Claus Ibsen stated, there are good chances that a File -> Properties converter will be added in future Camel versions, see https://issues.apache.org/jira/browse/CAMEL-7312.
If you just need to access some key value pairs, use Camel's properties component:
<bean id="properties" class="org.apache.camel.component.properties.PropertiesComponent">
<property name="location" value="classpath:com/mycompany/myprop.cfg"/>
</bean>
Access the property in your routes with the {{key}} syntax:
<to uri="{{cool.end}}"/>
The Camel documentation shows all possibilities.

iBatis - Why is sqlMapConfig.xml unable to find the sql maps defined in it?

I have a sqlMapConfig.xml that has three SQLMaps defined in it.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<!-- Statement namespaces are required for Ibator -->
<settings enhancementEnabled="true" useStatementNamespaces="true"/>
<!-- Setup the transaction manager and data source that are
appropriate for your environment
-->
<transactionManager type="JDBC">
<dataSource type="SIMPLE" >
<property name="JDBC.Driver"
value="com.mysql.jdbc.Driver"/>
<property name="JDBC.ConnectionURL"
value="jdbc:mysql://localhost:3306/sug"/>
<property name="JDBC.Username"
value="root"/>
<property name="JDBC.Password"
value="admin"/>
</dataSource>
</transactionManager>
<!-- SQL Map XML files should be listed here -->
<sqlMap resource="com/tatakelabs/dbmaps/categories_SqlMap.xml" />
<sqlMap resource="com/tatakelabs/dbmaps/pro_SqlMap.xml" />
<sqlMap resource="com/tatakelabs/dbmaps/pro_category_SqlMap.xml" />
</sqlMapConfig>
I get a runtime error - Cause: java.io.IOException: Could not find resource com/tatakelabs/dbmaps/categories_SqlMap.xml
categories_SqlMap.xml is present in that location. I tried changing the location of the map xml, but that did not help. sqlMapConfig.xml validates against the DTD. categories_SqlMap.xml also validates against the right DTD. I am at my wits end trying to figure out why it can't find the resource. The sqlMap files are generated by iBator.
This was happening because the sqlmap file location was not getting copied to target. Added a copy goal and that fixed it.
I had the same problem. It appears the problem lies with the location of the config file. Thus, its in relation of the project resource structure.
I moved the config file in the same package as the mapper classes and it worked. In this case try moving all the resources to this package and update the resource attributes to:
<sqlMap resource="categories_SqlMap.xml" />
<sqlMap resource="pro_SqlMap.xml" />
<sqlMap resource="pro_category_SqlMap.xml" />
Solved it.
I moved the xml file to where the Pojo was located and provided the path as follows:
<sqlMap resource="com/heena/ibatis/model/jsr/jsr.xml" />
And it worked.
place it ...src\java\abc.xml under the Source Packages directory.
If you are using Spring, you can use a SqlMapClientFactoryBean specifying property "mappingLocations". In this property you can specify a generic path, such as "com/tatakelabs/dbmaps/*_SqlMap.xml" or with a variable such as ${mapfiles}, that will be resolved by Spring as an array of file names. This lets you omit sqlMap element in sqlMapConfig. This technique will run with iBatis 2.3.4 on. However sql-map-config-2.dtd is also contained inside iBatis.jar, so you can experience some parsing errors, as /com/ibatis/sqlmap/engine/builder/xml/sql-map-config-2.dtd may have a bug. In this case you may want to replace it inside the jar with the one from the URL:
http://ibatis.apache.org/dtd/sql-map-config-2.dtd.

wpf & validation application block > message localization > messageTemplateResource Name&Type

I'm trying to write validation rules for my data objects in a WPF application. I'm writing them in the configuration file, and so far they are working fine.
I'm stumped on how to localize the messages using messageTemplateResourceName and messageTemplateResourceType. What I know is that the strings can be writen in a resource file, given a name and referenced by that name. I get the idea, but i haven't been able to make this work.
<ruleset name="Rule Set">
<properties>
<property name="StringValue">
<validator lowerBound="0" lowerBoundType="Ignore" upperBound="25"
upperBoundType="Inclusive" negated="false" messageTemplate=""
messageTemplateResourceName="msg1" messageTemplateResourceType="Resources"
tag=""
type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation"
name="String Length Validator" />
</property>
</properties>
</ruleset>
Where is the resource file and what value do I pass to messageTemplateResourceType?
I have tried writing the messages in the shell project's resource file but no sucess trying to retrieve the value. I only get the default built-in message.
I've tried
messageTemplateResourceType="typeof(Resources)"
messageTemplateResourceType="Resources"
messageTemplateResourceType="Resources.resx"
messageTemplateResourceType="typeof(Shell)"
messageTemplateResourceType="Shell"
messageTemplateResourceType="Shell,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null"
I've also tried adding a new resource file in the shell project, and adding a resource file to the data object's library. I'm all out of ideas Does anyone have any suggestions? I'm not even married to the idea of resource files, so if there are other ways to localize these messages I'd love to know!
thanks
You need to create your own resource file and then point the messageTemplateResourceType attribute to your fully qualified resource type. As long as the resource file can be loaded at runtime you should be fine.
<ruleset name="Rule Set">
...
messageTemplateResourceName="msg1"
messageTemplateResourceType="My.Fully.Qualified.ResourceType, My.AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
...
</ruleset>
An alternate way to do it would be use the messageTemplate as a key and write custom code to look up the actual localized string based on the messageTemplate key (either from a resource file or from a database or wherever else you are storing it).

Resources