Request is blocked in end 2 end testing in a webflux application - spring-security

Another problem I encountered in end 2 end tests, setting invalid credentials will cause the sent request blocked till it is timeout.
Source codes: https://github.com/hantsy/spring-reactive-sample/blob/master/security-method/src/test/java/com/example/demo/IntegrationTests.java#L83-L94
#Test
public void savingPostsWhenInvalidCredentialsThenUnauthorized() throws Exception {
this.rest
.post()
.uri("/posts")
.attributes(invalidCredentials())
.body(BodyInserters.fromObject(Post.builder().title("title test").content("content test").build()))
.exchange()
.expectStatus().isUnauthorized()
.expectBody().isEmpty();
}
Another case is if the user does not has permission, also caused the request blocked.
#Test
public void deletingPostsWhenUserCredentialsThenForbidden_mutateWith() throws Exception {
this.rest
.mutate().filter(basicAuthentication("user", "password")).build()
.delete()
.uri("/posts/1")
.exchange()
.expectStatus().is4xxClientError()
.expectBody().isEmpty();
}
I am using Reactor Netty as runtime in this sample, the similar tests are passed in the ApplicationTests(used bindToApplicationContext in a mock environment), and failed in IntegrationTests(which used bindToServer in end 2 end testing).

Related

Twitter template fails during sending direct message, but get rate limit request works

Why direct message is not sent?
spring-social-twitter:1.1.2.RELEASE does not work with spring-web:5.0.6.RELEASE
Example of main class:
package com.test;
import org.springframework.social.twitter.api.ResourceFamily;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
public class Main {
public static void main(String[] args) {
final TwitterTemplate template = new TwitterTemplate("TEST", "TEST","TEST", "TEST");
template.userOperations().getRateLimitStatus(ResourceFamily.DIRECT_MESSAGES);
System.out.println("Successfuly obtained rate limits");
System.out.println("Sending DM");
template.directMessageOperations().sendDirectMessage("user_id", "text");
}
}
dependencies from gradle build file:
dependencies {
compile "org.springframework:spring-web:5.0.6.RELEASE"
compile "org.springframework.social:spring-social-twitter:1.1.2.RELEASE"
compile "com.fasterxml.jackson.core:jackson-databind:2.9.5"
}
Result of execution:
Successfuly obtained rate limits
Sending DM
Exception in thread "main" org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://api.twitter.com/1.1/direct_messages/new.json": cannot retry due to server authentication, in streaming mode; nested exception is java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:732)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:698)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:457)
at org.springframework.social.twitter.api.impl.DirectMessageTemplate.sendDirectMessage(DirectMessageTemplate.java:77)
at com.test.Main.main(Main.java:13)
Caused by: java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1692)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:347)
at org.springframework.http.client.SimpleClientHttpResponse.getRawStatusCode(SimpleClientHttpResponse.java:55)
at org.springframework.web.client.DefaultResponseErrorHandler.hasError(DefaultResponseErrorHandler.java:51)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:754)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:724)
... 4 more
You didn't provide a callback_url.
Go to your twitter app Settings page:
https://apps.twitter.com/
and fill in Callback Url input field. This will fix your I/O problem.

#Inject into Jax-rs resource: CWWAM0002E: An exception occurred while merging an annotation into deployment descriptor:

I am getting a weird exception when I deploy Rest sevice locally to my WAS 85 environment in eclipse:
CWWAM0002E: An exception occurred while merging an annotation into deployment descriptor: com.ibm.wsspi.amm.merge.MergeException: Unable to find EnterpriseBean for class WackyDoodleResource
com.ibm.wsspi.amm.merge.MergeException: Unable to find EnterpriseBean for class WackyDoodleResource
This is not my real code but here is how I set it up with names changed to protect the innocent:
#Path("/wacky-doodle-resource")
public class WackyDoodleResource{
#Context UriInfo uriInfo
#Context SecurityContext securityContext;
#Inject WackyDoodleEJB wackyDoodleEJB;
#POST
#Consumes(MediaType.APPLICATIONI_JSON)
#RolesAllowed("WACKYDOODLES")
#Produces(MediaType.APPLICATIONI_JSON)
public Response createWackyDoodle(WackyDoodleRequestRO requestRO{
String response = null;
response = wackyDoodleEJB.createWackyDoodle(requestRO)
}
return Response.ok(response)).build();
}
#Default
#Singleton
public class WackyDoodleEJB implements IWackyDoodleEJB{
public String createWackyDoodle(WackyDoodleRequestRO req){
System.out.println("Do Something Wacky!");
}
}
public interface IWackyDoodleEJB{
public String createWackyDoodle(WackyDoodleRequestRO request);
}
(Simple recreation of my more complex code for illustration purposes)
I see that exception when I deploy my ear to my local Websphere server. The application appears to start up and deploy just fine (if you don't pay attention to what you find in the logs). However, when I attempt to hit any of my http request #myResources, I get this oddly nondescript message
E com.ibm.ws.webcontainer.internal.WebContainer handleRequest SRVE0255E: A WebGroup/Virtual Host to handle / has not been defined.
I suspect it has something to do with my ear not publishing correctly (the exception in my question). I honestly do not know however. So, what could be happening here? This seems like it should be pretty boilertplate stuff?
The error suggests that I should Turn my regular resource pojo into an EJB? If I add, for example, the stateless #nnotation to my class, the above exception in the logs goes away, but I am still not able to hit my sevice resources. I get the same nondescript exception. I am at a loss and I have been looking at this for an hour. If you could point me in any direction I would appreciate it.

NPE ocurred when used `WebTestClient.mutateWith() ` in end to end tests

When I wrote some tests for webflux applications. And I tried to add credentials via mutateWith(mockUser().password("password")) in WebTestClient, but it caused NPE thrown.
I used bindToServer to connect test client to the running remote APIs, and tried to use mutateWith(mockUser().password("password")) add basic authentication to the request. It throws a NPE when the tests.
Updated Source codes: https://github.com/hantsy/spring-reactive-sample/blob/master/security-method/src/test/java/com/example/demo/IntegrationTests.java#L118-L127
After I explored the source codes of mockUser, it requires a MockServer environment to run the tests, but it was run as end 2 end in my sample.
Changed mutateWith(mockUser().password("password")) to .mutate().filter(basicAuthentication("user", "password")).build(), the NPE was disappeared.
Hope this helpful for you.
#Test
public void deletingPostsWhenUserCredentialsThenForbidden_mutateWith()
throws Exception {
this.rest
.mutate().filter(basicAuthentication("user", "password")).build()
.delete()
.uri("/posts/1")
.exchange()
.expectStatus().is4xxClientError()
.expectBody().isEmpty();
}
Updated Source codes: https://github.com/hantsy/spring-reactive-sample/blob/master/security-method/src/test/java/com/example/demo/IntegrationTests.java#L118-L127

Error in Zuul SendErrorFilter during forward

When my Zuul Filter is unable to route to a configured URL, the 'RibbonRoutingFilter' class throws a ZuulException saying "Forwarding error" and the control goes to the 'SendErrorFilter' class.
Now when the SendErrorFilter class tries to do a forward, another exception happens during this forward call.
dispatcher.forward(ctx.getRequest(), ctx.getResponse());
The exception happening during this forward call is
Caused by: java.lang.IllegalArgumentException: UT010023: Request org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter$Servlet30RequestWrapper#6dc974ea was not original or a wrapper
at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:103) ~[undertow-servlet-1.1.3.Final.jar:1.1.3.Final]
at org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter.run(SendErrorFilter.java:74) ~[spring-cloud-netflix-core-1.0.0.RELEASE.jar:1.0.0.RELEASE]
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112) ~[zuul-core-1.0.28.jar:na]
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:197) ~[zuul-core-1.0.28.jar:na]
Finally when the control comes to my custom ZuulErrorFilter , i do not get the original exception. Instead the exception object i get is the one that occurs during the forward.
Update:
I found that a errorPath property can be configured to point to a Error Handling Service. If it is not configured, Zuul by default looks for a service named /error and tries to dispatch to that service. Since we did not have any service for /error , the dispatcher.forward() was throwing error.
Question
How can we skip this fwd to an error handling service ? We have a ErrorFilter to log the error. We do not want to have a error handling service.
We had faced the same issue and there is a simple solution to fix the Undertow "eating" the original exception, following my blog post:
http://blog.jmnarloch.io/2015/09/16/spring-cloud-zuul-error-handling/
You need to set the flag allow-non-standard-wrappers to true. In Spring Boot this is doable through registering custom UndertowDeploymentInfoCustomizer. Example:
#Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
factory.addDeploymentInfoCustomizers(new UndertowDeploymentInfoCustomizer() {
#Override
public void customize(DeploymentInfo deploymentInfo) {
deploymentInfo.setAllowNonStandardWrappers(true);
}
});
return factory;
}
Now regarding the question, either way I would highly encourage you to implement your own ErrorController, because otherwise you may experience odd Spring Boot behaviour (in our setup - ralying on the default was always generating the Whitelabel error page with 200 HTTP status code - which never happens on Tomcat in contradiction) and in this way was not consumable by AJAX calls for instance.
Related Github issue: https://github.com/spring-cloud/spring-cloud-netflix/issues/524

Using application context in quartz job

I am trying to read message bundle in a job (Grails 2.0, Quartz-0.4.2):
class Job1Job {
def timeout = 5000l // execute job once in 5 seconds
def grailsApplication
def execute() {
def ctx = grailsApplication.mainContext
def bean = ctx.getBean('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')
println bean.message(code:'default.home.label')
}
}
And get error:
Error 2011-12-28 14:30:14,021 [quartzScheduler_Worker-5] ERROR listeners.ExceptionPrinterJobListener - Exception occured in job: GRAILS_JOBS.testappcontext.Job1Job
Message: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
The code works perfectly in controller and service. What I am doing wrong ?
I suspect this code run perfectly in grails 1.3.7
You're going the long way around - just use what the taglib uses, the messageSource bean:
class Job1Job {
long timeout = 5000 // execute job once in 5 seconds
def messageSource
void execute() {
println messageSource.getMessage('default.home.label', null, Locale.default)
}
}

Resources