Iterating an array using Mule's foreach scope - foreach

I would like to iterate through an array and use the value taken from the array to put it within an http inbound endpoint. How would I be able to iterate through this array and take the value from the array to place it as a variable within the http inbound endpoint?
The code that I used to try was:
<flow name="foreachFlow1" doc:name="foreachFlow1">
<poll frequency="2000">
<foreach collection="#[groovy:['localhost:8082', 'localhost:8083']]"
doc:name="For Each">
<http:outbound-endpoint exchange-pattern="request-response"
address="http://#[payload]" method="GET" doc:name="HTTP" />
</foreach>
</poll>
</flow>
and I get the error
Invalid content was found starting with element 'poll'

Inbound endpoints are message sources and can not be parametrized the way you're describing.
To achieve your goal, trying a <poll> message source to wrap a foreach that uses http:outbound-endpoint to perform GET (#method) request-response (#exchange-apttern) interactions.
The trick is to bring the results for the HTTP calls back through the foreach, which by default do not do it. The following illustrate a potential approach:
<flow name="foreachFlow1">
<poll frequency="2000">
<processor-chain>
<set-variable variableName="httpResponses" value="#[[]]" />
<foreach collection="#[groovy:['localhost:8082', 'localhost:8083']]">
<http:outbound-endpoint
exchange-pattern="request-response" address="http://#[payload]"
method="GET" />
<expression-component>httpResponses.add(message.payloadAs(java.lang.String))
</expression-component>
</foreach>
</processor-chain>
</poll>
<logger level="INFO" message="#[httpResponses]" />
</flow>
<!-- Test server stubs -->
<flow name="server8082">
<http:inbound-endpoint exchange-pattern="request-response"
address="http://localhost:8082" />
<set-payload value="This is 8082" />
</flow>
<flow name="server8083">
<http:inbound-endpoint exchange-pattern="request-response"
address="http://localhost:8083" />
<set-payload value="This is 8083" />
</flow>

Related

Posting Multiple Images to Twitter with Coldfusion using MonkehTweet

I am using MonkehTweet Coldfusion wrapper for Twitter Authentication. I have everything up working, but i cannot get my head around posting multiple images using the PostUpdateWithMedia function. I am relatively new to coldfusion, and learning it along the way. A simple call to PostUpdateWithMedia(status="", media="") would post to Twitter with an image, but how can i use this to post multiple images. The PostUpdateWithMedia function from MonkehTweet is,
<cffunction name="postUpdateWithMedia" access="public" output="false" hint="Updates the authenticating user's status. Request must be a POST. A status update with text identical to the authenticating user's current status will be ignored to prevent duplicates.">
<cfargument name="status" required="true" type="String" hint="The text of your status update. URL encode as necessary. Statuses over 140 characters will be forceably truncated." />
<cfargument name="media" required="true" type="string" hint="Up to max_media_per_upload files may be specified in the request, each named media[]. Supported image formats are PNG, JPG and GIF. Animated GIFs are not supported." />
<cfargument name="possibly_sensitive" required="false" type="boolean" default="false" hint="Set to true for content which may not be suitable for every audience." />
<cfargument name="in_reply_to_status_id" required="false" type="String" hint="The ID of an existing status that the update is in reply to." />
<cfargument name="lat" required="false" type="String" hint="The location's latitude that this tweet refers to." />
<cfargument name="long" required="false" type="String" hint="The location's longitude that this tweet refers to." />
<cfargument name="place_id" required="false" type="String" hint="A place in the world. These IDs can be retrieved from geo/reverse_geocode." />
<cfargument name="display_coordinates" required="false" type="String" hint="Whether or not to put a pin on the exact coordinates a tweet has been sent from." />
<cfargument name="checkHeader" required="false" type="boolean" default="false" hint="If set to true, I will abort the request and return the response headers for debugging." />
<cfargument name="timeout" required="false" type="string" default="#variables.instance.timeout#" hint="An optional timeout value, in seconds, that is the maximum time the cfhttp requests can take. If the time-out passes without a response, ColdFusion considers the request to have failed." />
<cfset var strTwitterMethod = '' />
<cfset arguments["media[]"] = arguments.media />
<cfset structDelete(arguments,'media') />
<cfset strTwitterMethod = getCorrectEndpoint('api') & 'statuses/update_with_media.json' />
<cfreturn genericAuthenticationMethod(timeout=getTimeout(), httpURL=strTwitterMethod,httpMethod='POST', parameters=arguments, checkHeader=arguments.checkHeader) />
</cffunction>
I have tried passing in multiple files as,
PostUpdateWithMedia(status="", media="", media=""); but it didnot work. But, I am passing in the multiple media arguments wrong. Can someone help me with how to pass in multiple media arguments.
Unfortunately, MonkehTweet does not include support for the Twitter API media/upload endpoint, which is required for multi-image Tweets - it only supports the deprecated statuses/update_with_media, which still works, but only supports a single image. I also noticed that the code still refers to 140 character Tweets, so it probably has not been updated for some time. I'm not aware of an alternative ColdFusion wrapper for the API, either, so this is something you would need to build for yourself.

log4j2 appender talking to sql server database

This URL
https://logging.apache.org/log4j/log4j-2.0/manual/appenders.html
has this example:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error">
<Appenders>
<JDBC name="databaseAppender" tableName="dbo.application_log">
<DataSource jndiName="java:/comp/env/jdbc/LoggingDataSource" />
<Column name="eventDate" isEventTimestamp="true" />
<Column name="level" pattern="%level" />
<Column name="logger" pattern="%logger" />
<Column name="message" pattern="%message" />
<Column name="exception" pattern="%ex{full}" />
</JDBC>
</Appenders>
<Loggers>
<Root level="warn">
<AppenderRef ref="databaseAppender"/>
</Root>
</Loggers>
</Configuration>
When I try to wire up to a sqlserver database......
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<JDBC name="SQLServerAppender" tableName="dbo.LogEntry">
<DataSource jndiName="jdbc:sqlserver://MyMachine\\MyInstance:1433;databaseName=LoggingDB;applicationName=myappname;integratedSecurity=true;" />
<Column name="EntryDateUtc" isEventTimestamp="true" />
<Column name="LOGGER" pattern="%C" />
<Column name="Level" pattern="%level" />
<Column name="Message" pattern="%m" />
<Column name="UserName" pattern="%x" />
<Column name="Priority" pattern="%p" />
<Column name="ElapsedMilliseconds" pattern="%r" />
<Column name="ThreadName" pattern="%t" />
<Column name="ThrowableMessage" pattern="%throwable " />
</JDBC>
I get errors like:
ERROR No ConnectionSource provided: connectionSource
ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender for element JDBC org.apache.logging.log4j.core.config.ConfigurationException: Arguments given for element JDBC are invalid: field 'connectionSource' has invalid value 'null'
How do I set up a connection string in the xml-configuration to talk to sqlserver?
Even though it doesn't match the documentation, I tried this:
<Appenders>
<JDBC name="SQLServerAppender" tableName="dbo.LogEntry">
<ConnectionSource jndiName="jdbc:sqlserver
It didn't work of course.
What is the magic syntax sugar?? #help
Thanks.
The value of DataSource jndiName is not a SQL Server connection string. If you want to use a SQL Server connection string then put in Log4J configuration put something like:
<appender name="SQLServer" class="org.apache.log4j.jdbc.JDBCAppender">
<param name="url" value="jdbc:sqlserver://MyMachine\\MyInstance:1433;databaseName=LoggingDB;applicationName=myappname;"/>
<param name="driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<param name="user" value="user_id"/>
<param name="password" value="password"/>
<param name="sql" value="INSERT INTO LOG4J_TABLE VALUES('%x','%d','%C','%p','%m')"/>
<layout class="org.apache.log4j.PatternLayout"></layout>
</appender>
<logger name="log4j.rootLogger" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="SQLServer"/>
</logger>
Which will write to a table that you must have created previously like:
CREATE TABLE LOG4J_TABLE (
User_Id VARCHAR(20) NOT NULL,
Date_Stamp DATETIME NOT NULL,
Logger VARCHAR(100) NOT NULL,
Level VARCHAR(10) NOT NULL,
Message VARCHAR(8000) NOT NULL
)
Note that you canĀ“t use integratedSecurity=true straightforward from Java but must specify the user + password.
I think the problem is that JNDI is not enabled.
This is my configuration log4j2.xml:
<bean id="dataSourceProxy" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="dataSource"/>
</bean>
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSourceProxy"/>
</bean>
<bean id="jdbcTemplate" class="xx.com.xxxxx.framework.database.xxxxxJDBCTemplate">
<constructor-arg ref="dataSourceProxy"/>
</bean>
<bean id="DBSession" class="xx.com.xxxxx.framework.database.DBConnectionManager" lazy-init="true">
<constructor-arg type="java.lang.String" value="DBSession"/>
<constructor-arg ref="dataSourceProxy"/>
<constructor-arg ref="transactionManager"/>
<property name="template" ref="jdbcTemplate"/>
</bean>
It worked normally before we had upgraded log4j to log4j2. After upgrading, there was an error output from my weblogic console:
ERROR Could not create plugin of type class org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender for element JDBC org.apache.logging.log4j.core.config.ConfigurationException: Arguments given for element JDBC are invalid: field 'connectionSource' has invalid value 'null'
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.injectFields(PluginBuilder.java:210)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:121)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1120)
....
According to Apache documentation ,
a Log4j JDBC Appender configured with a DataSource is disabled by default. You may try to add java option -Dlog4j2.enableJndiJdbc=true to use JNDI's java protocol.
When we added set JAVA_OPTIONS=-Dlog4j2.enableJndiJdbc=true into our weblogic, the error was gone.
I hope it is helpful for you.

Mule flowvars getting affected which preserves payload when the payload is changed

I am storing the output from DB in a flowvar #[flowvars.test] after which I am iterating the payload to remove few key, value pair. when the payload is modified inside the for loop the value which is stored in flowvars also getting modified.I am using mule 3.9 runtime.
<db:parameterized-query><![CDATA[select MachineName,TransactionId,SourceAPIName,Source,Target,ErrorCode,Severity,MailContent,ExceptionType,ExceptionMessage from Notification
where Notify='Y' and IsNotify='N']]>
</db:select>
</poll>
<expression-filter expression="#[payload.size()>0]" doc:name="Stop If No Records"/>
<set-variable variableName="test" value="#[message.payload]" doc:name="Variable"/>
<set-variable variableName="validatedEntries" value="#[[]]"
doc:name="ValidatedEntries" />
<logger level="INFO" doc:name="Logger"/>
<foreach collection="#[flowVars.test]" doc:name="For Each">
<logger level="INFO" doc:name="Logger"/>
<set-variable variableName="tempNotificationTable" value="#[payload.remove('TransactionID')]" doc:name="Temp NotificationTable"/>
<expression-component doc:name="Expression"><![CDATA[#[flowVars.validatedEntries.add(payload)]]]></expression-component>
</foreach>
For-Each will not create a deep copy of the object. Because of this, your original payload is getting changed.

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.

Exclude IP adress from spring security cas filter

I have a site that uses CAS as a SSO solution and require all that access the site to be authenticated. To fulfill the regulations that our company has we need to create fully rendered snapshot copies of the site. I was thinking of using something like Httrack to accomplish this, but I need to get around the login. My plan was to exclude the IP address of the server running httrack, but I cannot seem to figure out how to configure this.
<sec:http name="contentSecurityFilterChain" use-expressions="true" access-decision-manager-ref="contentAccessDecisionManager" entry-point-ref="casAuthenticationEntryPoint">
<sec:custom-filter position="CAS_FILTER" ref="casAuthenticationFilter" />
<sec:logout logout-success-url="/logout.jsp" logout-url="/j_security_logout" invalidate-session="true" delete-cookies="sessionKey,userId,lastClient" />
<sec:access-denied-handler ref="accessDeniedHandler" />
<sec:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER" />
<sec:custom-filter ref="singleLogoutFilter" before="CAS_FILTER" />
<sec:csrf disabled="true" />
<sec:headers>
<!-- Enable hsts if possible. See http://tools.ietf.org/html/rfc6797 -->
<sec:hsts disabled="true" />
<sec:cache-control disabled="true" />
<sec:frame-options disabled="true" />
</sec:headers>
<sec:intercept-url pattern="/monitoring/**" access="hasRole('ROLE_MONITORING')" requires-channel="${security.channel.dispatcher}" />
channel="${security.channel.dispatcher}" />
<sec:intercept-url pattern="/api/login" access="hasRole('ROLE_AUTHENTICATED')" />
<sec:intercept-url pattern="/**" access="hasRole('ROLE_AUTHENTICATED') or hasIpAddress('192.168.123.123')" requires-channel="${security.channel.dispatcher}" />
</sec:http>
I tried the above as a first attempt (where 192.168.123.123 represents my excluded server), but the request still gets redirected to the SSO site before returning to the filter chain.
The closest I got in my various naive fiddlings was by adding a filter to the entry point that did not trigger the commence method; While it did not redirect the request, it only returned an empty page. I assume that is because by not calling the commence method the request was seen as not matching the filter group.
Is there a way to exclude an IP address from the security filters OR is there a better way of doing this?
Suggestions most welcomed!

Resources