How to configure the EHCache with CXF in Mule - web-services

I have a SOAP webservice as follow :-
<spring:bean id="cacheManager" name="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
<spring:bean id="cache" name="cache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<spring:property name="cacheManager" ref="cacheManager"/>
<spring:property name="cacheName" value="dbCache"/>
<spring:property name="maxElementsInMemory" value="10000"/>
<spring:property name="eternal" value="false"/>
<spring:property name="timeToIdle" value="${timeToIdle}"/>
<spring:property name="timeToLive" value="${timeToLive}"/>
<spring:property name="overflowToDisk" value="true"/>
<spring:property name="maxElementsOnDisk" value="10000000"/>
<spring:property name="diskPersistent" value="false"/>
<spring:property name="diskExpiryThreadIntervalSeconds" value="5"/>
<spring:property name="memoryStoreEvictionPolicy" value="LRU"/>
<!-- Cache Expiry -->
</spring:bean>
</spring:beans>
<ee:object-store-caching-strategy name="cachingStrategy" doc:name="cachingStrategy">
<custom-object-store class="com.anirban.EHCatche.EhcacheObjectStore">
<spring:property name="cache" ref="cache"/>
</custom-object-store>
</ee:object-store-caching-strategy>
<!-- Catch Strategy ends -->
<flow name="ServiceFlow" doc:name="ServiceFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP" />
<ee:cache doc:name="Cache" cachingStrategy-ref="cachingStrategy">
<cxf:jaxws-service serviceClass="com.test.services.schema.maindata.v1.MainData" doc:name="SOAP"/>
<component class="com.test.services.schema.maindata.v1.Impl.MainDataImpl" doc:name="JavaMain_ServiceImpl"/>
</ee:cache>
</flow>
Now as you can see .. I have wrapped the cxf:jaxws-service and component class under ee:cache block ..
The Webservice fetch a set of Data from DB
My main intention is if I trigger the webservice ,it will fetch the Data from DB from the first time and then for the same request it will fetch from cache for a particular time ... In between if I trigger the service with different request it will again fetch data from DB for the first time for that request and then retrieve from the cache for the subsequent same request ..
It will hold the data in cache for a particular time ..
Now the issue is If I trigger the service .. it's always fetching the Data from DB and it's not holding any data in cache for the same request ..
Every time I hit the service it hits the Database directly and the data is not fetched from cache for the same request ..
Please help .. how to configure the cache with CXF in Mule

Break your service flow in two, using a VM endpoint and serializing both the request and response to string. This will make the event cacheable.
<flow name="ServiceFlow" doc:name="ServiceFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP" />
<object-to-string-transformer />
<ee:cache doc:name="Cache" cachingStrategy-ref="cachingStrategy">
<vm:outbound-endpoint path="cxf.service" exchange-pattern="request-response" />
<object-to-string-transformer />
</ee:cache>
</flow>
<flow name="CXFFlow" doc:name="CXFFlow">
<vm:inbound-endpoint path="cxf.service" exchange-pattern="request-response" />
<cxf:jaxws-service serviceClass="com.test.services.schema.maindata.v1.MainData" doc:name="SOAP"/>
<component class="com.test.services.schema.maindata.v1.Impl.MainDataImpl" doc:name="JavaMain_ServiceImpl"/>
</flow>

So, the final solution is as David suggested, by breaking the flow into two and also using <object-to-string-transformer /> for serializing both the request and response which is very important for a Cache to perform

Related

Unable to sign in to Tomcat Manager with correct username password and roles

I am trying to sign in to Tomcat manager and host-manager webapps which I have hosted on Amazon Web Service.
Even after entering the correct password in the popup, the pop up keeps showing and if I cancel it, then I am redirected to 401 error page
I have updated /etc/tomcat8/tomcat-users.xml correctly.
It stopped working after I added <Context path="" docBase="mywebapp" debug="0" privileged="true" /> inside server.xml
/etc/tomcat8/tomcat-users.xml
<role rolename="manager-gui"/>
<user username="supermanager" password="superpassword" roles="manager-gui" />
<role rolename="admin-gui"/>
<user username="superadmin" password="superpassword" roles="admin-gui"/>
</tomcat-users>
server.xml
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" proxyPort="80" protocol="HTTP/1.1"
connectionTimeout="20000"
URIEncoding="UTF-8"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="MYDOMAIN.COM">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="MYDOMAIN.COM" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context path="" docBase="mywebapp" debug="0" privileged="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
/etc/tomcat8/Catalina/localhost/manager.xml(host-manager.xml)
/etc/tomcat8/Catalina/MYDOMAIN.COM/manager.xml(host-manager.xml)
<Context path="/manager"
docBase="/usr/share/tomcat8-admin/manager"
antiResourceLocking="false" privileged="true" />
All I did was tried to login using Google Chrome instead of Firefox and VOILA!
It worked!!!

Replacing the deprecated https:outbound-endpoint with http:request in Mule

I was using the following configuration to hit a SOAP based service in mule 3.2, which works fine
<https:connector name="https" doc:name="HTTP\HTTPS"></https:connector>
<https:outbound-endpoint exchange-pattern="request-response" method="POST"
address="https://localhost:8080/CXF3Service/test" responseTimeout="15000" contentType="application/xml"
doc:name="HTTP Submit Request SOAP" connector-ref="https"> <message-properties-transformer
scope="outbound"> <add-message-property key="SOAPAction" value="https://myservice/myEndpoint"
/> </message-properties-transformer> </https:outbound-endpoint>
SOAP Binding in wsdl will look like,
<wsdl:operation name="sayHello">
<soap:operation soapAction="https://myservice/myEndpoint" style="document"/>
<wsdl:input name="sayHello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHelloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
On migrating to Mule 3.6, i replaced the code as follows. this was done to replace the deprecated https:outbound-endpoint with http:request
<http:request-config name="http" protocol="HTTPS"
host="localhost" port="8080"
doc:name="HTTP Request Configuration"/>
<http:request config-ref="http" path="CXF3Service/test" method="POST"
doc:name="HTTP" responseTimeout="15000" >
<http:request-builder>
<http:header headerName="SOAPAction" value="https://myservice/myEndpoint" ></http:header>
</http:request-builder>
<http:success-status-code-validator
values="0..599" />
</http:request>
But on hitting the service with new code, i am getting a SOAP Fault as response.
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Server did not recognize the value of HTTP Header SOAPAction: https://myservice/myEndpoint, "".</faultstring>
<detail/>
</soap:Fault>
</soap:Body>
</soap:Envelope>
What could be the possible reason for this?
FYI. I am using a cxf:proxy-client with payload as envelope, which remains unchanged for both.
<cxf:proxy-client payload="envelope" doc:name="Proxy client">
<cxf:inInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor">
<spring:property name="prettyLogging" value="true" />
</spring:bean>
</cxf:inInterceptors>
<cxf:outInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor">
<spring:property name="prettyLogging" value="true" />
</spring:bean>
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor">
<spring:property name="prettyLogging" value="true" />
</spring:bean>
</cxf:outFaultInterceptors>
</cxf:proxy-client>
Small tweak did the magic!!
I set the SOAPAction before the http:request instead of setting it inside.
<cxf:proxy-client payload="envelope" doc:name="Proxy client">
<cxf:inInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor">
<spring:property name="prettyLogging" value="true" />
</spring:bean>
</cxf:inInterceptors>
<cxf:outInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor">
<spring:property name="prettyLogging" value="true" />
</spring:bean>
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<spring:bean class="org.apache.cxf.interceptor.LoggingOutInterceptor">
<spring:property name="prettyLogging" value="true" />
</spring:bean>
</cxf:outFaultInterceptors>
</cxf:proxy-client>
<message-properties-transformer>
<add-message-property key="SOAPAction" value="https://myservice/myEndpoint"/>
</message-properties-transformer>
<http:request config-ref="http" path="CXF3Service/test" method="POST"
doc:name="HTTP" responseTimeout="15000" >
<http:success-status-code-validator
values="0..599" />
</http:request>

WCF ERROR- (413) Request Entity Too Large

I have 2 WCF service working together. One is Class Library and another one in webservice.
Its working fine until now. But if i try to send large amount of data it throw me 413 error...
An exception was thrown: The remote server returned an error: (413) Request Entity Too Large.
Below is web.config file-
For Class Library-
<add key="SMTP" value ="dummy"/>
<add key="BookingEmailFrom" value ="dummy"/>
<add key="BookingEmailToWBD" value ="dummy"/>
</appSettings>
<connectionStrings/>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
<!--
The <authentication> section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
<authentication mode="Windows"/>
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet
Information Services 7.0. It is not necessary for previous version of IIS.
-->
<system.serviceModel>
<services>
<service name="JSONWebService.Service1" behaviorConfiguration="JSONWebService.Service1Behavior">
<endpoint address="../Service1.svc" binding="webHttpBinding" contract="JSONWebService.IService1"
behaviorConfiguration="webBehaviour"/>
For web service client-
<?xml version="1.0"?>
<configuration>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\vx.x\Config
-->
<configSections>
</configSections>
<appSettings>
<add key="ConnectionString" value="Server=dummy;uid=sa;pwd=dummy;database=dummy"/>
---------------------- -->
section enables configuration
of the security authentication mode used by
ASP.NET to identify an incoming user.
-->
section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"/>
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="basic" binding="webHttpBinding" contract="JSONWebService.IService1"
behaviorConfiguration="webBehaviour"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior" >
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before
deployment -->
</bindings>
</system.serviceModel>
</configuration>
Any help would be really appreciated.
Thanks
You are encountering a WCF default limit on the message size. To raise the limit, use the maxReceivedMessageSize attribute in your web.config file (server side).
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding maxReceivedMessageSize="10000000">
</basicHttpBinding>
</bindings>
</system.serviceModel>
This is probably really late, but for anyone else that is also stuck.
The initial problem is solved by what BilalAlam described (increase the maxRecievedMessageSize) but your issue is the bindings need to be tied to the endpoint via the bindingConfiguration in the endpoint and the name in the binding.
Example
<bindings>
<webHttpBinding>
<binding maxReceivedMessageSize="2147483647" name="NAMETOTIEENDPOINT">
<readerQuotas maxStringContentLength="2000000"/>
</binding>
</webHttpBinding>
</bindings>
<services>
<service>
<endpoint address="basic" bindingConfiguration="NAMETOTIEENDPOINT" binding="webHttpBinding" contract="JSONWebService.IService1" />
</service>
</services>

Mule routing Web service using choice flow control

I'm trying to use choice flow control to route SOAP web service, it depends on payload to change to matching web-service. Here is my flow
<flow name="ProxyServiceFlow1" doc:name="ProxyServiceFlow1">
<http:inbound-endpoint exchange-pattern="request-response"
address="http://localhost:8081/hrManagerServiceProxy" doc:name="HTTP" />
<set-variable variableName="clientType"
value="#[message.inboundProperties['http.query.params']['clientType']]"
doc:name="Set clientType" />
<choice doc:name="Choice">
<when expression="#[clientType == 'unsecure']">
<cxf:proxy-service namespace="http://service.freetalk.viettel.com/"
service="RegisterServiceService" payload="body" wsdlLocation="unsecure.wsdl"
enableMuleSoapHeaders="false" doc:name="SOAP" />
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8081/HR/hrManagerService" doc:name="HTTP"/>
</when>
<otherwise>
<cxf:proxy-service namespace="http://service.freetalk.viettel.com/"
service="RegisterServiceService" payload="body" wsdlLocation="unsecure2.wsdl"
enableMuleSoapHeaders="false" doc:name="SOAP" />
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8081/HR/hrManagerService" doc:name="HTTP"/>
</otherwise>
</choice>
</flow>
It's just my thought, because I google many times but still get no result. Someone please give me some advises.
Its not the cxf:proxy-service that needs to be used along with the HTTP Outbound.
It should be cxf:proxy-client
Try using cxf:proxy-client with your http:outbound-endpoint.
<choice doc:name="Choice">
<when expression="#[clientType == 'unsecure']">
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8081/HR/hrManagerService" doc:name="HTTP">
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true">
</cxf:proxy-client>
</http:outbound-endpoint>
</when>
<otherwise>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8081/HR/hrManagerService" doc:name="HTTP">
<cxf:proxy-client payload="body" enableMuleSoapHeaders="true">
</cxf:proxy-client>
</http:outbound-endpoint>
</otherwise>
</choice>
Hope this helps.

Debugging Mule flows from FunctionalTestCase test

I'm new to Mule ESB and am trying to figure out how I can debug mule flows when running them from a FunctionalTestCase test class.
Using the visual debugger in Mule Studio works fine when running as a Mule Application, but not when running in a Junit test.
Is there any way to debug a flow that is run from a test? As an example, is there any way to step through TestFlow1 in a test method of a FunctionalTestCase if configured as below?
<flow name="TestFlow1" doc:name="TestFlow1">
<vm:inbound-endpoint exchange-pattern="one-way"
doc:name="VM" path="testIn" />
<choice doc:name="Choice">
<when expression="payload == 'Foo'">
<logger message="Got Foo!" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="testOut0" doc:name="VM"/>
</when>
<otherwise>
<logger message="Got [#payload]!" level="INFO" doc:name="Logger"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="testOut1" doc:name="VM"/>
</otherwise>
</choice>
</flow>
<flow name="TestFlow2" doc:name="TestFlow2">
<vm:inbound-endpoint exchange-pattern="one-way" path="testOut0" doc:name="VM"/>
<test:component />
</flow>
<flow name="TestFlow3" doc:name="TestFlow3">
<vm:inbound-endpoint exchange-pattern="one-way" path="testOut1" doc:name="VM"/>
<test:component />
</flow>
Unfortunately, this is a known issue.
Please upvote the issue and watch it.