Spring MVC returns 404 in production for some requests but works fine in all other envs - spring-mvc

We have the following combination in our application.
Spring mvc + tiles as view resolver + controller mapping (Request mapping)
Docker to run our application
Splunk to check the logs (developers dont have access to login to the server and check the logs)
We are trying to hit the following URL in Production which gives 404 in the network tab but it works fine in all other envs (there was one request which was successful in production using the same URL). All other URLs are working fine in production.
https://host:port/context_name/assignUpdate.do
Here is the code for the same.
web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
dispatcher-servlet.xml
<mvc:default-servlet-handler />
<context:annotation-config />
<aop:aspectj-autoproxy />
<context:component-scan base-package="we have correct package mentioned here" />
SomeController.java
#Controller
public class SomeController {
#RequestMapping(value = "assignUpdate", method = RequestMethod.POST)
public ModelAndView assignCampaignUpdate(formparam form, HttpSession session){
method body
}
}
Points to be considered
How about adding #ModelAttribute before formparam (not sure that will make any difference)
formparam has a member var which is a List of some other class which has all primitives (the volume of some other class goes huge around 1.2K in production whereas in the other envs it will be around 50) - also tried this one by bringing down the search to one item in UI and sent the request. din work
Any help here
Request Headers
Accept: /
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 993
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Only log which i could get
[logtype=access] x_client_ip="ip" date="[09/Aug/2018:07:27:09 -0400]" http_status="404" content_length=0 referer="https://localhost:port/context_name/mainpage.do" user_agent="Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" method=POST uri="/context_name/assignUpdate.do" query="" protocol=HTTP/1.1 durationms=55 fsreqid=- srcip=10.42.247.20

After spinning my head for long time, i finally got the solution for the above problem.
The exception was IndexoutofBounds. In the request body, we are passing object with index more than 256. Since spring framework supports collection limit of 0 - 255 as index in the request body object, dispatcher servlet throws indexoutofbounds exception and returns 404 as status code for that request. To overcome this issue, we need to override the default collection limit of 256 which is provided by spring framework.
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
#InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.setAutoGrowCollectionLimit(600);
}
For more information, refer https://dzone.com/articles/spring-initbinder-for-handling-large-list-of-java

Related

JAX-RS REST service + EJB on WildFly 10, always adds no-cache HTTP header in responses

I have wrote a stateless EJB that provides a rest service.
I am working with the Wildfly 10 application server and developing with the Netbeans IDE.
I have tried to cache the return values of few methods for few hours by adding a max-age header in the http-response of the service methods. Please consider this is a simplified version of my bean:
#Stateless
#DeclareRoles({"role1","role2"})
#RolesAllowed({"role1","role2"})
#Path("api-dummy")
public class DummyApiREST {
#EJB
private StuffFacade stuffFacade;
#GET
#Path("get-stuff")
#Produces({MediaType.APPLICATION_JSON})
public Response findStuff() {
Stuff stuff = stuffFacade.getStuff();
Response.ResponseBuilder builder = Response.status(Response.Status.OK).entity(stuff);
Utils.setCacheHeader(maxAgeSeconds, builder);
return builder.build();
}
}
And the setCacheHeader method:
private static Response.ResponseBuilder setCacheHeader(int maxAgeSeconds, Response.ResponseBuilder builder) {
CacheControl cc = new CacheControl();
cc.setNoCache(false);
cc.setNoStore(false);
cc.setMaxAge(maxAgeSeconds);
cc.setPrivate(true);
builder.cacheControl(cc);
return builder;
}
But the returned response of "get-stuff" always contains a duplicate of the Cache-Control header; the duplicate header contains no-cache directives (the is also a Pragma header):
HTTP/1.1 200 OK
Expires: 0
Cache-Control: no-cache, no-store, must-revalidate
Cache-Control: no-transform, max-age=60, private
X-Powered-By: Undertow/1
Server: WildFly/10
Pragma: no-cache
Date: Thu, 13 Apr 2017 15:11:17 GMT
Connection: keep-alive
Content-Type: application/json
I suppose the problem is caused by a default behaviour--or filter-- for the JAX-RS services in my EJBs. My questions are:
Is there a better way to set the max-age and enable caching in JAX-RS + EJB?
Is there a way to disable this no-cache default behaviour? (OR in other words, where is this usually configured?)
..and..what is wrong in my solution? :-)
NOTE: Perhaps it is not related, I have configured a jdbc security-domain and users authenticate and principal(s) work well.
Regards
I have found the solution.
By default Wildfly (and I think JBoss too) adds the no-cache directives to all the private resources (resources that needs authentication).
You have to change the configuration in standalone.xml file, by adding an attribute disable-caching-* to the server-container tag:
<servlet-container name="default" disable-caching-for-secured-pages="false">
<jsp-config/>
<websockets/>
</servlet-container>
In this way no more Pragma and nocache directives will be added to responses and the code I posted in my question, it simply works as expected.
EDIT: Remind, when requests for private resources, at the same URL, have to return different contents to different users you have to:
add the private header to that responses, for your reverse proxy to
not cache that content OR in alternative..
..left the nocache header there for that responses

Why does my Web API return 404 on all resources when called from a Console app?

I have a little Web API, almost directly from the standard VS project template, i.e. Home and Values controllers, and lots of MVC cruft. It is set to run and debug under IIS 10.
I have set up tracing by adding the package Microsoft.AspNet.WebApi.Tracing and the following code in WebApiConfig:
public static void Register(HttpConfiguration config)
{
config.EnableSystemDiagnosticsTracing();
SystemDiagnosticsTraceWriter traceWriter = config.EnableSystemDiagnosticsTracing();
traceWriter.IsVerbose = true;
traceWriter.MinimumLevel = TraceLevel.Debug;
config.Services.Replace(typeof(ITraceWriter), new SimpleTracer());
...
...
}
SimpleTracer is an ITraceWriter that writes to a text file.
When I call the API from outside the VS ecosystem, i.e. from PostMan in Chrome, a bad url, that results in a 404 error message, and the creation of a new trace file if there's not already one. Of I call it from PostMan with a good url, I get the expected result, and a trace of the request in the trace file.
When I call it from my Console app, even with a good url, I still get a 404 error response, and nothing is written to the trace file. I made sure by removing it and IIS doesn't even re-create it when using the .exe client.
If I call it from the compiled .exe from outside VS, I get the same error.
Then, when I set the Web API to use IIS Express, everything works perfectly. Do I need CORS for calls from non-web apps, does IIS need an extra header in this case? What is wrong?
EDIT A: This is the request when I use PostMan, and it returns a 200 and the expected list of strings.
GET /DemoApi/api/values HTTP/1.1
Host: localhost
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: f9454ffc-6a8d-e1ed-1a28-23ed8166e534
and the response and headers:
["value1","value2","value3","value4","value5","value6","value7"]
Cache-Control →no-cache
Content-Length →64
Content-Type →application/json; charset=utf-8
Date →Tue, 13 Dec 2016 06:20:07 GMT
Expires →-1
Pragma →no-cache
Server →Microsoft-IIS/10.0
X-AspNet-Version →4.0.30319
X-Powered-By →ASP.NET
EDIT B: This is the request sent using HttpClient:
GET http://abbeyofthelema/api/values HTTP/1.1
Accept: application/json
Host: abbeyofthelema
Connection: Keep-Alive
The only real difference is that because Fiddler doesn't capture traffic from localhost, I had to use my computer name instead. The same recipient still gets the request.
The response here is:
HTTP/1.1 404 Not Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Tue, 13 Dec 2016 08:07:25 GMT
Content-Length: 4959
According to Timothy Shields at the following link
Why is HttpClient BaseAddress not working?
You must place a slash at the end of the BaseAddress, and you must not place a slash at the beginning of your relative URI

401 error when using a web service in sapui5

I am implementing a web service into my sapui5 table by
var oModel = new sap.ui.model.odata.ODataModel("http://mywebservice.com/security.svc", false);
sap.ui.getCore().setModel(oModel);
When I launch my code in a web browser and inspect element, I am getting the following errors:
Failed to load resource: the server responded with a status of 401 (Unauthorized)
XMLHttpRequest cannot load http://mywebservice.com/security.svc/$metadata. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:53457' is therefore not allowed access. The response had HTTP status code 401.
I also tested it in Fiddler and I get:
HTTP/1.1 401 Unauthorized
Cache-Control: private
Server: Microsoft-IIS/8.0
Set-Cookie: ASP.NET; path=/; HttpOnly
X-AspNet-Version: 4.0.30319
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Tue, 09 Jun 2015 19:33:51 GMT
Content-Length: 0
Proxy-Support: Session-Based-Authentication
Any help on how to fix the 401 error would be greatly appreciated.
Creating a new ODataModel, it tries to fetch the metadata for the service you have called.
It's basically XMLHttpRequest to a different domain(http://mywebservice.com) than you page(localhost) is on.So the browser is blocking it as it usually allows a request in the same origin for security reasons. Read about same-origin policy
Solution:
You need to do something different when you want to do a cross-domain request.
the origin (where the page with JavaScript is at) and the target: http://mywebservice.com (where the JavaScript is trying to reach) domains must be the exact same.
A tutorial about how to achieve that is Using CORS.
In .NET server,you can configure this in web.config as below
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="your_clientside_websiteurl" />
</customHeaders>
</httpProtocol>
<system.webServer>
Just clone the shortcut for chrome on your desktop, and then in the shortcut properties add the parameter --disable-web-security at the end of chrome executable path
e.g
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security
NB:add that parameter --disable-web-security in Target location after one space

Change Response from HTTP Request sent by a program

I have a program that activate an chip for racing results. (Its just a piece of hardware).
I watch with Fiddler (Sniffing program) the in and outgoing traffic from my pc when I connect the chip with my computer.
The program sends the following HTTP Request:
POST http://example.com/index.php HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Content-Length: 185
Content-Type: application/x-www-form-urlencoded
Host: example.com
Pragma: no-cache
User-Agent: SomeProgram 1.2.3
Data==%0D%0AAjlFNEEw-SOMELONGSECRETKEY-RGAw%3D%3D%0D%0A
I receive the following response:
<?xml version="1.0" encoding="utf-8"?>
<message type="3" result="1" txid="someid" activationdate="" availablecredits="732" firstname="John" lastname="Doe" email="JohnDoe#outlook.com" phonenumber="00123445" notification_email="1" notification_text="1"/>
Is it possible to edit the response so that when the programs check for the availablecredits variable, he get the value 9999 instead of 732.
Im working on a Windows 8 laptop.
Definitely - Fiddler allows you to modify requests and responses by adding rules to FiddlerScript. Citing Fiddler documentation:
To make custom changes to web requests and responses, use
FiddlerScript to add rules to Fiddler's OnBeforeRequest or
OnBeforeResponse function. Which function is appropriate depends on
the objects your code uses: OnBeforeRequest is called before each
request, and OnBeforeResponse is called before each response.
So, all you have to do is to add to OnBeforeResponse the logic for replacing the availablecredits attribute value with any value you desire.

asp.net web service return invalid XML

i have a web service its run locally, but when i hosted on AWS its not running from my client I get the error "System.ServiceModel.ProtocolException: There is a problem with the XML ..."
I tried to call it from SoapUI its working
this is the request :
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:her="http://HerakiNet.com/">
<soapenv:Header/>
<soapenv:Body>
<her:SayHello>
<!--Optional:-->
<her:name>Ahmed</her:name>
</her:SayHello>
</soapenv:Body>
</soapenv:Envelope>
and the response as raw:
HTTP/1.0 200 OK
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Date: Sun, 29 Dec 2013 11:12:39 GMT
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Content-Length: 359
X-Cache: MISS from UB15-WMJ-080811
Via: 1.1 UB15-WMJ-080811:3128 (Lusca)
Connection: keep-alive
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><SayHelloResponse xmlns="http://HerakiNet.com/"><SayHelloResult>Hello , Ahmed</SayHelloResult></SayHelloResponse></soap:Body></soap:Envelope>
can any one help??
this is the result of executing a small test from DotNet App:
System.ServiceModel.ProtocolException: There is a problem with the XML that was
received from the network. See inner exception for more details. ---> System.Xml
.XmlException: The data at the root level is invalid. Line 1, position 1 ...
the application code is:
var client = new EstimatorWcfService.EstimatorWebServiceSoapClient();
Console.WriteLine(client.SayHello("Ahmed"));
According to error, you are calling wrong end point url from your client.
There would be two urls in service tag in your wsdl one for http and another for https. May be you are using https one instead of http. Cross check from soap ui (at top of your request).

Resources