Custom Mediator in Sequence only run when WSO2 StartUp - wso2

I make a custom mediator that simply print "Hello World" my custom mediator look like this :
public class HelloWorld extends AbstractMediator implements ManagedLifecycle{
public static void helloWorld() {
System.out.println("Hello World");
}
public void init(SynapseEnvironment synapseEnvironment) {
// initializing surcharges map with some symbols
helloWorld();
}
public void destroy() {
// clearing the surcharges contents
}
#Override
public boolean mediate(MessageContext arg0) {
// TODO Auto-generated method stub
return false;
}
}
i call this class in sequence called "Hello" :
<sequence name="Hello">
<class name="com.exec.HelloWorld">
</class>
and i use this sequence in proxy like this :
<proxy xmlns="http://ws.apache.org/ns/synapse" name="FileProxy" transports="vfs" startOnLoad="true" trace="disable">
<target>
<inSequence>
<log level="full"/>
<target sequence="Hello"/>
</inSequence>
</target>
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="transport.PollInterval">15</parameter>
<parameter name="transport.vfs.MoveAfterProcess">file:///Users/Source</parameter>
<parameter name="transport.vfs.FileURI">file:///Users/Target/</parameter>
<parameter name="transport.vfs.FileNamePattern">.*.txt</parameter>
<parameter name="transport.vfs.ContentType">text/plain</parameter>
I expect that everytime i put a file (*.txt) in the Source folder than my sequence will be called. But the problem is the sequence is only called once (when the wso2 esb Startup). How can i make my sequence to be called every time I put a file in the Source folder?
Thanks,

I think it is working as expected, but I think you missunderstood how it works your custom mediator. The message you see is the one showed by the init method, this is when the meditor is created.
This mediator is running everytime you left a file in the folder but the method launched when it happens is "mediator" methos, which implementation does nothing (retrun false). So you should implement mediator method as
public boolean mediate(MessageContext arg0) {
hellowWorld();
return false;
}
and it will show the message as you expect.
Hope it works!

You should call your logic inside mediate method(). And make the return value as true. If you make that as false, mediation engine will return false in the mediation process, and it makes issue in the message flow.
You can check this sample

Related

Logging is not functioning properly after changing Logging Configuration via managemnt console in WSO2 EI 6.5.0

I have developed API which call the class mediator via sequence in WSO2 EI 6.5.0. Initially API logs are getting printed except class mediator logs in Server log.
To enable logs for class mediator as per this, I logged into management console Home> Configure> Logging section and went to section Configure Log4J Loggers , searched log keyword whatever i added inside class mediator to find out class mediator and changed class level to Debug
post this change, nothing is printed when i invoke service via postman, but API response getting. I just restarted server, post this management console url also not getting printed in server logs.
Below is the management console logging configuration image for reference.
Class Mediator:
package com.abc.in;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
import org.apache.synapse.core.axis2.Axis2MessageContext;
/*import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;*/
import java.util.ArrayList;
import java.util.Map;
public class DuplicateHeadersMediator extends AbstractMediator {
// private static final Log logger = LogFactory.getLog(DuplicateHeadersMediator.class);
public boolean mediate(MessageContext messageContext) {
log.info("DuplicateHeadersMediator called********** : " );
trace.info("trace DuplicateHeadersMediator called********** :");
org.apache.axis2.context.MessageContext axis2MessageContext = ((Axis2MessageContext) messageContext)
.getAxis2MessageContext();
Map excessHeaders = (Map) axis2MessageContext.getProperty("EXCESS_TRANSPORT_HEADERS");
log.info("excessHeaders : " + excessHeaders.entrySet());
trace.info("trace excessHeaders : " + excessHeaders.entrySet());
Map transportHeaders = (Map) axis2MessageContext.getProperty("TRANSPORT_HEADERS");
log.info("transportHeaders : " + transportHeaders.entrySet());
trace.info("trace transportHeaders : " + transportHeaders.entrySet());
if (excessHeaders.size() != 0 && transportHeaders.size() != 0) {
for (Object key : transportHeaders.keySet()) {
addPropertiesForExcessHeaders((String)key,excessHeaders,messageContext);
}
}
return true;
}
// Add extra properties to the synapse message context for duplicated headers.
private void addPropertiesForExcessHeaders(String headerName, Map excessHeaders, MessageContext messageContext) {
if (excessHeaders.get(headerName) != null) {
ArrayList<String> list = (ArrayList) excessHeaders.get(headerName);
if (list.size() > 0) {
int i = 2;
for (String value : list) {
String propName = headerName + i;
messageContext.setProperty(propName, value);
log.info("propName : " + propName);
trace.info("trace propName : " + propName);
i += 1;
}
}
}
}
}
API:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/readcookiesapi" name="ReadCookiesAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<log level="custom">
<property name="ReadCookiesAPI" value="is called *****"/>
</log>
<sequence key="HeaderMediatorCall_Sequecne"/>
<log level="custom">
<property expression="$trp:test" name="test1"/>
<property expression="$ctx:test2" name="test2"/>
<property expression="$ctx:test3" name="test3"/>
</log>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Sequence:
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="HeaderMediatorCall_Sequecne" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<log level="custom">
<property name="HeaderMediatorCall_Sequecne" value="B4 *****"/>
</log>
<class name="com.abc.in.DuplicateHeadersMediator"/>
<log level="custom">
<property name="HeaderMediatorCall_Sequecne" value="after *****"/>
</log>
</sequence>
Kindly clarify my doubts mentioned below.
how can I recover default logging mechanism since this change made product logging weird, so that artifacts like API, Sequence etc and server logs i'll get properly
why class mediator logs are not getting printed initially or how can i get those class mediators log in wso2 ei server 6.5.0
When you extend AbstractMediator you should already have an instance of the logger for you to use. Check here. So you don't have to instantiate a new Logger. You can simply use the existing logger.
I have used java.util.logging.Logger to reflect logger inside class mediator. Still not sure why org.apache.commons.logging.LogFactory not printing anything in log.
import java.util.logging.Logger;
public class ParseEmailBody extends AbstractMediator {
private static final Logger logger = Logger.getLogger(ParseEmailBody.class.getName());
public boolean mediate(MessageContext context) {
logger.info("===Inside ParseEmailBody Class Mediator===");
return true;
}

Regd. getting empty response with data mapper in wso2 EI

I am trying to transform json to xml using datamapper and i am getting the empty xml structure but not getting any values in wso2. I have created data mapper dependencies and loaded both input and out structures and used AI to map json -> xml and they mapped correctly.
I tried on eclipse oxygen(esb-6.2.0) and integration studio(v8) also and deployed in EI(6.5.0) but still the behavior is same empty response structure. I kept a log in the in-sequence and it is logging the json request but not the xml response. I am not getting why the issue is happening.
Please provide your thoughts and attached the code to this post. Please do needful
The issue is with the API. In the API we need to specify the input and the output data type. In your case since the transformation is from JSON to XML, the input type needs to be JSON while the output type needs to be XML. But you have defined both as xml which resulted in this issue. Modify the input type to JSON and you will get the expected results
<api xmlns="http://ws.apache.org/ns/synapse" name="DataMapper" context="/data">
<resource methods="POST" url-mapping="/mapper">
<inSequence>
<log separator="/">
<property name="payload" expression="json-eval($.body)"/>
</log>
<datamapper config="gov:datamapper/Wso2DataMapper.dmc" inputSchema="gov:datamapper/Wso2DataMapper_inputSchema.json" outputSchema="gov:datamapper/Wso2DataMapper_outputSchema.json" xsltStyleSheet="gov:datamapper/Wso2DataMapper_xsltStyleSheet.xml" inputType="JSON" outputType="XML"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
input
{
"studNo":"Sample studNo",
"studName":"Sample studName",
"StudGroup":"Sample StudGroup",
"studAddress":{
"addrLine1":"Sample addrLine1",
"AddrLine2":"Sample AddrLine2",
"Mandal":"Sample Mandal",
"District":"Sample District",
"State":"Sample State",
"Country":"Sample Country",
"Zip":"Sample Zip"
}
}
output
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<studentNo>Sample studNo</studentNo>
<studentName>Sample studName</studentName>
<studentGroup>Sample StudGroup</studentGroup>
<studentAddress>
<AddressLine1>Sample AddrLine2</AddressLine1>
<AddressLine2>Sample addrLine1</AddressLine2>
<Mandal>Sample Mandal</Mandal>
<District>Sample District</District>
<State>Sample State</State>
<Country>Sample Country</Country>
<ZIP>Sample Zip</ZIP>
</studentAddress>
</Student>

Setting SOAP Envelope Payload in a Custom Mediator

I am writing a proxy service in WSO2 ESB that accepts a JSON payload and performs some transformations (to a SOAP message) that are quite complex, so we are writing the transformation logic in a Custom Mediator.
As you can see, my custom mediator class sets a property in the message context, and the proxy flow extracts this property and sets the payload (using a Javascript API that I could find).
This results in my SOAP message being "double wrapped" in two envelope tags, and I need to use an enricher with a XPath expression to remove the outer envelope/body tags.
Is it possible to set the XML payload within the custom mediator, thus avoiding to read a property and writing the XML payload in the proxy flow?
The proxy code is listed below:
<?xml version="1.0" encoding="UTF-8"?>
<proxy name="stackOverflowProxy" startOnLoad="true" trace="disable"
transports="jms" xmlns="http://ws.apache.org/ns/synapse">
<target>
<inSequence>
<!-- process incoming request in custom class. the payload is a JSON object -->
<class name="stackOverflow.CustomMediator"/>
<!-- set registration xml string as xml payload -->
<script language="js"><![CDATA[mc.setPayloadXML(new XML(mc.getProperty('mediatorPayload')));]]></script>
<enrich>
<source clone="true"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xpath="$body//soapenv:Envelope/soapenv:Body/*"/>
<target type="body"/>
</enrich>
</inSequence>
<outSequence/>
<faultSequence/>
</target>
</proxy>
And this is the Custom Mediator class:
package stackOverflow;
// imports ...
public class CustomMediator extends AbstractMediator {
public boolean mediate(MessageContext messageContext) {
//messageContext has a json object property
//message is processed and transformed to a SOAPEnvelope (namespaces omitted for simplicity)
//soapEnvelopeString = <Envelope><Body><tag>value</tag></Body></Envelope>
messageContext.setProperty("mediatorPayload", soapEnvelope.toString());
return true;
}
}
In your custom mediator you are setting entire soap message in to a property and in script mediator setting it as payload of the soap message. thats why you are getting double soap env.
in your class mediator set only the body payload to property and then insert that value as payload in main flow using script will solve your issue.
package stackOverflow;
// imports ...
public class CustomMediator extends AbstractMediator {
public boolean mediate(MessageContext messageContext) {
//messageContext has a json object property
//message is processed and transformed to a SOAPEnvelope (namespaces omitted for simplicity)
//**soapPayload = <tag>value</tag>**
messageContext.setProperty("mediatorPayload", soapPayload);
return true;
}
}

How to invoke a simple webservice with camel?

this is my route:
<route>
<from uri="timer:timerName?period=2000"/>
<to uri="ahc:http://www.google.com/search?q=Camel"/>
<log message="${property.CamelHttpResponseCode}"/>
</route>
i want to get response code status but i got this error
Exchange[Message: [Body is null]]
How can i fix this problem ?
I guess reading the "Get the response code" paragraph in the documentation would have helped :
Exchange exchange = template.send("ahc:http://www.google.com/search", new Processor() {
public void process(Exchange exchange) throws Exception {
exchange.getIn().setHeader(Exchange.HTTP_QUERY, constant("hl=en&q=activemq"));
}
});
Message out = exchange.getOut();
int responseCode = out.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
For this simple case you can use camel-jetty. Otherwise there are additional components such as Camel-Restlet for calling and exposing HTTP services.
http://camel.apache.org/jetty.html
<route>
<from uri="direct:start"/>
<to uri="http://www.google.com/search?q=Camel"/>
<route>
Edit:
Just for testing purposes you can do like this:
<route>
<from uri="jetty://localhost:5050/test"/>
<to uri="jetty://http://www.google.com?q=Camel"/>
<route>
Then use a tool like postman in chrome or fiddler and call your localhost service.

property injection in apache cxf using spring

I have the following class
public class HeaderClass{
#Resource
private WebServiceContext webServiceContext;
public String getUserAgent() {
MessageContext msgCtx = webServiceContext.getMessageContext();
HttpServletRequest request = (HttpServletRequest)msgCtx.get(AbstractHTTPDestination.HTTP_REQUEST);
return request.getHeader("user-agent")
}
In my service bean class I want to inject this HeaderClass, so that I can use it there as follows:
package mypack;
#Path("/MyService")
public class MyServiceClass {
//May be some annotation has to be given here which I don't know
HeaderClass header;
public void useHeader() {
//Code to use the header
System.out.println(header.getUserAgent());
}
}
I have the following inside beans.xml file
<jaxrs:server id="SampleService" address="/">
<jaxrs:features>
<cxf:logging />
</jaxrs:features>
<jaxrs:serviceBeans>
<ref bean="MyServiceClass"/>
</jaxrs:serviceBeans>
</jaxrs:server>
<bean id="MyServiceClass" class="mypack.MyServiceClass"/>
I don't know how to add the property HeaderClass in the bean "MyServiceClass"
I am using apache cxf with spring configuration file (beans.xml).
Please help.
One way to achieve this is to add those lines to your beans.xml:
<bean id="HeaderClass" class="mypack.HeaderClass"/>
<bean id="MyServiceClass" class="mypack.MyServiceClass">
<property name="header" ref="HeaderClass" />
</bean>
You may also need to add a setHeader() method to your MyServiceClass.