Why JPA/Hibernate is not performing batching? - jpa-2.0

My Entity class looks as follows :
#Entity
class Entity {
private UUID id;
private String name;
// normal getters and setters
#PrePersist
public void init(){
if(id == null){
setId(UUID.randomUUID());
}
}
In my persistence.xml, I have following :-
<property name="hibernate.jdbc.batch_size" value="30"/>
<property name="hibernate.order_inserts" value="true"/>
<property name="hibernate.order_updates" value="true"/>
Within a single transaction,
I am calling "entityManager.persist(myEntity)" inside a for loop. The exact number of iterations may vary across multiple runs.
In my logging configuration I have following,
<logger category="org.hibernate.jdbc.BatchingBatcher">
<level name="DEBUG"/>
</logger>
<logger category="org.hibernate.jdbc.AbstractBatcher">
<level name="DEBUG"/>
</logger>
<logger category="org.hibernate.persister.entity.AbstractEntityPersister">
<level name="DEBUG"/>
</logger>
However, in the server's log, I can not find any evidence of any sort of batching being performed during insert.
I am using Hibernate as a JPA provider.
Any idea what am I doing wrong here ?

Related

Why is onMessage() (JMS Listener) not called during unit tests

From console output below, as far as I could see, my embedded ActiveMQ was initialized correctly and it is answering at 61616 port.
When I run the test below, I assume the message is successfully sent because I can debug line-by-line and see both simpleSend() and sendMessage() been ran.
I was expecting to see onMessage been triggered twice but It is not really occurring.
In the code below, when I run the unit test, I understand that:
1 - an embedded ActiveMQ with its broker is started
2 - an instance of MyListener is passed to org.springframework.jms.listener.DefaultMessageListenerContainer
So, what I am missing here in order to test onMessage()?
Console
INFO | Using Persistence Adapter: MemoryPersistenceAdapter
INFO | Apache ActiveMQ 5.14.1 (localhost, ID:win10-cha-55866-1509636415848-0:1) is starting
INFO | Listening for connections at: tcp://127.0.0.1:61616
INFO | Connector tcp://localhost:61616 started
INFO | Apache ActiveMQ 5.14.1 (localhost, ID:win10-cha-55866-1509636415848-0:1) started
INFO | For help or more information please see: http://activemq.apache.org
Sender
import javax.jms.Queue;
import org.springframework.jms.core.JmsTemplate;
public class SampleJmsMessageSender {
private JmsTemplate jmsTemplate;
private Queue queue;
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void setQueue(Queue queue) {
this.queue = queue;
}
public void simpleSend() {
jmsTemplate.send(queue, s -> s.createTextMessage("hello queue world"));
}
public void sendMessage(final MyPojo mp) {
this.jmsTemplate.convertAndSend(mp);
}
}
EmbeddedActiveMQ.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Embedded ActiveMQ Broker -->
<amq:broker id="broker" useJmx="false" persistent="false"
useShutdownHook="false">
<amq:transportConnectors>
<amq:transportConnector uri="tcp://localhost:61616" />
</amq:transportConnectors>
</amq:broker>
</beans>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- JmsTemplate Definition -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="defaultDestination" ref="destinationQueue" />
<property name="messageConverter" ref="myMessageConverter" />
</bean>
<bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<constructor-arg index="0" value="tcp://localhost:61616" />
</bean>
<!-- ConnectionFactory Definition -->
<bean id="connectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<constructor-arg ref="amqConnectionFactory" />
</bean>
<bean id="destinationQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="IN_QUEUE" />
</bean>
<bean id="SampleJmsMessageSender" class="com.mypackage.spring.jms.SampleJmsMessageSender">
<property name="queue" ref="destinationQueue" />
<property name="jmsTemplate" ref="jmsTemplate" />
</bean>
<bean id="myMessageConverter" class="com.mypackage.spring.jms.SampleMessageConverter" />
<!-- this is the Message-Driven POJO (MDP) -->
<bean id="messageListener" class="com.mypackage.spring.jms.MyListener">
<property name="jmsTemplate" ref="jmsTemplate" />
<property name="queue" ref="destinationQueue" />
</bean>
<!-- and this is the message listener container -->
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destinationName" value="IN_QUEUE" />
<property name="messageListener" ref="messageListener" />
</bean>
</beans>
Unit Test
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DefaultTextMessageSenderIntegrationTest {
private static SampleJmsMessageSender messageProducer;
#SuppressWarnings("resource")
#BeforeClass
public static void setUp() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:EmbeddedActiveMQ.xml", "classpath:applicationContext.xml");
messageProducer = (SampleJmsMessageSender) applicationContext.getBean("SampleJmsMessageSender");
}
#Test
public void test1() {
messageProducer.simpleSend();
}
#Test
public void test2() {
messageProducer.sendMessage(new MyPojo("name", 1));
}
}
Listener
import org.springframework.jms.core.JmsTemplate;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.TextMessage;
import java.util.Map;
public class MyListener implements MessageListener {
private JmsTemplate jmsTemplate;
private Queue queue;
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
public void setQueue(Queue queue) {
this.queue = queue;
}
#Override
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
String msg = ((TextMessage) message).getText();
System.out.println("Received message: " + msg);
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
}
public MyPojo receiveMessage() throws JMSException {
Map map = (Map) this.jmsTemplate.receiveAndConvert();
return new MyPojo((String) map.get("name"), (Integer) map.get("age"));
}
}
pom.xml
<properties>
<springframework.version>4.3.4.RELEASE</springframework.version>
<activemq.version>5.14.1</activemq.version>
<maven-war-plugin.version>2.6</maven-war-plugin.version>
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
<junit.version>4.12</junit.version>
</properties>
<dependencies>
<!-- Spring JMS -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${springframework.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- ActiveMQ -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>${activemq.version}</version>
</dependency>
<!-- test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration>
<warSourceDirectory>src/main/webapp</warSourceDirectory>
<warName>spring-jms</warName>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<finalName>spring-jms</finalName>
</build>
your unit test stops before your listener (asynchronously) consume the message, you have to include that to the test by
Adding a Thread.sleep(2000); to delay the test stop
Or you add MyListener.receiveMessage() and remove the DMLC...
Or you put String msg = null; of MyListener as an instance variable and await in the test this value to be not null...
With actual code, in debug mode you can put a breakpoint on MyListener.onMessage to verify that the message is consumed

how to configure Single event receiver for multiple streams/dynamic stream name in wso2 DAS?

I have configured JMS receiver in WSO2 DAS something like below xml. Now I am configuring receiver xml file for each stream. I see there is no configuration difference except stream name change (streamName="TABLE_NAME"). Is there any way I can use single event receiver for multiple streams to avoid duplicate code.
<?xml version="1.0" encoding="UTF-8"?>
<eventReceiver name="divolte_events_data_receiver" statistics="enable"
trace="enable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="jms">
<property name="transport.jms.DestinationType">queue</property>
<property name="transport.jms.Destination">MyQueue</property>
<property name="java.naming.factory.initial">org.wso2.andes.jndi.PropertiesFileInitialContextFactory</property>
<property name="java.naming.provider.url">repository/conf/jndi.properties</property>
<property name="transport.jms.SubscriptionDurable">false</property>
<property name="transport.jms.ConnectionFactoryJNDIName">QueueConnectionFactory</property>
<property name="transport.jms.UserName">admin</property>
<property encrypted="true" name="transport.jms.Password">***</property>
</from>
<mapping customMapping="disable" type="json"/>
<to streamName="TABLE_NAME" version="1.0.0"/>
Its not possible with DAS as receivers are bound to streams and the flow. For JMS it looks like same but generally there are other receiver types which requires its own receiver. Ex:- In Http receivers different endpoints will be created for each receiver where as JSON event structure is based on the stream bound to the receiver

Unable to unmarshall the CXF web service object to XML

I'm trying to call a web service exposed by third party. After receiving the response I'm wrapping the response to the appropriate class. While marshalling the object of the wrapper class to xml string using "jaxb" I'm getting the error as:
org.apache.camel.NoTypeConversionAvailableException: No type converter
available to convert from type:
com.unifyv4.ws.CreateOrganisationResponse to the required type:
java.io.InputStream with value
com.unifyv4.ws.CreateOrganisationResponse#312ea56e
Detailed Stack Trace:
n | BodyType com.unifyv4.ws.CreateOrganisationResponse
n | Body
com.unifyv4.ws.CreateOrganisationResponse#2c9a5080
n | ]n | n | Stacktracen |
java.io.IOException:
org.apache.camel.NoTypeConversionAvailableException: No type converter
available to convert from type:
com.unifyv4.ws.CreateOrganisationResponse to the required type:
java.io.InputStream with value
com.unifyv4.ws.CreateOrganisationResponse#2c9a5080
at org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:141)[235:org.apache.camel.camel-jaxb:2.15.1.redhat-621084]
at org.apache.camel.processor.MarshalProcessor.process(MarshalProcessor.java:83)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:448)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:191)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.Pipeline.access$100(Pipeline.java:44)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.Pipeline$1.done(Pipeline.java:139)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.CamelInternalProcessor$InternalCallback.done(CamelInternalProcessor.java:251)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.RedeliveryErrorHandler$1.done(RedeliveryErrorHandler.java:460)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.management.InstrumentationProcessor$1.done(InstrumentationProcessor.java:86)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.processor.SendProcessor$1.done(SendProcessor.java:149)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.component.cxf.CxfClientCallback.handleResponse(CxfClientCallback.java:61)[207:org.apache.camel.camel-cxf:2.15.1.redhat-621084]
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:823)[74:org.apache.cxf.cxf-core:3.0.4.redhat-621084]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1644)[96:org.apache.cxf.cxf-rt-transports-http:3.0.4.redhat-621084]
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream$1.run(HTTPConduit.java:1155)[96:org.apache.cxf.cxf-rt-transports-http:3.0.4.redhat-621084]
at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$3.run(AutomaticWorkQueueImpl.java:428)[74:org.apache.cxf.cxf-core:3.0.4.redhat-621084]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)[:1.8.0_40]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)[:1.8.0_40]
at org.apache.cxf.workqueue.AutomaticWorkQueueImpl$AWQThreadFactory$1.run(AutomaticWorkQueueImpl.java:353)[74:org.apache.cxf.cxf-core:3.0.4.redhat-621084]
at java.lang.Thread.run(Thread.java:745)[:1.8.0_40]
Caused by: org.apache.camel.NoTypeConversionAvailableException: No
type converter available to convert from type:
com.unifyv4.ws.CreateOrganisationResponse to the required type:
java.io.InputStream with value
com.unifyv4.ws.CreateOrganisationResponse#2c9a5080
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.mandatoryConvertTo(BaseTypeConverterRegistry.java:177)[198:org.apache.camel.camel-core:2.15.1.redhat-621084]
at org.apache.camel.core.osgi.OsgiTypeConverter.mandatoryConvertTo(OsgiTypeConverter.java:122)[204:org.apache.camel.camel-blueprint:2.15.1.redhat-621084]
at org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:172)[235:org.apache.camel.camel-jaxb:2.15.1.redhat-621084]
at org.apache.camel.converter.jaxb.JaxbDataFormat.marshal(JaxbDataFormat.java:138)[235:org.apache.camel.camel-jaxb:2.15.1.redhat-621084]
... 20 more
Below is the blueprint.xml file and class where I'm trying to marshal the response object.
Blueprint.xml
<cxf:rsServer id="crmRequest" address="http://localhost:9002/rest/" serviceClass="com.spectranet.createEnterpriseCustomer.ReceiveEnterpriseRequest" />
<bean id="crmRequestBean" class="com.spectranet.createEnterpriseCustomer.ReceiveEnterpriseRequest" />
<bean id="myProcessor" class="com.spectranet.createEnterpriseCustomer.MyProcessor" />
<bean id="myProcessor2" class="com.spectranet.createEnterpriseCustomer.MyProcessor2" />
<bean id="dozerConverterLoader" class="org.apache.camel.converter.dozer.DozerTypeConverterLoader">
<argument index="0" ref="myCamel" />
<argument index="1" ref="createOrg" />
</bean>
<bean id="createOrg" class="org.apache.camel.converter.dozer.DozerBeanMapperConfiguration">
<property name="mappingFiles">
<list>
<value>transformation.xml</value>
</list>
</property>
</bean>
<cxf:cxfEndpoint id="unifyCreateOrg" address="http://203.122.58.158:9080/unifyejb/CRMAPI" serviceClass="com.unifyv4.ws.CRMAPI" serviceName="com.unifyv4.ws.CRMAPIService" wsdlURL="wsdl/CRMAPI_WSDL.wsdl" />
<camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
<endpoint uri="dozer:createOrg?sourceModel=com.spectranet.createEnterpriseCustomer.CRMCAFRequest&targetModel=com.unifyv4.ws.CreateOrganisation&mappingFile=transformation.xml" id="crmToUnify"/>
<dataFormats>
<jaxb contextPath="generated" id="generated"/>
<jaxb contextPath="com.unifyv4.ws" prettyPrint="true" encoding="UTF-8" partClass="com.unifyv4.ws.CreateOrganisationResponse" id="myPartialJaxb"/>
</dataFormats>
<route>
<from uri="cxfrs:bean:crmRequest" id="crmRequest">
<description/>
</from>
<convertBodyTo type="com.spectranet.createEnterpriseCustomer.CRMCAFRequest"/>
<to pattern="InOut" ref="crmToUnify"/>
<setHeader headerName="Username">
<constant>admin</constant>
</setHeader>
<setHeader headerName="Password">
<constant>admin</constant>
</setHeader>
<setHeader headerName="operationName">
<constant>createOrganisation</constant>
</setHeader>
<setHeader headerName="operationNameSpace">
<constant>http://ws.unifyv4.com/</constant>
</setHeader>
<log message="customer: ${in.body.organisation.customer}"/>
<log message="ipAddress: ${in.body.sessionObject.ipAddress}"/>
<process ref="myProcessor"/>
<to pattern="InOut" uri="cxf:bean:unifyCreateOrg"/>
<marshal ref="myPartialJaxb"/>
<log message="Messsage from soap call is : ${body}"/>
</route>
</camelContext>
Java Code to Marshal the object to xml.
package com.spectranet.createEnterpriseCustomer;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import com.unifyv4.ws.CreateOrganisationResponse;
import com.unifyv4.ws.Organisation;
public class MyProcessor2 implements Processor {
public void process(Exchange exchng) throws Exception {
CreateOrganisationResponse orgResponse = new CreateOrganisationResponse();
orgResponse.setReturn(exchng.getIn().getBody(Organisation.class));
System.out.println("Organisation Created : " + orgResponse.getReturn().getOrgNo());
exchng.getIn().setBody(orgResponse);
}
}
Kindly please provide any suggestions if any.
First of all, may I know why you want to marshal ?
Looking at route, I dont think you need to marshal any payload.
Just play around XPATH, XSLT & Camel. Camel becomes more complicated in-fact, if you want to marshal and unmarshal. I am not saying its wrong, I am saying its easier without the hassle of marshal, unmarshal, etc. Because ultimately thats what all frameworks do internally. :)
Eg: https://github.com/gnanagurus/camel-guru-projects/tree/master/camel-cxf-geocoder-example
Cheers
This issue can come when the generated class does not contain XML root element tag. Because of it, framework can not explicitly convert the objects to XML and vice versa.
Hence you are creating the response via processor, please refer your WSDL and create the wrapper response as well.
Thanks
Shiv

MUnit testing a flow with collection-aggregator

I am trying to write MUnit tests for my Mule flows. I want to write a test for the below flow
<flow name="DownloadFTPFileIntoLocalFlow" processingStrategy="synchronous" tracking:enable-default-events="true">
<quartz:inbound-endpoint jobName="Source-File-Scheduler" cronExpression="${source.pollingfrequency}" startDelay="10000" responseTimeout="10000" doc:name="Quartz">
<quartz:endpoint-polling-job>
<quartz:job-endpoint ref="InputSFTPEndpoint"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<logger message="DownloadFTPFileIntoLocalFlow #[payload.getClass().getName()]" level="INFO" doc:name="Logger"/>
<set-property propertyName="MULE_CORRELATION_GROUP_SIZE" value="#[java.lang.Integer.MAX_VALUE]" doc:name="GroupsizeForExceptionAggregator"/>
<set-property propertyName="MULE_CORRELATION_ID" value="#[java.util.UUID.randomUUID().toString()]" doc:name="corelationIdForExceptionAggregator"/>
<set-variable variableName="originalPayload" value="#[payload]" doc:name="originalPayload"/>
<byte-array-to-object-transformer doc:name="Byte Array to Object"/>
<flow-ref name="ProcessCSVFlow" doc:name="ProcessCSVFlow" />
<exception-strategy ref="Default_Exception_Strategy" doc:name="DownloadFTPFileIntoLocalFlow Strategy"/>
</flow>
<sub-flow name="ProcessCSVFlow" tracking:enable-default-events="true">
<transformer ref="enrichWithHeaderAndEndOfFileTransformer" doc:name="headerAndEOFEnricher" />
<set-variable variableName="outputfilename" value="#['Mercury'+server.dateTime.year+server.dateTime.month+server.dateTime.dayOfMonth+server.dateTime.hours+server.dateTime.minutes+server.dateTime.seconds+'.csv']" doc:name="outputfilename"/>
<!-- <set-variable variableName="outputfilename" value="#['Mercury'+server.dateTime.year+':'+server.dateTime.month+':'+server.dateTime.dayOfMonth+'::'+server.dateTime.hours+':'+server.dateTime.minutes+':'+server.dateTime.seconds+'.csv']" doc:name="outputfilename"/> -->
<sftp:outbound-endpoint exchange-pattern="one-way" connector-ref="DestinationSFTP" host="${destination.host}" port="22" responseTimeout="10000" doc:name="DestinationSFTP"
outputPattern="#[outputfilename]" path="${destination.path}" user="${destination.username}" password="${destination.password}"/>
<gzip-compress-transformer/>
<sftp:outbound-endpoint exchange-pattern="one-way" connector-ref="InputSFTP" host="${source.host}" port="22" responseTimeout="10000" doc:name="SourceArchiveSFTP"
outputPattern="#[outputfilename].gzip" path="Archive" user="${source.username}" password="${source.password}"/>
<component doc:name="Delete Read File">
<singleton-object class="component.DeleteProcessedFileComponent">
<property key="host" value="${source.host}"/>
<property key="username" value="${source.username}"/>
<property key="password" value="${source.password}"/>
<property key="workingDirectory" value="${source.path}"/>
</singleton-object>
</component>
<parse-template location="successmessagetemplate.txt" doc:name="Success Template"/>
<smtp:outbound-endpoint host="${smtp.host}" port="${smtp.port}" user="${smtp.from.address}" password="${smtp.from.password}"
to="${smtp.to.address}" from="${smtp.from.address}" subject="${mail.success.subject}" responseTimeout="10000"
doc:name="SuccessEmail" connector-ref="Gmail"/>
<logger message="Process completed successfully" level="INFO" doc:name="Logger"/>
</sub-flow>
Exception handling block
<catch-exception-strategy name="Default_Exception_Strategy">
<flow-ref name="ExceptionHandlingSubflow" doc:name="ExceptionHandlingSubflow"/>
</catch-exception-strategy>
<sub-flow name="ExceptionHandlingSubflow" tracking:enable-default-events="true">
<collection-aggregator timeout="60000" failOnTimeout="false" doc:name="Exception Aggregator"/>
<logger message="Exception has occured Payload is #[payload] and Message is #[message]" level="ERROR" doc:name="Logger"/>
<parse-template location="errormessagetemplate.txt" doc:name="Error Template"/>
<smtp:outbound-endpoint host="${smtp.host}" port="${smtp.port}" user="${smtp.from.address}" password="${smtp.from.password}"
to="${smtp.to.address}" from="${smtp.from.address}" subject="${mail.failure.subject}" responseTimeout="10000"
doc:name="ErrorEmail" connector-ref="Gmail"/>
</sub-flow>
The interesting bit is the exception sub-flow, especially the collection-aggregator
My unit test is
#Test
public void whenMultipleExceptionsOccurInFlow_itShouldSendOnlyOneFailureEmail() throws Exception {
whenMessageProcessor("collection-aggregator")
.withAttributes(attribute("name").ofNamespace("doc").withValue("Exception Aggregator")).thenReturnSameEvent();
destinationSFTP.thenThrow(new RuntimeException("Dummy Exception destinationSFTP"));
MuleEvent testEvent = PropertyEnricher.enrich(testEvent(IOUtils.toInputStream("hello,dummy,payload"))).get();
runFlow("DownloadFTPFileIntoLocalFlow", testEvent);
verifyCallOfMessageProcessor("outbound-endpoint").ofNamespace("smtp")
.withAttributes(attribute("name").ofNamespace("doc").withValue("ErrorEmail"))
.times(1);
}
Now if I do not mock the collection aggregator out my test does not pass, I can understand that this is tricky as the aggregator has a "pause" within it and hence is not an ideal candidate for a unit test, however from a technical standpoint I want to understand what is causing the unit test to fail (when collection-aggregator is not mocked).
My test fails when the collection-aggregator is not mocked.
junit.framework.AssertionFailedError: On smtp:outbound-endpoint.Expected 1 but got 0 calls
at junit.framework.Assert.fail(Assert.java:50)
at org.mule.munit.common.mocking.MunitVerifier.times(MunitVerifier.java:86)
at nz.co.mightyriver.ProcessCsvTest.whenMultipleExceptionsOccurInFlow_itShouldSendOnlyOneFailureEmail(ProcessCsvTest.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
So I've been trying to reproduce this issue:
Production Code
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="9090" doc:name="HTTP Listener Configuration"/>
<flow name="stack-munit-and-aggregationFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<set-payload value="#['lalero_' + new java.util.Date().toString()]" doc:name="Set Payload"/>
<flow-ref name="stack-munit-and-aggregationSub_Flow" doc:name="stack-munit-and-aggregationSub_Flow"/>
<set-payload doc:name="Set Payload" value="#[payload.toString()]"/>
</flow>
<sub-flow name="stack-munit-and-aggregationSub_Flow">
<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator" timeout="10"/>
</sub-flow>
Test Code
package org.mule.munit;
import org.junit.Assert; import org.junit.Test; import org.mule.api.MuleEvent; import org.mule.api.MuleException; import org.mule.munit.runner.functional.FunctionalMunitSuite;
public class TheTest extends FunctionalMunitSuite {
#Test
public void aTest() throws MuleException, Exception { MuleEvent event = runFlow("stack-munit-and-aggregationFlow", testEvent(""));
String payload = (String) event.getMessage().getPayload();
Assert.assertTrue(payload.contains("lalero"));
} }
If you check this code you'll notice that I'm not mocking out the collection aggregator. After a few tests I wasn't able to reproduce your error.
I think the issue could somewhere else.
Could you please share you're code so I can investigate further?
World of warning though, due to an issue discovered in:
How to mock a Java component within Mule Flow using MUnit
You may find a problem if you try to directly test your sub-flow ExceptionHandlingSubFlow. But as you were not doing that in your example code I don't think those two are related.
Cheers!

wso2 esb sequence DB update

I have a problem with the DBreport mediator which output a syntax error, but I can't see any error in the SQL statement
<sequence xmlns="http://ws.apache.org/ns/synapse" name="_dbcount">
<dblookup>
<connection>
<pool>
<password>1234</password>
<user>root</user>
<url>jdbc:mysql://localhost:3306/new_db</url>
<driver>com.mysql.jdbc.Driver</driver>
</pool>
</connection>
<statement>
<sql>
<![CDATA[ select * from consume where username= ? and id_api+ ?]]></sql>
<parameter value="riccardo" type="VARCHAR" />
<parameter value="1" type="INTEGER" />
<result name="result_use" column="use" />
<result name="result_user" column="username" />
</statement>
</dblookup>
<dbreport>
<connection>
<pool>
<password>1234</password>
<user>root</user>
<url>jdbc:mysql://localhost:3306/new_db</url>
<driver>com.mysql.jdbc.Driver</driver>
<property name="autocommit" value="false" />
</pool>
</connection>
<statement>
<sql>
<![CDATA[UPDATE consume SET use=21 WHERE username='riccardo' AND id_api='1']]></sql>
</statement>
</dbreport>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="result for client" expression="get-property('result_user')" />
<property xmlns:ns="http://org.apache.synapse/xsd" xmlns:ns3="http://org.apache.synapse/xsd" name="result for use" expression="get-property('result_use')" />
</log>
</sequence>
The first DB lookup works fine but the second SQL statement in the DBreport cannot update the value:
ERROR - DBReportMediator Error execuring insert statem
ent : UPDATE consume SET use='21' WHERE username='riccardo' AND id_api='1' again
st DataSource : jdbc:mysql://localhost:3306/new_db
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in
your SQL syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'use='21' WHERE username='riccardo' AND id_api=
'1'' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)...
My tables are as follows:
consume (int id, varchar username, int id_api, int use)
users (int id, varchar username, varchar password)
many thanks
EDIT I think there are major issues with DBREPORT AND DBLOOKUP mediators when writing on a Mysql DB, reading is fine, but Update and Insert just don't work...
tell me if I am wrong
Nuvio,
I think this issue arises not because of something wrong in the DBReport mediator. While going through the reported stack trace and the sequence configuration I can see you have defined "use" as a column name. I'm not quite sure how you created a database column with the term "use" because it is a MySQL keyword and MySQL query compiler should throw a SQLException whenever you have a keyword as a column or any other user defined attribute in your SQL query. Having a non-keyword name for in place of the column "use" would fix your problem.
Cheers,
Prabath