Is this possible to somehow run Citrus simulator scenario from within Citrus testcase?
I have an end-to-end test scenario. I send a message to the input endpoint and receive it from the very last endpoint:
<parallel>
<sequential>
<receive endpoint="...">
<message>
<resource file="..."/>
</message>
<header>
...
</header>
</receive>
</sequential>
<sequential>
<sleep seconds="10"/>
<send endpoint="...">
<message>
<resource file="..."/>
</message>
<header>
...
</header>
</send>
</sequential>
</parallel>
In the meantime my application performs some additional readings. I need to simulate replies for these readings and it would be great if I am able to include replies for these reading in this testcase or start a particular Simulator scenario together with running this testcase (no need to start additional external Java Simulator application before testing). Is this possible?
Best Regards
Let me see if I understood your scenario correctly:
Send the initial message.
Simulate replies for those "additional readings".
Receive a response to the initial message.
You can achieve this with the <parallel> & <sequential> tags:
<parallel>
<sequential>
<!-- send initial request -->
<send ...>
<!-- receive response to the initial request -->
<receive ...>
</sequential>
<sequential>
<!-- simulate readings -->
</sequential>
</parallel>
You have two threads. In the first <sequential> you send the initiating request (1) AND wait for a response (3).
In the second <sequential> you simulate replies for your readings (2).
Both threads will run in parallel. Citrus will send the request, after which it will wait for a response with the <receive> action. That response will only come after you finish simulating your readings (on the parallel thread) and your app will be capable of sending the correct response (I presume). This means that you either need to put a sleep between the <send> and <receive> inside your first <sequential> OR configure a high enough timeout for the <receive> action.
I have also answered an older question of yours related to Citrus and topics, and I presume, that is why you have two <sequential> running in parallel with the <receive> in the first one. If your app sends a response only after the readings are beings simulated, the setup that I have posted above should work, since the speed of the response should not be an issue. If speed is still an issue, something like this should work:
<parallel>
<sequential>
<!-- receive response to the initial request -->
<receive ...>
</sequential>
<sequential>
<!-- send initial request -->
<send ...>
</sequential>
<sequential>
<!-- simulate readings -->
</sequential>
</parallel>
Again, don't forget the timeout on the <receive> action.
In case you need something like reusable test scenarios, maybe templates can help you.
Related
I'm creating a Spring Integration prototype using Spring Boot.
I have a 'hub' that accepts console input and sends that to an separate socket/tcp application.
The tcp application echos what it was sent in its reply to the hub.
The hub then takes the tcp response & sends it to a separate restful/http application.
The http application echos what is was sent back to the hub.
I'm stuck on the hub's int-http:outbound-gateway which send a request to http. When i omit the 'reply-channel', i can enter more than one bit of text and send to the tcp application. That reply is forwarded to the http application & printed in the console.
However, when i include a reply-channel, i can send one message to the tcp application (the http app receives it) and then the hub application 'stalls'; i type messages in console, hit 'enter' but nothing happens.
Here's my config:
<!-- TO tcp application/server -->
<int:channel id="input" />
<int:gateway id="simple.gateway"
service-interface="com.foo.SimpleGateway"
default-request-channel="input"/>
<int-ip:tcp-connection-factory id="client"
type="client"
host="localhost"
port="4444"
single-use="true"
so-timeout="10000"/>
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="input"
reply-channel="clientBytes2StringChannel"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000"/>
<int:object-to-string-transformer id="clientBytes2String"
input-channel="clientBytes2StringChannel"
output-channel="broadcast.channel" />
<int:channel id="broadcast.channel" />
<int:recipient-list-router id="tcp.broadcast.list"
input-channel="broadcast.channel">
<int:recipient channel="to.http" />
<!-- other channels to broadcast to -->
</int:recipient-list-router>
<!-- TO HTTP restful endpoint -->
<!-- this sends the requests -->
<int:channel id="to.http" />
<!-- <int-http:outbound-gateway id="http-outbound-gateway" -->
<!-- request-channel="to.http" -->
<!-- url="http://localhost:8080/howdy?message={msg}" -->
<!-- http-method="GET" -->
<!-- expected-response-type="java.lang.String" -->
<!-- charset="UTF-8"> -->
<!-- <int-http:uri-variable name="msg" expression="payload"/> -->
<!-- </int-http:outbound-gateway> -->
<int-http:outbound-gateway id="http-outbound-gateway"
request-channel="to.http"
url="http://localhost:8080/howdy?message={msg}"
http-method="GET"
expected-response-type="java.lang.String"
charset="UTF-8"
reply-channel="from.http.pubsub.channel">
<int-http:uri-variable name="msg" expression="payload"/>
</int-http:outbound-gateway>
<!-- http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html -->
<int:publish-subscribe-channel id="from.http.pubsub.channel" />
<bean id="inboundHTTPPrinterService"
class="com.foo.service.InboundHTTPPrinterService"/>
<int:service-activator id="inboutdHttpPrintServiceActivator"
ref="inboundHTTPPrinterService"
input-channel="from.http.pubsub.channel"
method="printFromHttp"/>
</beans>
In its final form, i want the HTTP response to be printed somewhere AND forwarded to a separate AMQP application.
Your description isn't clear, however, I guess, you mean some issue in here:
<int:service-activator id="inboutdHttpPrintServiceActivator"
ref="inboundHTTPPrinterService"
input-channel="from.http.pubsub.channel"
method="printFromHttp"/>
It would be great to see the printFromHttp() source code, but according your fears it seems for that the method is void.
To send message back to the replyChannel in the headers you should return something from your service method. Looks like in your case it is just enough the same payload or message if that.
Greeting everyone, I try to configure simple authorization code flow via Spring Security OAuth.
I tested my authorisation and resource server configuration via following approaches:
Create a web application as client and use its page to fire http post call to /oauth/authorize.
After getting code, I use the same page to
fire another http post with code and get token.
At the end, I use
curl -H to place token inside header and get response from protected
resource.
But when I try to use rest template. It throw error message 401 Unauthorised error.
Server side - security configure:
<http auto-config="true" pattern="/protected/**"
authentication-manager-ref="authenticationManager">
<custom-filter ref="resourceFilter" before="PRE_AUTH_FILTER" />
<csrf disabled="true" />
</http>
<http auto-config="true">
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
<form-login default-target-url="/admin.html" />
<logout logout-success-url="/welcome.html" logout-url="/logout"/>
<csrf disabled="true" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="admin" password="123456" authorities="ROLE_USER,ROLE_ADMIN" />
</user-service>
</authentication-provider>
</authentication-manager>
Server side - authorisation and resource configure:
<oauth:authorization-server
client-details-service-ref="clientDetails" error-page="error">
<oauth:authorization-code />
</oauth:authorization-server>
<oauth:client-details-service id="clientDetails">
<oauth:client client-id="admin" secret="fooSecret" />
</oauth:client-details-service>
<oauth:resource-server id="resourceFilter" />
Client Side:
<oauth:client id="oauth2ClientContextFilter" />
<oauth:resource id="sso" client-id="admin"
access-token-uri="http://localhost:8080/tough/oauth/token"
user-authorization-uri="http://localhost:8080/tough/oauth/authorize"
use-current-uri="true" client-secret="secret"
client-authentication-scheme="header" type="authorization_code"
scope="trust" />
<oauth:rest-template id="template" resource="sso"/>
If anyone knows where goes wrong, please do let me know.
There were two issues with my configuration above.
I noticed my client used wrong secret to communicate with authorization server.
Token endpoint at authorization server use authentication manager which
serve user authentication. It result
client are rejected all times until I create new security realm for
token endpoint and configure it to use a authentication manger designed for
client.
Note client is different from user. Client is third party want to access resource belong to your user (also called resource owner).
I had the same problem. It helped to add a
org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService
to spring securities authentication-manager, glueing the clientDetailsService to the authentication manager. So
<authentication-manager alias="authenticationManager">
...
<authentication-provider user-service-ref="clientDetailsUserDetailsService"/>
...
</authentication-manager>
nearly solved the problem for me. I had one more Issue: Since ClientDetailsUserDetailsService has no default constructor, spring threw Exceptions of the form
org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class
[class org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService]:
Common causes of this problem include using a final class or a non-visible class;
nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
Which I could not solve without using a copy of that class receiving the clientDetailsService as property instead of a constructor arg.
Lets start with a little background information. I am running a very simple ASP.net MVC Azure cloud service (a web role, Windows Server 2012 R2 with IIS 8.5). This service receives statistics from a flash client, which posts data roughly every 10 seconds (for potentially very large number of clients) and JavaScript. All the service contains is a single controller with two simple actions with a bunch of parameters (representing the individual statistics which are send in various combinations). All the service does is set the CORS and cookie responses (the clients/JavaScript can be embedded on random domains), verify the integrity of the received data and then store it into an Azure table storage account.
In order to ensure our service operates optimally we use New Relic to track service performance, and in order to ensure that our data is accurate (i.e. we successfully record all received messages) we implemented a custom error handling solution so we can fix any problems/bugs that might arise.
We have load tested our service using jmeter and encountered no problems, but now that we have deployed to a live environment and our service is being used we are starting to encounter occasional 500 internal server errors (approx 5% of requests). The big problem being that our own error handling code is not detecting these errors, however New Relic does report certain requests generating a 500 internal server error (with no further information like a stack trace, sometimes with, sometimes without reported parameters).
Our custom error handling consists of an HTTP module which registers to both the AppDomain.CurrentDomain.UnhandledException and the context.Error events. In theory this should be catching (and then logging) any exceptions which are not already being caught (and logged) inside our own code. Relevant web.config sections are configured in the following manner:
<customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/500.aspx">
<error statusCode="404" redirect="~/404.aspx" />
<error statusCode="500" redirect="~/500.aspx" />
</customErrors>
and
<httpErrors existingResponse="Replace">
<clear />
<error statusCode="404" path="404.html" responseMode="File" />
<error statusCode="500" path="500.html" responseMode="File" />
</httpErrors>
<modules>
<add type="namespace.UnhandledExceptionModule" name="UnhandledExceptionModule" preCondition="managedHandler" />
</modules>
However, this is not the case. I have tried turning on all kinds of logging but the IIS logs are useless (they only show that a 500 response was returned, but no other useful information). The only useful information I have been able to gather is from the failed request traces, but I have not been able to determine what the actual problem is from that information (googling the error code or exception leads to nothing concrete). A screenshot of the relevant section of a failed trace can be found here:
http://i57.tinypic.com/20acrip.jpg
I also uploaded the complete trace here:
http://pastebin.com/fDt3thvr
Each failed request generates exactly the same log, so the errors we are seeing are consistently being caused by the same problem. However, I am not able to determine what this problem is, let alone find a way of fixing it. Even though I have an error code and message, googling them only returns very old topics on issues that have been fixed 6 years ago.
It is pretty important for our business that these messages can be recorded with a high degree of accuracy, but as it stands now I have no further ideas on how to gain better information on what is happening on these servers. We are also not able to replicate this behavior in a controlled environment.
Also, our error logging itself does work properly. 'Normal' errors are logged as expected and we have also verified the HTTP module actually works.
Edit:
The controller pseudo code is as follows:
[HttpPost]
public ActionResult Method(...)
{
// Set cookie and CORS reponse, check for early out.
if(earlyOut)
return 404;
// Store received values.
azuretable.ExecuteAsync(TableOperation.InsertOrMerge(...));
return 200;
}
Edit2:
I have spend some time analyzing failed request traces and they mostly seem to be generated by users with IE9. I actually managed to reproduce the error 2 times by quickly leaving the page while it is loading, as the problem seems to be caused by aborted Ajax calls (which we make the most of during page load). Why would an aborted call cause a 500 error though instead of being handled neatly?
Do the cookies exceed 4k ? The same thing happened to us on IIS, and the requests sometimes ended up with 500 Internal Server error. The errors were virtually untraceable.
I reproduced the issue by simply inflating a cookie over the 4093 bytes limit.
I think that it is because you are not awaiting your async method call, or your are not returning an awaitable response. I had exactly this issue when I forgot to do that.
await azuretable.ExecuteAsync(TableOperation.InsertOrMerge(...))
Then you should be good. I think you'll find that the async call is finishing after your call has completed back to the caller.
I am using Spring Security 3.2.3 in my Spring MVC application and getting some unexpected behavior.
According to the documentation here, it should be possible to use ${_csrf.token} in the meta tags of my html:
<meta name="_csrf" content="${_csrf.token}" />
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}" />
From where I extract the value of "content" using JQuery and place it into the Request Header using AJAX.
For some reason though, Spring Security doesn't "convert" this into an actual token, it just gets sent into the header as a literal string "${_csrf.token}".
Trying the alternate route of using ${_csrf.token} in a hidden input according to the documentation, I then tried to check what the token evaluates to by checking the input's value, but it's still just plain text "${_csrf.token}".
Since it seems that Spring Security isn't in effect, am I missing some kind of configuration? I am currently using a barebones Spring Security Java configuration (as opposed to xml) as shown here:
import org.springframework.context.annotation.*;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.*;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf();
}
}
I know configure is getting called since I put a debug statement in it, so I assume that CSRF protection is indeed enabled since it should be by default.
I realize that the syntax "${}" is JSP Expression Language, and I am currently successfully using it to evaluate the context into an object with Thymeleaf, for example:
th:object="${context}"
So I tried adding "th:" in front of the meta tag's "content" like so:
<meta name="_csrf" th:content="${_csrf.token}"/>
But it results in an exception that this cannot be evaluated:
Exception evaluating SpringEL expression: "_csrf.token"
I think the key here may be figuring out how to get the expression to evaluate properly in my view.
I finally solved this problem, but it basically required rewriting Spring Security. Here it is in all its glory.
First, I followed the suggestions in Eyal Lupu's great blog post here, but I had to tweak it to my situation because of my AJAX requirement.
As for the Thymeleaf situation, the key tidbit is hidden away in the archives of the Thymeleaf forums - Infamous Issue 7.
https://github.com/thymeleaf/thymeleaf-spring/issues/7#issuecomment-27643488
The last comment by the creator of Thymeleaf himself says that:
th:action ... detects when this attribute is being applied on a
tag --which should be the only place, anyway--, and in such case
calls RequestDataValueProcessor.getExtraHiddenFields(... ) and adds the
returned hidden fields just before the closing tag.
That was the key phrase I needed to get the token to work. Unfortunately it's completely not obvious why th:action would also kick off getExtraHiddenFields, but at any rate it does, and that's what matters.
So for anyone struggling with Thymeleaf + Spring Security CSRF + AJAX POST, here are my steps (this is paring it down quite a bit but these are the high-level concepts to solve it):
Implement the Spring interface RequestDataValueProcessor and register it in Spring Security's XML config so you can override the method getExtraHiddenFields, which allows you to insert a hidden input field into the HTML (with the token of course). The token itself is generated with a Java.Util UUID.
With JQuery, read the value from that hidden field and set the Request Header's "X-CSRF-Token" attribute so that it gets sent over HTTP. It's not possible to simply leave the token in the hidden input field because we are not doing a form Submit, instead we use AJAX POST to call methods on the server side.
Extend Spring's HandlerInterceptorAdapter and register it as an interceptor so that every time a POST method is done, the "preHandle" method on the server side is called so it can compare the request token (extracted from the HTTP header in the previous step) to the session's token (should be the same!). After it does this check, it can either allow the request to go through or return an error.
I started with the same source article as you, I think, and the same "you should be able to" add answers as you did. I fought it a different way. I made Thymeleaf give me the answer I wanted.
<meta name="_csrf" th:content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
Thymeleaf put the attribute "content" with the requested Spring EL contents. I then used the provided JavaScript/JQuery to extract the info from the meta tags straight into the CSRF header.
Before adding the thymeleaf-extras-springsecurity namespace and its dependency into my project, I had similar problems. I never did get the meta tags to work, even with thymeleaf-extras-springsecurity. But I did successfully retrieve Spring Security's csrf token using the hidden input. I have instructions below that work for me:
In the html tag, add:
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
In your pom.xml (if you're using Maven) you'll need to add the dependency: thymeleaf-extras-springsecurity4.
Then add the hidden input inside your page's body to retrieve the csrf token.
<input type="hidden" id= "csrf-token" th:name="${_csrf.parameterName}" th:content="${_csrf.token}" />
and then use that within your javascript/jquery as follows:
function f1() {
var token1 = $('input#csrf-token').attr("content");
...
$.ajax({
...
type: "POST",
beforeSend: function (request)
{
request.setRequestHeader("X-CSRF-TOKEN", token1);
},
...
This all assumes that you have spring security enabled, and that you have NOT turned off csrf protection.
You have incorrect configuration for springSecurityFilterChain in your web.xml. Correct definition is:
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
Spring Security uses set of servlet filters to provide the functionality it is offering (including CSRF protection). These filters are defined as Spring beans (i.e. they are instantiated and managed by Spring application context). DelegatingFilterProxy is a special type of servlet filter, which finds root application context on the registered servlet context and delegates every call to the same named bean.
Your issue is a different one, just stumbled across this one as well and it took me several hours to figure out the cause. The cause for the issue described by you is that you did not enable csrf support within your spring-security.xml
This little snippet needs to go into your security-config.xml:
<!-- Static resources such as CSS and JS files are ignored by Spring Security -->
<security:http pattern="/static/**" security="none" />
<security:http use-expressions="true">
<!-- Enables Spring Security CSRF protection -->
<security:csrf/>
<!-- Configures the form login -->
<security:form-login
login-page="/login"
login-processing-url="/login/authenticate"
authentication-failure-url="/login?error=bad_credentials"
username-parameter="username"
password-parameter="password"/>
<!-- Configures the logout function -->
<security:logout
logout-url="/logout"
logout-success-url="/login"
delete-cookies="JESSIONID"/>
<!-- Anyone can access these urls -->
<security:intercept-url pattern="/auth/**" access="permitAll"/>
<security:intercept-url pattern="/login" access="permitAll"/>
<security:intercept-url pattern="/signin/**" access="permitAll"/>
<security:intercept-url pattern="/signup/**" access="permitAll"/>
<security:intercept-url pattern="/user/register/**" access="permitAll"/>
<!-- The rest of our application is protected. -->
<security:intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<!-- Adds social authentication filter to the Spring Security filter chain. -->
<security:custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" />
</security:http>
....
...
..
.
Save time by configuring this correctly...
Cheerio,
Flo!
In case you don't need to use Thymeleaf, I'd suggest the following:
Add this to the top of your page:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
Add this to your login form:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
Add these dependencies to your pom.xml:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
After struggling a lot, that worked for me.
I am trying to poll an RSS feed using Mule Studio but have been unsuccessful polling the information using the http outbound-endpoint in the Mule application. I have previously encountered the same issue using the http inbound-endpoint with the same site but was able to resolve the issue by assigning the User-Agent to MuleESB by setting the address to be
http://www.theaggie.org/feed/?User-Agent=MuleESB
However, now with the http outbound-endpoint, I am unable to poll the feed and get a 403 Forbidden error. My XML for the flow is
<flow name="aggregatorFlow1" doc:name="aggregatorFlow1">
<poll>
<processor-chain>
<set-variable variableName="httpMessages" value="#[[]]" />
<http:outbound-endpoint exchange-pattern="one-way" address="http://www.theaggie.org/feed/?User-Agent=MuleESB" method="GET" />
<expression-component>httpMessages.add(message.payloadAs(java.lang.String))</expression-component>
</processor-chain>
</poll>
<logger level="INFO" message="#[httpMessages]" />
</flow>
If I change the exchange-pattern to request-response, the logger would just output [ ]. I do not have issues with other sites using the same xml code.
Clearly the exchange-pattern should be request-response, as you seem to care about the payload of the response.
Try adding the following before the http:outbound-endpoint:
<set-property propertyName="User-Agent" value="MuleESB" />