Camel route with intermediate processing - post

I need to write a Camel route that would send a file to a web service. Before sending the file to the endpoint, I have to query a database for some information and send the file to the endpoint along with additional information. I would also have to move the file to another directory after the entire route has completed. I was able to create the individual parts of the route independently. I wanted to know how I could do this in a single route.

It's your design decision how to do that.
You can have your individual parts as sub-routes (that is my preferable way).
It makes route more functional structured and at least more readable.
Then you can pass your message(file) to them one after another or in parallel by using multicast component.
in XML DSL it will look like:
<route id="main-route">
<from uri="..." />
<!-- DB processing -->
<to uri="direct:db-route-endpoint"/>
<multicast parallelProcessing="false">
<!-- No parallel processing: file will be stored after Web Service call completed
or for parallel parallelProcessing="true" -->"
<to uri="...web service endpoint... "/>
<to uri="direct:store-file-endpoint"/>
</multicast>
</route>
<route id="db-route">
<from uri="direct:db-route-endpoint" />
... DB processing ...
</route>
<route id="store-file-route">
<from uri="direct:store-file-endpoint" />
... save file to another directory ...
</route>

Related

Extended Schedule Task in Sitecore not working

I have created an extended scheduled task with some parameters and has also added Schedule "20160201T235900|20190201T235900|127|00:10:00" to run every 10 minutes.
Frequncy in web.config is also set to 5 minutes. 00:05:00
But It is not at all executing somehow. Can anyone help me out with some possible reasons for this.
Extended Schedule
|||||Task Info
This Extended Schedule template ships with Active Commerce, and is helpful for specifying parameters that are commonly needed when executing Active Commerce tasks, including a site/shop context, database context, and other parameters.
Out of the box however, the Sitecore DatabaseAgent will not execute schedules for items which don't explicitly use Sitecore's Schedule template (even if the template inherits from it, as Extended Schedule does).
To work around this, Active Commerce ships with its own extended DatabaseAgent. You can enable it by enabling the xActiveCommerce.Scheduling.config.example config patch that ships with Active Commerce. In case this example config is missing, I've included its contents below.
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<scheduling>
<agent type="Sitecore.Tasks.DatabaseAgent">
<patch:delete />
</agent>
<agent type="Sitecore.Tasks.DatabaseAgent">
<patch:delete />
</agent>
<agent type="ActiveCommerce.Tasks.DatabaseAgent" method="Run" interval="00:10:00" instance="master">
<param desc="database">master</param>
<param desc="schedule root">/sitecore/system/tasks/schedules</param>
<LogActivity>true</LogActivity>
</agent>
<agent type="ActiveCommerce.Tasks.DatabaseAgent" method="Run" interval="00:10:00" instance="core">
<param desc="database">core</param>
<param desc="schedule root">/sitecore/system/tasks/schedules</param>
<LogActivity>true</LogActivity>
</agent>
</scheduling>
</sitecore>
</configuration>
Are you using InitializeSpeedBooster.config? then you have to delete the following lines:
<processor type="Sitecore.Pipelines.Loader.InitializeScheduler, Sitecore.Kernel">
<patch:delete />
</processor>

How to get only value part of linked list values from mule DB connector

I have the below flow which returns a list of values from DB with in mule.
I want to be able to get only the value part of the result from DB instead of a full linked list in the format of "column=value". I want to use the value part as part of a URL in the next http block. Please see my flow below. Any feedback will be helpful please.
<http:request-config name="HTTP_Request_Configuration" protocol="HTTPS" host="jsonplaceholder.typicode.com/#[flowVars.custID]" port="443" doc:name="HTTP Request Configuration"/>
<http:listener-config name="HTTP_Listener_Configuration1" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="dbcconnectorFlow">
<http:listener config-ref="HTTP_Listener_Configuration2" path="/lockStatus" allowedMethods="PUT" doc:name="HTTP"/>
<db:select config-ref="Oracle_Configuration" doc:name="Database">
<db:dynamic-query><![CDATA[select CUST_NO FROM CUSTOMERS WHERE LOCKED='N']]></db:dynamic-query>
</db:select>
<logger message="#[message.payload]"" level="INFO" doc:name="Logger"/>
<set-variable variableName="custID" value="#[message.payload[0]]" doc:name="Variable"/>
<http:request config-ref="HTTP_Request_Configuration" path="/" method="PUT" doc:name="HTTP"/>
</flow>
Ekow
One way to get only the value part of the result from DB is to put a transform message (Dataweave) component after the DB component and configure it as shown in this example:
<flow name="myprojectFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<db:select config-ref="MySQL_Configuration" doc:name="Database">
<db:parameterized-query><![CDATA[select CompanyName from Customers limit 10]]></db:parameterized-query>
</db:select>
<response>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
payload.CompanyName[1]]]></dw:set-payload>
</dw:transform-message>
</response>
</flow>
The output is the first company name string in the array. The column name is not included.
Found a way around this. I had to convert the db results which was an object into xml using the object to xml transformer. Then use the splitter to split the results since I was expecting multiple output as below
[xpath3('//root/data/"xml_tag_of_required_data"', payload, 'NODESET')]. I then set the output as a variable and referenced the variable in the http endpoint URL.

How can I effectively prevent bot requests or at least prevent them from clogging my logs?

I assume the errors I'm getting are caused by bots that have:
indexed my previous website under the same domain; and
are probing for vulnerabilities of some kind.
Here are some of the errors:
Code: 404; Type: Http; Error: A public action method 'IPC$' was not found on controller ...
Code: 0; Type: InvalidOperation; Error: The requested resource can only be accessed via SSL.
There are other errors for specific URLs that used to exist, but have since been removed.
Is there a way to prevent bots from hitting these links or is it something I'll have to deal with by filtering out specific requests in ELMAH?
Unfortunately, due to the amount of bots out there and the variety of ways that they are coded to attack or scrape your website, you will not be able to prevent all of these errors. However, you can easily choose to ignore specific types of errors in Elmah. Here is a sample of a filter in the <elmah> section of a web.config file:
<errorFilter>
<test>
<or>
<and>
<!-- filter all errors out that fall in the range 400-499 -->
<greater binding="HttpStatusCode" value="399" type="Int32" />
<lesser binding="HttpStatusCode" value="500" type="Int32" />
</and>
<regex binding="BaseException.Message" pattern="A potentially dangerous \b.+?\b value was detected from the client" caseSensitive="false" />
<regex binding="BaseException.Message" pattern="he provided anti-forgery token was meant for user" caseSensitive="false" />
</or>
</test>
</errorFilter>
That will filter out all the 404s etc. by only including errors less than 400 or greater than 499, and excludes a couple of specific .NET exceptions that are commonly triggered by malicious bots. From there, you can tweak to suit...

Is it possible to rewrite url using ColdFusion?

I have got a requirement for generating user friendly urls.I am on IIS.
My dynamic URLs looks like,
www.testsite.com/blog/article.cfm?articleid=4432
Client wants the urls should look like
www.testsite.com/blog/article_title
I know this can be easily done using IIS URL rewiter 2.0.
But the Client wants to do it using ColdFusion only. Basic idea he given like,
User will hit the url www.testsite.com/blog/article_title
I need to fetch the article id using the article_title in the url.
Using the ID to call the article.cfm page and load the output into cfsavecontent and then deliver that output to the browser.
But I do not think its possible at application server level. How IIS will understand our user friendly urls . OR am I missing something important? Is it possible to do it using ColdFusion at application server level?
First, I hate to recommend reinventing the wheel. Webservers do this and do this well.
Cold Fusion can do something like this with #cgi.path_info#. You can jump through some hoops as Adam Tuttle explains here: Can I have 'friendly' url's without a URL rewriter in IIS?.
Option #2: My Favorite: OnMissingTemplate..
Only available to users of Application.cfc (I'm pretty sure .cfm has no counterpart to onMissingTemplate).
You can use this function within application.cfc and all affected pages will throw any "missing" urls at this event. You can then place
<cffunction name="onMissingTemplate">
<cfargument name="targetPage" type="string" required=true/>
<!--- Use a try block to catch errors. --->
<cftry>
<cfset local.pagename = listlast(cgi.script_name,"/")>
<cfswitch expression="#listfirst(cgi.script_name,"/")#">
<cfcase value="blog">
<cfinclude template="mt_blog.cfm">
<cfreturn true />
</cfcase>
</cfswitch>
<cfreturn false />
<!--- If no match, return false to pass back to default handler. --->
<cfcatch>
<!--- Do some error logging here --->
<cfreturn false />
</cfcatch>
</cftry>
</cffunction>
mt_blog.cfm can have contents like, if your url is say just like /blog/How-to-train-your-flea-circus.cfm
<!--- get everything after the slash and before the dot --->
<cfset pagename = listfirst(listlast(cgi.script_name,"/"),".")>
<!--- you may probably cache queries blog posts --->
<cfquery name="getblogpost">
select bBody,bTitle,bID
from Blog
where urlname = <cfqueryparam cfsqltype="cf_sql_varchar" value="#pagename#">
</cfquery>
<!--- This assumes you will have a field, ex: urlname, that has a url-friendly format to match
to. The trouble is that titles are generically, in most blogs, changing every special char
to - or _, so it's difficult to change them back for this sort of comparison, so an add'l
db field is probably best. It also makes it a little easier to make sure no two blogs have
identical (after url-safe-conversion) titles. --->
...
Or if you use a url like /blog/173_How-to-train-your-flea-circus.cfm (where 173 is a post ID)
<!--- get everything after the slash and before the dot --->
<cfset pageID = listfirst(listlast(cgi.script_name,"/"),"_")>
<!--- you may probably cache queries blog posts --->
<cfquery name="getblogpost">
select bBody,bTitle,bID
from Blog
where bID = <cfqueryparam cfsqltype="cf_sql_integer" value="#pageID#">
</cfquery.
...
I don't recommend using a missing file handler (or CF's onMissingTemplate). Otherwise IIS will return a 404 status code and your page will not be indexed by search engines.
What you need to do is identify a unique prefix pattern you want to use and create a web.config rewrite rule. Example: I sometimes use "/detail_"+id for product detail pages.
You don't need to retain a physical "/blog" sub-directory if you don't want to. Add the following rewrite rule to the web.config file in the web root to accept anything after /blog/ in the URL and interpret it as /?blogtitle=[everythingAfterBlog]. (I've added an additional clause in case you want to continue to support /blog/article.cfm links.)
<rules>
<rule name="Blog" patternSyntax="ECMAScript" stopProcessing="true">
<match url="blog/(.*)$" ignoreCase="true" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{SCRIPT_FILENAME}" matchType="IsFile" negate="true" />
<add input="{PATH_INFO}" pattern="^.*(blog/article.cfm).*$" negate="true" />
</conditions>
<action type="Rewrite" url="/?blogtitle={R:1}" appendQueryString="true" />
</rule>
</rules>
I recommend using a "301 Redirect" to the new SEO-friendly URL. I also advise using dashes (-) between word fragments and ensure that the character case is consistent (ie, lowercase) or you could get penalized for "duplicate content".
To add to what cfqueryparam suggested, this post on Using ColdFusion to Handle 404 errors shows how to replace the web server's 404 handler with a CFM script - giving you full rewrite capabilities. It is for an older version of IIS, but you should be able to find the proper settings in the IIS version you are using.
As Adam and other's have said (and the same point is made in the post) this is not something you should do if you can avoid it. Web servers working at the HTTP level are much better equipped to do this efficiently. When you rely on CF to do it you are intentionally catching errors that are thrown in order to get the behavior you want. That's expensive and unnecessary. Typically the issue with most clients or stakeholders is a simple lack of understanding or familiarity with technology like url rewriting. See if you can bend them a little. Good luck! :)

Removing all namespaces in the xml and valid per wsdl

Again I am back with a question related to the same wsdl, this time wanted to remove all namespaces in the request, and conforming to the wsdl.
The same wsdl tripservice wsdl from the link ,simply replace the "from" element with the below.
<xs:element minOccurs="0" name="from" nillable="true">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="12"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
Using soapui we know that the below request xml conforms to wsdl.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:trip="http://trip.price.service" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header/>
<soapenv:Body>
<trip:getTripPrice>
<trip>
<adults>9</adults>
<duration>9</duration>
<from xsi:nil="true" />
<rooms>3</rooms>
</trip>
</trip:getTripPrice>
</soapenv:Body>
</soapenv:Envelope>
I removed almost all namespaces from the request, however not able to remove xsi namespace from the request, so as to conform to wsdl
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header/>
<Body>
<getTripPrice xmlns="http://trip.price.service">
<trip xmlns="">
<adults>9</adults>
<duration>9</duration>
<from xsi:nil="true" />
<rooms>3</rooms>
</trip>
</getTripPrice>
</Body>
</Envelope>
How to remove xsi namespace as well, still valid as per the wsdl?
This is a generic XML processing question, "How do you control the use and production of namespace prefixes in XML producer 'x'"? In your case, according to the comments, 'xml producer X is xslt.' It will then depend on what implementation of XSLT you are using and whether it has any options to control this particular behavior.
In general, xslt takes the usual attitude that namespace prefixes are just syntactic sugar, and does not offer convenient mechanisms for controlling their use. You may be able to encourage it make more use of prefixes by declaring them at the top of your XSLT definition.
I recommend compression as the real solution to reducing bandwidth usage.

Resources