Recession: Impact in Software as a Service(SaaS) 

Global uncertainties continue to dominate headlines. Inflation is expected to reach the highest levels of ~3.5% in the US and Europe by the end of 2023. To ease inflation, Central Banks need to dampen demand, by making it expensive (for financial institutions, businesses and households) to borrow by increasing Federal Reserve interest rates . We are expecting a federal rate hike of 4.75% – 5.0% by the end of 2023. These are all data showing we are heading toward recession. The US labor market was robust last quarter but this quarter it is not very promising. Everyday we are hearing layoff news from different sectors.

IMF inflation forecast

These inflation and layoff news are impacting our tech market. Many companies have a growth challenge: They expect to get as much as 50 percent of their revenue from new businesses and products by 2026 but are not on a path that will take them there. Current economic conditions are forcing high-growth yet unprofitable tech startups to tighten their financial belts.

There are few realities, software companies are facing for their growth.

US-based Venture capitalists backed software startups slowed down – VC are very clear of high valuation and demanding that companies spend less, improve profit margin and high output. Unicorn creation also slowed in 2022 Q4. This is one of the lowest quarterly count since the first quarter of 2020.

Depressed company valuations – Private company valuations are cooling down. Over the last 4 quarters, we have seen public valuations compressing.

 Software companies have three critical revenue streams.

  1. License / Subscription Revenue – When the customer pays for the right to own and use a copy of the software/hardware product or subscribe/access  software platform
  2. software or hardware product – Customer pays for ongoing support or premium support.
  3. Cloud based licensed software – Customer pays the software provider for specific deliverables such as software implementation or technical training.

In the current world all these 3 revenue streams are shrinking. Companies are using only essential services to run their business. This is directly impacting software revenue, which is leading these companies into low valuation.

Infrastructure Maintenance –  SaaS companies are providing the software as a service. This means the customer does not have to purchase hardware to run the software—that cost is transferred to the SaaS provider. This is implying continuous software running coast. This cost is not going anywhere.So due to inflation this SaaS running cost increases tremendously.

Mule 4: Consume a SOAP Webservice

The Web Service Consumer is an existing connector in Mule 4 that you can configure to point to a SOAP based web service. Webservice consumer call webservice hosted elsewhere as WSDL SOAP services and get response. This connector simplified process and encapsulated all the feature to consume SOAP based webservice. When no connector is available specific to any product (like Service-Now, Workday etc.), which is hosted as SOAP based webservice then this webservice consumer Connector enables any services to consume.

The main feature of this connector is

  • Consuming DOC Literal Web services.
  • SOAP multipart messages.
  • SOAP Headers.
  • DataSense support for SOAP Headers, SOAP Body, and Attachment.
  • Embedded DataWeave transformations inside the operation.
  • Support and Unified experience for SOAP with attachments and MTOM handling.
  • Custom HTTP configuration as transport (runtime and design time).
  • Web Service Security (WS Security) support.

Connector Configuration- In this section we define connector configuration to communicate with SOAP based webservice end point. By default, connector uses a simple non protected HTTP configuration to send all outgoing SOAP message.  In connector configuration you can select your SOAP version from drop down  and provide WSDL location. Connector extract and populates Service, Port and webservice endpoint address from WSDL file.

But if you are using secure endpoint address with HTTPS you need to configure custom Transportation Configuration for HTTPS.

These are the steps to enable your secure HTTPS endpoint.

  • Create jks file with keytool command
 keytool -keystore clientkeystore.jks -genkey -alias client 
  • Download certificate from WSDL HTTPS endpoint and add this certificate in your JKS file with below command
keytool -importcert -file certificate.cer -keystore clientkeystore.jks -alias "Alias"
  • Now configure TLS Context for Webservice consumer connector.
<tls:context name="TLS_Context" doc:name="TLS Context" doc:id="f634b824-2695-4d5f-8789-7a309b1511cb" >
           <tls:trust-store path="certificate/clientkeystore.jks" password="xxxxxx" type="jks" />
     </tls:context>
  • Now configure HTTP Request configuration for HTTPS endpoint.
<http:request-config name="HTTPS_Request_configuration" doc:name="HTTPS Request configuration" doc:id="02db1fd9-9f04-4eae-83cf-df43effd25d2">
           <http:request-connection protocol="HTTPS" host="service.vanrish.com" port="443" tlsContext="TLS_Context">
     	   </http:request-connection>
	</http:request-config>

  • If TLS and HTTPS configuration configured then you can select HTTP request configuration from Webservice consumer
<wsc:config name="BookService_Web_Service_Consumer_Config" doc:name="Book Web Service Consumer Config" doc:id="59fd0d73-f90d-4cf0-9855-c008307067a2" >
 <wsc:connection wsdlLocation="wsdl\bookservice.wsdl" service="BookService" port="BookServicePort" address="https://service.vanrish.com:443/service/BookService">
  <wsc:custom-transport-configuration >
    <wsc:http-transport-configuration requesterConfig="HTTPS_Request_configuration"/>
  </wsc:custom-transport-configuration>
 </wsc:connection>
</wsc:config>

Connector Parameter- If connector configuration is configured properly, your operation parameters are available from WSDL as drop down options.

In Message section there are three parameters available

  1. Body – The Body is main part of the SOAP message. The body element accepts embedded DataWeave scripts as values so that you can construct the XML request without having a side effect on the message or having to use multiple components to create the request.
  2. Headers – The headers element contains application-specific information (like authentication, payment, and so on) about the SOAP message . This elements accepts embedded DataWeave scripts as values.
  3. Attachment – The attachments element enables you to bind attachments to the SOAP message. This element also accepts embedded DataWeave scripts as values.

Since you configured custom HTTPS connector for your webservice consumer Connector you can configure Transport Configuration. In Transport header section you can select “Edit inline” and add all your header parameters in line

<wsc:consume doc:name="Consume" doc:id="ca5a1247-7cf6-4c7f-a442-b6fd037c13c9" config-ref="BookService_Web_Service_Consumer_Config" operation="AddBook">
       <wsc:transport-headers >
          <wsc:transport-header key="SOAPAction" value="AddBook" />
          <wsc:transport-header key="Content-Type" value="text/xml; charset=UTF-8" />
          <wsc:transport-header key="Authorization" value="${book.authorization}" />
       </wsc:transport-headers>
 </wsc:consume>

Here is webservice consumer flow diagram

Code for this flow

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
	xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:tls="http://www.mulesoft.org/schema/mule/tls"
	xmlns:wsc="http://www.mulesoft.org/schema/mule/wsc"
	xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/wsc http://www.mulesoft.org/schema/mule/wsc/current/mule-wsc.xsd
http://www.mulesoft.org/schema/mule/tls http://www.mulesoft.org/schema/mule/tls/current/mule-tls.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
	
	<wsc:config name="BookService_Web_Service_Consumer_Config" doc:name="Book Web Service Consumer Config" doc:id="59fd0d73-f90d-4cf0-9855-c008307067a2" >
            <wsc:connection wsdlLocation="wsdl\bookservice.wsdl" service="BookService" port="BookServicePort" address="https://service.vanrish.com:443/service/BookService">
	            <wsc:custom-transport-configuration >
					<wsc:http-transport-configuration requesterConfig="HTTPS_Request_configuration" />
				</wsc:custom-transport-configuration>
            </wsc:connection>
     </wsc:config>

	<tls:context name="TLS_Context" doc:name="TLS Context" doc:id="f634b824-2695-4d5f-8789-7a309b1511cb" >
           <tls:trust-store path="certificate/clientkeystore.jks" password="changeit" type="jks" />
     </tls:context>

    <http:request-config name="HTTPS_Request_configuration" doc:name="HTTPS Request configuration" doc:id="02db1fd9-9f04-4eae-83cf-df43effd25d2">
           <http:request-connection protocol="HTTPS" host="service.vanrish.com" port="443" tlsContext="TLS_Context">
     	   </http:request-connection>
	</http:request-config>

	<sub-flow name="addbook-ServiceSub_Flow" doc:id="511f0969-0b7d-4b7e-a113-60ef03e97648" >
             <logger level="INFO" doc:name="Logger" doc:id="e6bd0106-e512-4fdd-97cf-1dbd77e1e0e7" message="Entering into AddBook flow"/>
                             <ee:transform doc:name="Transform Message" doc:id="06cc17de-86a9-4c53-a2f4-167d9561bed9" >
                                           <ee:message >
                                                          <ee:set-payload ><![CDATA[%dw 2.0
 output application/xml skipNullOn="everywhere"
 ns n0  https://www.service.vanrish.com/BookService/
  ---
   n0#AddBook:
         {
                 n0#Book : {
                 	ID: payload.id,
                 	Title : payload.title,
                 	Author : payload.author
                 }
         }]]></ee:set-payload>
                                           </ee:message>
                             </ee:transform>
                             <logger level="INFO" doc:name="Logger" doc:id="ce84f628-7b38-4d2d-b5e3-9fdded2c9289" message="soap request --> #[payload]"/>
                             
<wsc:consume doc:name="Consume" doc:id="ca5a1247-7cf6-4c7f-a442-b6fd037c13c9" config-ref="BookService_Web_Service_Consumer_Config" operation="AddBook">
                                           <wsc:transport-headers >
                                                          <wsc:transport-header key="SOAPAction" value="AddBook" />
                                                          <wsc:transport-header key="Content-Type" value="text/xml; charset=UTF-8" />
                                                          <wsc:transport-header key="Authorization" value="${book.authorization}" />
                                           </wsc:transport-headers>
                             </wsc:consume>
                             <logger level="INFO" doc:name="Logger" doc:id="680d69e0-2b01-480c-afe7-660ca22b2f9f" message="AddBook Output-->#[payload]"/>
                             <ee:transform doc:name="Transform Message" doc:id="72d26561-107a-4c6e-a7d4-85bd18e0d316" >
                                           <ee:message >
                                                          <ee:set-payload ><![CDATA[%dw 2.0
ns ns0 https://www.service.vanrish.com/BookService/
 

output application/json skipNullOn="everywhere"
---
payload.body.ns0#AddBookResponse]]></ee:set-payload>
                                           </ee:message>
                             </ee:transform>
                             <logger level="INFO" doc:name="Logger" doc:id="ea517185-efa4-4bf2-a03f-e8bd4d308e80" message="Output AddBook --> #[payload]"/>
              </sub-flow>
</mule>

Mule 4: APIKit for SOAP Webservice

Mule 4 introduced APIKit for soap webservice. It is very similar to APIKit for Rest. In SOAP APIKit, it accepts WSDL file instead of RAML file. APIKit for SOAP generates work flow from remote WSDL file or downloaded WSDL file in your system.

To create SOAP APIKit project, First create Mulesoft project with these steps in Anypoint studio.

Under File Menu -> select New -> Mule Project

Mule 4 Project Settings

In above pic WSDL file gets selected from local folder to create Mule Project.

Once you click finish, it generates default APIKit flow based on WSDL file.

In this Mulesoft SOAP APIKit example project, application is consuming SOAP webservice and exposing WSDL and enabling SOAP webservice.

Mule 4 API Kit for Soap Router

In SOAP Router APIKit, APIKit SOAP Configuration is defined WSDL location, Services and Port from WSDL file.

API Kit SOAP configuration

In above configuration, “soapkit-config” SOAP Router look up for requested method. Based on requested method it reroutes request from api-main flow to method flow. In this example, requested method is “ExecuteTransaction” from existing wsdl, so method flow name is

<flow name=“ExecuteTransaction:\soapkit-config”>  

In this example we are consuming same WSDL but end point is different.

To call same WSDL we have to format our request based on WSDL file. In dataweave, create request based on WSDL and sending request through HTTP connector.

Here is dataweave transformation to generate request for existing WSDL file

%dw 2.0
output application/xml
ns soap http://schemas.xmlsoap.org/soap/envelope/
ns xsi http://www.w3.org/2001/XMLSchema-instance
ns ns0 http://localhost/Intellect/ExternalWebService
ns xsd http://www.w3.org/2001/XMLSchema
ns ns1 xsd:string
---
 
{
  	soap#Envelope @('xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'): {
  	 	
  	soap#Body: {
     	ExecuteTransaction @('xmlns': 'http://localhost/Intellect/ExternalWebService'): {
     	  Request @(xsi#'type': 'xsd:string'): payload.soap#Body.ns0#ExecuteTransaction.Request 
     	 
     	  }
     	
    	}
    	
  	}
}

Here is main flow

Main flow for API SOAP Kit

Here is full code

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:apikit-soap="http://www.mulesoft.org/schema/mule/apikit-soap"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:wsc="http://www.mulesoft.org/schema/mule/wsc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core
http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http
http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/apikit-soap
http://www.mulesoft.org/schema/mule/apikit-soap/current/mule-apikit-soap.xsd
http://www.mulesoft.org/schema/mule/wsc
http://www.mulesoft.org/schema/mule/wsc/current/mule-wsc.xsd
http://www.mulesoft.org/schema/mule/ee/core
http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd"
> <http:listener-config basePath="/fda" name="api-httpListenerConfig"> <http:listener-connection host="0.0.0.0" port="8081"/> </http:listener-config> <apikit-soap:config httpStatusVarName="httpStatus" name="soapkit-config" port="ISTCS2SubmitOrderSoap" service="ISTCS2SubmitOrder" wsdlLocation="ISTCOrder.wsdl"/> <wsc:config doc:id="b2979182-c4e9-489b-9420-b9320cfe9311" doc:name="Web Service Consumer Config" name="Web_Service_Consumer_Config"> <wsc:connection address="https://enterprisetest.vanrish.com/pub/xchange/request/atlas" port="ISTCS2SubmitOrderSoap" service="ISTCS2SubmitOrder" wsdlLocation="api/ISTCOrder.wsdl"/> </wsc:config> <http:request-config doc:id="408de2f8-c21a-42af-bfe7-2d7e25d153b0" doc:name="HTTP Request configuration" name="HTTP_Request_configuration"> <http:request-connection host="enterprisetest.fadv.com" port="443" protocol="HTTPS"/> </http:request-config> <flow name="api-main"> <http:listener config-ref="api-httpListenerConfig" path="/ISTCS2SubmitOrder/ISTCS2SubmitOrderSoap"> <http:response statusCode="#[attributes.protocolHeaders.httpStatus default 200]"/> <http:error-response statusCode="#[attributes.protocolHeaders.httpStatus default 500]"> <http:body><![CDATA[#[payload]]]></http:body> </http:error-response> </http:listener> <apikit-soap:router config-ref="soapkit-config"> <apikit-soap:attributes><![CDATA[#[%dw 2.0 output application/java --- { headers: attributes.headers, method: attributes.method, queryString: attributes.queryString }]]]></apikit-soap:attributes> </apikit-soap:router> </flow> <flow name="ExecuteTransaction:\soapkit-config"> <logger doc:id="62a3748e-b81c-4a95-9af0-99c5a282b237" doc:name="Logger" level="INFO" message="Entering into flow"/> <ee:transform doc:id="c130d7ff-bd70-4af0-b7d4-9a6caa0d771f"> <ee:message> <ee:set-payload><![CDATA[%dw 2.0 output application/xml ns soap http://schemas.xmlsoap.org/soap/envelope/ ns xsi http://www.w3.org/2001/XMLSchema-instance ns ns0 http://localhost/Intellect/ExternalWebService ns xsd http://www.w3.org/2001/XMLSchema ns ns1 xsd:string --- { soap#Envelope @('xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance'): { soap#Body: { ExecuteTransaction @('xmlns': 'http://localhost/Intellect/ExternalWebService'): { Request @(xsi#'type': 'xsd:string'): payload.soap#Body.ns0#ExecuteTransaction.Request } } } } ]]></ee:set-payload> </ee:message> </ee:transform> <http:request config-ref="HTTP_Request_configuration" doc:id="6d7001f3-b90a-4ed8-96d2-d577329d21d5" doc:name="Request" method="POST" path="/pub/xchange/request/atlas"/> <logger doc:id="a05e704f-e539-48f3-9556-fe66641e3f64" doc:name="Logger" level="INFO" message="#[payload]"/> </flow> </mule>