WSO2 MongoDB GridFS - mongodb

I am new to WSO2. I'm using wso2ei-6.5.0. I'm trying to add MongoDB GridFS interaction to a data service I already have working with MongoDB. I'm not finding any information in the WSO2 documentation. Does anyone have any samples that can help me?
Working MongoDB data service code. This will only insert documents into normal Mongo collections, not the GridFS collection where binary data gets stored in chunks.
<data name="MongoDB" serviceGroup="" serviceNamespace="">
<description/>
<config id="MongoAudit">
<property name="mongoDB_servers">localhost</property>
<property name="mongoDB_database">audit</property>
<property name="mongoDB_write_concern">FSYNC_SAFE</property>
<property name="mongoDB_read_preference">PRIMARY</property>
<property name="mongoDB_maxWaitTime">60000</property>
</config>
<query id="mongoInsertAudit" useConfig="MongoAudit">
<expression>mycollection.insert("{ correlation_id: #, flowname: #, payload: #}")</expression>
<param name="correlation_id" sqlType="STRING"/>
<param name="flowname" sqlType="STRING"/>
<param name="payload" sqlType="STRING"/>
<result element="UpdatedRowCount" rowName="Row" useColumnNumbers="true" outputType="XML">
<element column="1" name="Value" exportType="SCALAR" xsdType="xs:integer"/>
</result>
</query>
<operation name="mongoInsertAuditOp">
<call-query href="mongoInsertAudit">
<with-param name="correlation_id" query-param="correlation_id"/>
<with-param name="flowname" query-param="flowname"/>
<with-param name="payload" query-param="payload"/>
</call-query>
</operation>

Related

WSO2 ESB with x-www-form-urlencoded messaage type service call

I have used following code for sending x-www-form-urlencoded message to backed server.
<endpoint xmlns="http://ws.apache.org/ns/synapse" name="FormDataReceiver">
<http uri-template="http://www.eaipatterns.com/MessageEndpoint.html" method="post">
<suspendOnFailure>
<progressionFactor>1.0</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
<retryDelay>0</retryDelay>
</markForSuspension>
</http>
</endpoint>
Also used following API code.
<api xmlns="http://ws.apache.org/ns/synapse" name="FORM" context="/Service">
<resource methods="POST">
<inSequence>
<log level="full"></log>
<property name="name" value="Mark" scope="default" type="STRING"></property>
<property name="company" value="wso2" scope="default" type="STRING"></property>
<property name="country" value="US" scope="default" type="STRING"></property>
<payloadFactory media-type="xml">
<format>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<root xmlns="">
<name>$1</name>
<company>$2</company>
<country>$3</country>
</root>
</soapenv:Body>
</soapenv:Envelope>
</format>
<args>
<arg evaluator="xml" expression="$ctx:name"></arg>
<arg evaluator="xml" expression="$ctx:company"></arg>
<arg evaluator="xml" expression="$ctx:country"></arg>
</args>
</payloadFactory>
<log level="full"></log>
<property name="messageType" value="application/x-www-form-urlencoded" scope="axis2" type="STRING"></property>
<property name="DISABLE_CHUNKING" value="true" scope="axis2" type="STRING"></property>
<call>
<endpoint key="FormDataReceiver"></endpoint>
</call>
<respond></respond>
</inSequence>
</resource>
</api>
But still that message send as rest call manner.
I want something like following message body into backed server. This example message should send through the message body. In here I have used WSO2 Given Example. I have added same wso2esb link for your further reference. wso2. Actually I need to send message XML={{my_xml_message_here}}. Please help me to continue this. Thanks lot.
name=Mark&company=wso2
There is missing Content-Type in header for this type of request. Need to add:
<header name="Content-Type" scope="transport" value="application/x-www-form-urlencoded"/>

WSO2 EI Dataservice as Rest API with sequence calls

I'm new to wso2 and currently I'm trying to expose a mongodb data service as REST API. I followed this tutorial and exposed my data service as Rest resource like this:
<data>
<config>...</config>
<query id="count" useConfig="MongoDB">
<expression>myCollection.count()</expression>
<result outputType="json">{
"Documents": {
"Document": [
{
"Data": "$document"
}
]
}
}</result>
</query>
<operation name="count_op">
<call-query href="count"/>
</operation>
<resource method="GET" path="users/count">
<call-query href="count"/>
</resource>
</data>
Works fine, however when I tried to access the resource from my angular2 project, I stumbled upon the CORS problem. I read up some posts about that and figured I need to modify my Rest API with something like this:
<resource methods="OPTIONS" url-mapping="/*">
<inSequence>
<property action="set" name="HTTP_SC" scope="axis2"
type="STRING" value="200"/>
<property action="set" name="messageType" scope="axis2"
type="STRING" value="application/json"/>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</faultSequence>
</resource>
I tried to integrate this code with my data service definition (the one above) but I can't get it working and it makes me wonder if data service exposed as REST resource are the same thing as Rest APIs? It seems I cannot invoke any elements or other mediators in the data service definition. Do I need to create an actual Rest API for this? If so, how can I use my mongo dataservice as a resource for my Rest API?
EDIT: The CORS error I'm getting from my angular2 project when trying to access the service is "No 'Access-Control-Allow-Origin' header is present on the requested resource." which is another topic. But it led me to edit my data service so I edited my data service resource element and added a new one:
<resource method="GET" path="users/count">
<inSequence>
<property action="set" name="HTTP_SC" scope="axis2" type="STRING" value="200"/>
<property action="set" name="messageType" scope="axis2" type="STRING" value="application/json"/>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</faultSequence>
<call-query href="count"/>
</resource>
<resource method="OPTIONS" path="users/count">
<inSequence>
<property action="set" name="HTTP_SC" scope="axis2"
type="STRING" value="200"/>
<property action="set" name="messageType" scope="axis2"
type="STRING" value="application/json"/>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence>
<sequence key="rest_add_access_control_headers"/>
<respond/>
</faultSequence>
</resource>
rest_add_access_control_headers sequence looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="rest_add_access_control_headers" xmlns="http://ws.apache.org/ns/synapse">
<property name="Access-Control-Allow-Origin" scope="transport"
type="STRING" value="*"/>
<property name="Access-Control-Allow-Methods" scope="transport"
type="STRING" value="GET,POST,PUT,DELETE,OPTIONS"/>
<property name="Access-Control-Allow-Headers" scope="transport"
type="STRING" value="origin, content-type, accept, Authorization"/>
</sequence>
The first seems to be fine but the second one makes my dataservice faulty, giving this error in managemenet console:
DS Code: UNKNOWN_ERROR Source Data Service:- Name: mongodb_dataservice Location: \MongoDB.dbs Description: N/A Default Namespace: http://ws.wso2.org/dataservice Nested Exception:- java.lang.NullPointerException at org.wso2.carbon.dataservices.core.DataServiceFactory.createDataService(DataServiceFactory.java:207) at org.wso2.carbon.dataservices.core.DBDeployer.createDBService(DBDeployer.java:797) at org.wso2.carbon.dataservices.core.DBDeployer.processService(DBDeployer.java:1152) at org.wso2.carbon.dataservices.core.DBDeployer.deploy(DBDeployer.java:201) at org.apache.axis2.deployment.repository.util.DeploymentFileData.deploy(DeploymentFileData.java:136) at org.apache.axis2.deployment.DeploymentEngine.doDeploy(DeploymentEngine.java:807) at org.apache.axis2.deployment.repository.util.WSInfoList.update(WSInfoList.java:144) at org.apache.axis2.deployment.RepositoryListener.update(RepositoryListener.java:377) at org.apache.axis2.deployment.RepositoryListener.checkServices(RepositoryListener.java:254) at org.apache.axis2.deployment.RepositoryListener.startListener(RepositoryListener.java:371) at org.apache.axis2.deployment.scheduler.SchedulerTask.checkRepository(SchedulerTask.java:59) at org.apache.axis2.deployment.scheduler.SchedulerTask.run(SchedulerTask.java:67) at org.wso2.carbon.core.deployment.CarbonDeploymentSchedulerTask.runAxisDeployment(CarbonDeploymentSchedulerTask.java:93) at org.wso2.carbon.core.deployment.CarbonDeploymentSchedulerTask.run(CarbonDeploymentSchedulerTask.java:138) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.NullPointerException at org.wso2.carbon.dataservices.core.engine.DataService.init(DataService.java:352) at org.wso2.carbon.dataservices.core.DataServiceFactory.createDataService(DataServiceFactory.java:190) ... 20 more
Again, I'm not sure if I'm even supposed to put such code in data service definition since the code was meant to be for Rest API definition, the one where you use sequences, mediators etc...
How can I consume my dataservice with an ESB API? Would you please provide an example on how to do that ? I did some research but couldn't find anything.
May I know why you are unable to invoke the data service? Are you getting any error while invocation? if you could provide the logs it will be helpful.
Moreover DSS is used to fetch data from DB ,The best practice is to provide an ESB API which will consume this service rather than exposing DSS service to outside world directly

WSO2 http endpoint

I would like to create a Dynamic HTTP Endpoint in WSO2. I have a sequence (Tconf) which contains all the property values. I am deriving them, using the Property Mediator. Once I get the variables, I am using the SendMediator to send an rest request. Unfortunately it does not seem to be working. Not sure what I am doing wrong, but none of the properties are getting appended. I can see all the properties when I log them.
<api xmlns="http://ws.apache.org/ns/synapse" name="TririgaApi" context="/tririga">
<resource methods="GET" url-mapping="/employee">
<inSequence>
<sequence key="Tconf"/>
<property xmlns:ns="http://org.apache.synapse/xsd" name="uri.var.service.user" expression="get-property('tri.service.user')"/>
<property xmlns:ns="http://org.apache.synapse/xsd" name="uri.var.service.pass" expression="get-property('tri.service.pass')"/>
<property xmlns:ns="http://org.apache.synapse/xsd" name="uri.var.service.host" expression="get-property('tri.service.host')"/>
<property xmlns:ns="http://org.apache.synapse/xsd" name="uri.var.service.path" expression="get-property('tri.service.path')"/>
<property xmlns:ns="http://org.apache.synapse/xsd" name="uri.var.service.wfName" expression="get-property('triPeople.database.employee.wfName')"/>
<send>
<endpoint>
<http method="GET" uri-template="http://host:port/{uri.service.host}{uri.var.service.path}?USERNAME={uri.var.service.user}&PASSWORD={uri.var.service.pass}&ioName={uri.var.service.wfName}"/>
</endpoint>
</send>
</inSequence>
</resource>
</api>
You can configure your sequence and API like below to acheive your requirnment.
Sequence Config:
<sequence xmlns="http://ws.apache.org/ns/synapse">
<property name="uri.var.service.user" scope="default" type="STRING" value="testuser"/>
<property name="uri.var.service.pass" scope="default" type="STRING" value="testpasswd"/>
<property name="uri.var.service.host" scope="default" type="STRING" value="testhost"/>
<property name="uri.var.service.path" scope="default" type="STRING" value="testpath"/>
<property name="uri.var.service.wfName" scope="default"
type="STRING" value="testwfName"/>
</sequence>
API Config:
<api xmlns="http://ws.apache.org/ns/synapse" name="TririgaApi" context="/tririga">
<resource methods="GET" url-mapping="/employee">
<inSequence>
<log>
<property name="====== API IN =====" value="==== INSEQ ===="/>
</log>
<sequence key="conf:/Tconf"/>
<property name="POST_TO_URI" value="true" scope="axis2"/>
<send>
<endpoint>
<http method="GET" uri-template="http://localhost:9000/{uri.var.service.host}/{uri.var.service.path}?USERNAME={uri.var.service.user}&PASSWORD={uri.var.service.pass}&ioName={uri.var.service.wfName}"/>
</endpoint>
</send>
</inSequence>
</resource>
</api>
Thanks.

Transaction mediator in wso2esb 4.8.0

I'm working with wso2esb 4.8.0 and i go through this scenario which is given in wso2esb documentation.I want to copy the records from first database to second database as soon as i delete them from first database.but when i put the duplicate record it should neither delete from first nor insert into second.
my proxy service :
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="Transaction_mediator"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<property name="name"
expression="//name/text()"
scope="default"
type="STRING"/>
<property name="id"
expression="//id/text()"
scope="default"
type="STRING"/>
<property name="price"
expression="//price/text()"
scope="default"
type="STRING"/>
<transaction action="new"/>
<log level="full">
<property name="text" value="Reporting to the DB1"/>
</log>
<dbreport useTransaction="true">
<connection>
<pool>
<dsName>DS1</dsName>
</pool>
</connection>
<statement>
<sql>
delete from c1 where name=?</sql>
<parameter expression="get-property('name')" type="VARCHAR"/>
</statement>
</dbreport>
<log level="full">
<property name="text" value="Reporting to the DB2"/>
</log>
<dbreport useTransaction="true">
<connection>
<pool>
<dsName>DS2</dsName>
</pool>
</connection>
<statement>
<sql>
INSERT into c1 values (?,?,?)</sql>
<parameter expression="get-property('name')" type="VARCHAR"/>
<parameter expression="get-property('id')" type="INTEGER"/>
<parameter expression="get-property('price')" type="INTEGER"/>
</statement>
</dbreport>
<transaction action="commit"/>
<send/>
</inSequence>
<outSequence>
<log level="full"/>
<send/>
</outSequence>
</target>
<description/>
</proxy>
It's working but error occurred when i put duplicate records.At that time It deleting records from first but not inserting into second database.What should i do?is their any solution?let me know.
There is an issue with transaction mediator with JDBC and it has been reported in the wso2 esb issue tracker. Therefore, this may be fixed in feature releases.

Log4j Grouping application logs

I am trying to group logs of multiple related applications to a single log file.
For example I have 3 applications A1.esb, A2.esb, A3.esb.
I want all the logs from these 3 applications get logged to a single log file called A.log.
Similarly, I want B.log for B1.esb, B2.esb and B3.esb.
I am using log4j in JBoss application server.
I have tried to use TCLFilter but I only succeeded in getting individual applications logging to individual log files. As in, A1.esb logging to A1.log, A2.esb logging to A2.log and so on. But I couldn't figure out a way of grouping these loggings.
Thanks a lot guys for your response.
I have managed to fix it by reading some documentation on log4j for jboss.
All I had to do was to specify an appender per application group and inside each appender, I would have a filter chain.
So my log appender shall look like the following.
<appender name="A" class="org.apache.log4j.FileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"></errorHandler>
<param name="Append" value="false"/>
<param name="File" value="${jboss.server.home.dir}/log/A.log"/>
<param name="Threshold" value="INFO"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
</layout>
<filter class="org.jboss.logging.filter.TCLFilter">
<param name="AcceptOnMatch" value="true"/>
<param name="DeployURL" value="A1.esb"/>
</filter>
<filter class="org.jboss.logging.filter.TCLFilter">
<param name="AcceptOnMatch" value="true"/>
<param name="DeployURL" value="A2.esb"/>
</filter>
<filter class="org.jboss.logging.filter.TCLFilter">
<param name="AcceptOnMatch" value="true"/>
<param name="DeployURL" value="A3.esb"/>
</filter>
<filter class="org.apache.log4j.varia.DenyAllFilter"/>
</appender>
and so on for Group B, which would have B1.esb, B2.esb and B3.esb.
Define an appender you will use for these three logs:
<appender name="A" class="org.jboss.logging.appender.DailyRollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="${jboss.server.log.dir}/A.log"/>
<param name="Append" value="true"/>
<param name="Threshold" value="INFO"/>
<param name="DatePattern" value="'.'yyyy-MM-dd"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
</layout>
</appender>
Then route your packages to this logger with additivity=false
<category name="A1.esb" additivity="false">
<priority value="INFO"/>
<appender-ref ref="A"/>
</category>
<category name="A2.esb" additivity="false">
<priority value="INFO"/>
<appender-ref ref="A"/>
</category>
<category name="A3.esb" additivity="false">
<priority value="INFO"/>
<appender-ref ref="A"/>
</category>
I hope you are using different packages for each application.