500 Internal Server Error with passing wrong parameter in action of struts 2.0 - infinite

my working environment is below
jsp,struts 2.0,java
And my issue is that
when i fire below url in browser
(1) https://test123.local.com/test123/test.action?id=9
it works fine
but when i fire the same url with updatin 9 to 9'
(2) https://test123.local.com/test123/test.action?id=9'
give me the following exception in console
SEVERE: Servlet.service() for servlet default threw exception
Infinite recursion detected:
and as per checking in FF fireburg tool display me the 500 Internal Server Error.
and body have idea to prevent this type of error, I need to catch this error in exception and want to redirect the users to access restricted page.
Here i mentioned more detail which i had found from my side.
as per the shown in (2) given url
my struts-admin.xml entry as like below
<action name="test" method="test" class="com.os.Environment.TestAction">
<interceptor-ref name="customStack">
</interceptor-ref>
<result>/jsp/user/tested.jsp</result>
<result name="passed" type="redirect-action">passed?Id=${Id}</result>
</action>
<interceptor-stack name="customStack">
<interceptor-ref name="chainStack"/>
<interceptor-ref name="myCustomCheck"/>
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="exception">
<param name="logEnabled">true</param>
<param name="logLevel">ERROR</param>
</interceptor-ref>
</interceptor-stack>
hence first of my customStack interceptor called
below is my custom interceptor code
public class myCustomCheck extends AbstractInterceptor
{
private String invoke(ActionInvocation invocation) throws Exception
{
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
return invocation.invoke(); //this line throw the exception
}
public String intercept(ActionInvocation invocation) throws Exception
{
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
return invoke(invocation);
}
}
i had debugging the above code , and i had found that my interceptor will not call my "handled" name action and throws the exception as per given below:
Infinite recursion detected: [//test!test, //handled, //handled] - [unknown location]
at com.opensymphony.xwork2.ActionChainResult.execute(ActionChainResult.java:207)
at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:348)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:253)
let me know if you want to other information

Related

Keep part of URI encoded in camel route

I am new to camel, so this may be a simple problem to solve.
I have a spring-boot application with camel components which interacts with GitLab API.
My problem is that I need to keep the endpoint URIs in camel routes encoded, for example:
from("direct:start")
.setHeader("PRIVATE-TOKEN",constant("myToken"))
.to("https://gitlab.com/api/v4/projects/12345/repository/files/folder%2Ffile%2Eextension/raw?ref=master")
When the route starts, the message is sent to
"https://gitlab.com/api/v4/projects/12345/repository/files/folder/file.extension/raw?ref=master"
which returns 404, because the parameter file_path has to be encoded, as said in the GitLab doc (I've cheked with a GET from curl: with the first URI a json is returned, with the second 404).
I tried to pass the last part of the URI as HTTP_QUERY, but in this case there is the "?" between it and the URI and I get 404 again:
https://gitlab.com/api/v4/projects/12345/repository/files/?folder%2Ffile%2Eextension/raw?ref=master
I tried adding the URI with the headerHTTP_URI: this time the URI is reached correctly, but I get null body instead of the json answer.
Any idea to solve this issue?
I see that you already tried using HTTP_URI header. How did you set it? Try this:
from("direct:start")
.setHeader("PRIVATE-TOKEN", constant("myToken"))
.setHeader(Exchange.HTTP_URI, simple("https://gitlab.com/api/v4/projects/12345/repository/files/folder%2Ffile%2Eextension/raw?ref=master"))
.to("http:dummy");
This way you set the URI during the route execution, not in endpoint definition. According to docs:
Exchange.HTTP_URI: URI to call. Will override existing URI set directly on the endpoint. This URI is the URI of the HTTP server to call. Its not the same as the Camel endpoint URI, where you can configure endpoint options such as security etc. This header does not support that, its only the URI of the HTTP server.
Don't forget the dependency:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-http</artifactId>
</dependency>
The test:
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:start")
.setHeader("PRIVATE-TOKEN", constant("myToken"))
.setHeader(Exchange.HTTP_URI, simple("http://0.0.0.0:8080?param=folder%2Ffile%2Eextension/raw&ref=master"))
.to("http:dummy");
from("jetty:http://0.0.0.0:8080?matchOnUriPrefix=true")
.setBody(constant("{ key: value }"))
.setHeader(Exchange.CONTENT_TYPE, constant(MediaType.APPLICATION_JSON_VALUE))
.to("mock:result");
}
};
}
#Test
public void test() throws InterruptedException {
getMockEndpoint("mock:result").expectedHeaderReceived(Exchange.HTTP_QUERY, "param=folder%2Ffile%2Eextension/raw&ref=master");
final Exchange response = template.send("direct:start", new Processor() {
public void process(Exchange exchange) throws Exception {
// nothing
}
});
assertThat(response, notNullValue());
assertThat(response.getIn().getHeader(Exchange.HTTP_URI).toString(), containsString("folder%2Ffile%2"));
assertThat(response.getOut().getBody(String.class), containsString("{ key: value }"));
assertMockEndpointsSatisfied();
}
I tried adding the URI with the headerHTTP_URI: this time the URI is reached correctly, but I get null body instead of the json answer.
Keep in mind that the response should be stored at the OUT body:
Camel will store the HTTP response from the external server on the OUT body. All headers from the IN message will be copied to the OUT message, so headers are preserved during routing. Additionally Camel will add the HTTP response headers as well to the OUT message headers.

Apache Camel: Unable to get the Exception Body

Whenever there is normal flow in my Camel Routes I am able to get the body in the next component. But whenever there is an exception(Http 401 or 500) I am unable to get the exception body. I just get a java exception in my server logs.
I have also tried onException().. Using that the flow goes into it on error, but still I do not get the error response body that was sent by the web service(which I get when using POSTMAN directly), I only get the request in the body that I had sent to the web service.
Also adding the route:
from("direct:contractUpdateAds")
.to("log:inside_direct:contractUpdateAds_route_CompleteLog?level=INFO&showAll=true&multiline=true")
.streamCaching()
.setHeader(Exchange.HTTP_METHOD, constant("POST"))
.setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
.log("before calling ADS for ContractUpdate:\nBody:${body}")
.to("{{AdsContractUpdateEndpoint}}")
.log("after calling ADS for ContractUpdate:\nBody:${body}")
.convertBodyTo(String.class)
.end();
Option 1: handle failure status codes yourself
The throwExceptionOnFailure=false endpoint option (available at least for camel-http and camel-http4 endpoints) is probably what you want. With this option, camel-http will no longer consider an HTTP Status >= 300 as an error, and will let you decide what to do - including processing the response body however you see fit.
Something along those lines should work :
from("...")
.to("http://{{hostName}}?throwExceptionOnFailure=false")
.choice()
.when(header(Exchange.HTTP_RESPONSE_CODE).isLessThan(300))
// HTTP status < 300
.to("...")
.otherwise()
// HTTP status >= 300 : would throw an exception if we had "throwExceptionOnFailure=true"
.log("Error response: ${body}")
.to("...");
This is an interesting approach if you want to have special handling for certains status codes for example. Note that the logic can be reused in several routes by using direct endpoints, just like any other piece of Camel route logic.
Option 2 : Access the HttpOperationFailedException in the onException
If you want to keep the default error handling, but you want to access the response body in the exception handling code for some reason, you just need to access the responseBody property on the HttpOperationFailedException.
Here's an example:
onException(HttpOperationFailedException.class)
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
// e won't be null because we only catch HttpOperationFailedException;
// otherwise, we'd need to check for null.
final HttpOperationFailedException e =
exchange.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class);
// Do something with the responseBody
final String responseBody = e.getResponseBody();
}
});

Where do I put the Authentication Filter for Spring Boot 1.3.3

So I know what the problem is, I just don't know how to fix it.
Problem
I am using Spring Boot 1.3.3 and the CorsFilter is set like the following
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
private Environment env;
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://192.168.1.132:8100")
.allowedHeaders("Accept", "Content-Type","X-Auth-Token", "Origin", "Pragma","Cache-Control",
"If-Modified-Since","Authorization")
.exposedHeaders("X-Auth-Token")
.allowedMethods("PUT","POST","GET","OPTIONS")
.allowCredentials(true).maxAge(3600);
}
}
Secuity Config
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/save-user","/test","/error","/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
http.addFilterAfter(new CustomStatelessAuthenticationFilter(tokenAuthenticationService),
UsernamePasswordAuthenticationFilter.class);
...
}
The problem I am having is that I am using a Custom Token something like X-Auth-Token to validate the user. BUT CustomStatelessAuthenticationFilter is being called before the CorsRegistry. Before Chrome makes a call it does a OPTIONS call to make sure the application is legit. It won't allow me to pass the X-AUTH-TOKEN header without validating the call is legit. So it does not allow me to pass the X-AUTH-TOKEN until the server gets a response status OK From the server. Well since the CustomStatelessAuthenticationFilter gets call first, the X-AUTH-TOKEN returns as null. To fix this I had to do something like this...
CustomStatelessAuthenticationFilter
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
boolean debug = this.logger.isDebugEnabled();
if(debug) {
this.logger.debug("Custom.Custom Stateless Authentication");
}
if (request.getMethod().equals("OPTIONS")) {
response.addHeader("Access-Control-Allow-Origin", "http://192.168.1.132:8100");
response.addHeader("Access-Control-Allow-Headers", "X-Auth-Token");
response.addHeader("Access-Control-Expose-Headers", "X-Auth-Token");
response.setStatus(HttpServletResponse.SC_OK);
} else {
SecurityContextHolder.getContext().setAuthentication(
this.tokenAuthenticationService.getAuthentication((HttpServletRequest) request));
filterChain.doFilter(request, response);
}
}
In other words I have to return to the client that Status is OK manually before it will make the real request. It makes two request, one to make sure the OPTION call returns a OK (Pre Flight Request), then it makes another that actually makes the call with the X-Auth-Token in it. I don't want to do this because its completely ignoring my CorsMapping. I want it to check the CorsMapping First before continuing on. So where do I setup the authenitcation correctly so it already accepts the OPTIONS check first before actually authenticating.
I've also tried something like the following in my security config
http.addFilterAfter(new CustomStatelessAuthenticationFilter(tokenAuthenticationService),
CsrfFilter.class);
I advise a Upvote for this because I have not found a solid solution. So far the addCorsMappings has cause me more of a pain than the older solution of just adding a CorsFilter in older versions

RESTEasy - Stacktrace in logs when throwing WebApplicationException

I am using Resteasy 2.3.3, bundled with JBoss-AS-7.1.3. I'm trying to
throw a new WebAppliationException, and the output (to the client) seems
fine, but I'm left with an unwanted stack trace in my log. I have a few
other Exceptions mapped, and I was wondering if the mapping was somehow
causing an issue ­ trying to wrap this Exception.
Simple example:
public class SimpleService {
#GET
#Path("stuff")
public String getStuff(final #QueryParam("param1") String param1,
#QueryParam("param2") String param2) throws ActionException {
if (param1==null && param2==null) {
throw new WebApplicationException();
}
I get the following exception:
[WARN] org.jboss.resteasy.core.SynchronousDispatcher#error - failed to execute: javax.ws.rs.WebApplicationException
Any ideas what this error might mean? How I could get rid of the messages?
I stumbled across another class in the javadoc - NoLogWebApplicationException, and it says:
WebApplicationExceptions are logged by RESTEasy. Use this exception
when you don't want your exception logged
https://docs.jboss.org/resteasy/docs/2.3.3.Final/javadocs/org/jboss/resteasy/spi/NoLogWebApplicationException.html

CXF custom validation and FaultOutInterceptors for manage Errors

I have developed a web service using cxf. In case of an error due to a request that doesn't respect the xsd schema asociated I would custom the error sent to the client. For that:
1- I have added a specific EventHandlerValidator and a specific FaultOutInterceptor in web-services.xml
<jaxws:endpoint id="getNewCustomerOrderId" implementor="#getNewCustomerOrderIdWS" address="/GetNewCustomerOrderId">
<jaxws:properties>
<entry key="jaxb-validation-event-handler">
<ref bean="getNewCustomerOrderIdEventHandlerValidator"/>
</entry>
<entry key="schema-validation-enabled" value="IN"/>
<entry key="set-jaxb-validation-event-handler" value="true"/>
</jaxws:properties>
<jaxws:outFaultInterceptors>
<ref bean="getNewCustomerOrderIdCXFFaultOutInterceptor"/>
</jaxws:outFaultInterceptors>
</jaxws:endpoint>`enter code here
2 - I have implemented these classes:
In the handleValidator I just throw my own exception with a code and message
public class GetNewCustomerOrderIdEventHandlerValidator implements ValidationEventHandler {
#Override
public boolean handleEvent(ValidationEvent event) {
throw new MyException(MyExceptionCode.ERCC_GNCOI_100, event.getMessage());
}
}
FaultExceptionInterceptor runs for every exception thrown during webservice call. I only want to catch MyException with code ERCC_GNCOI_100 for customizing it, so:
public class GetNewCustomerOrderIdCXFFaultOutInterceptor extends AbstractSoapInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(CreateCustomerOrderCXFFaultOutInterceptor.class);
#Inject
private CreateCustomerOrderFaultExceptionService createCustomerOrderFaultExceptionService;
private static final JAXBContext jaxbContext;
static {
try {
jaxbContext = JAXBContext.newInstance(CreateCustomerOrderException.class);
} catch (JAXBException e) {
LOGGER.error(CormoranMarker.TECH, "Error during JAXBContext instantiation");
throw new RuntimeException(e);
}
}
public GetNewCustomerOrderIdCXFFaultOutInterceptor() {
super(Phase.MARSHAL);
}
#Override
public void handleMessage(SoapMessage message) throws Fault {
Fault exceptionFault = (Fault) message.getContent(Exception.class);
exceptionFault.setMessage("My custom message");
if (exceptionFault.getCause() instanceof MyException) {
MyException myException = (MyException) exceptionFault
.getCause();
if (myException.getCode().equals(myException.ERCC_GNCOI_100)) {// validation
// schema
// errors
Element elt = buildExceptionFaultDetail(cormoranFunctionalException);
exceptionFault.setDetail(elt);
}
}
}
private Element buildExceptionFaultDetail(CormoranFunctionalException cormoranFunctionalException) {
// Build custom response
}
}
However, in the interceptor I'm not able to catch my exception:
Fault exceptionFault = (Fault) message.getContent(Exception.class);
This line gets an unmarshalling exception:
Unmarshalling Error: cvc-complex-type.2.4.a: Invalid content was found starting with element 'customerOrderType1'. One of '{customerOrderID, version, customerOrderType, depositDate}' is expected.
In the logs I see that My exception has been thrown:
12:32:27.338 [qtp200426125-38] ERROR c.o.c.c.e.MyException - [] - MyException : Non-respect du schéma (XSD) du WebService exposé par Cormoran : cvc-complex-type.2.4.a: Invalid content was found starting with element 'customerOrderType1'. One of '{customerOrderID, version, customerOrderType, depositDate}' is expected.
Could you help me?
Thank you in advance!
Auri
There are two problems with the Interceptor as written.
First, you need to set the new content to the message after you make your changes. To do that, you can add the following to the handleMessage method after your code
message.setContent(Exception.class, exceptionFault);
Second, the phase you chose was too late to make changes to the Fault object. It looks like PRE_STREAM is the latest phase that allows the change. The CXF Interceptor documentation has the full list of phases.
You can modify the message as below.
Fault exceptionFault = (Fault) message..getExchange().getContent(Exception.class);

Resources