Jersey ExceptionMapper implementations skipped on deploy - java

In my pet project I have a simple jersey (v 2.13) resource that performs some crud operations, and the input is validated by hibernate-validator (v 5.0.1.Final).
The problem is that while the junit tests works as expected, when I deploy the webapp all the ExceptionMapper implementations are ignored.
Here some details:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public JsonResult<User> addUser(#Valid Userbean user) {
//do stuff...
}
The validation is made by hibernate-validator.
the Userbean is annotate with:
#NotNull
private String password;
I've created an ExceptionMapper implementation:
#Provider
public class ValidationExceptionMapper implements ExceptionMapper<ValidationException> {
#Override
public Response toResponse(ValidationException e) {
return Response.status(422).build();
}
}
Leaving aside that on validation the proper status code should be 400, my problem is that while in my junit-test everything goes fine...
Userbean entity = new Userbean();
entity.setUsername(username);
Response response = target.path("users").request(MediaType.APPLICATION_JSON).post(Entity.json(entity));
int status = response.getStatus();
assertEquals(422 status);
...I cannot reproduce the same behaviour when I run it on tomcat (I've tried tomcat7 / tomcat 8 and also glassfish 4.1)
I always get a 400 status code instead of 422 and ValidationExceptionMapper is being skipped.
$ curl -v -X POST -H "Content-Type: application/json" --data "{\"username\":\"MrFoo\"}" http://localhost:8080/playground-webapp/jaxrs/jersey/users/
* About to connect() to localhost port 8080 (#0)
* Trying ::1... connected
> POST /playground-webapp/jaxrs/jersey/users/ HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: localhost:8080
> Accept: */*
> Content-Type: application/json
> Content-Length: 20
>
* upload completely sent off: 20out of 20 bytes
< HTTP/1.1 400 Bad Request
< Server: Apache-Coyote/1.1
< Content-Type: text/html;charset=utf-8
< Content-Language: en
< Content-Length: 990
< Date: Sun, 28 Dec 2014 15:07:34 GMT
< Connection: close
<
* Closing connection #0
<html><head><title>Apache Tomcat/7.0.52 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 400 - Bad Request</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Bad Request</u></p><p><b>description</b> <u>The request sent by the client was syntactically incorrect.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.52</h3></body></html>
The same call made on the test server works as expected:
curl -v -X POST -H "Content-Type: application/json" --data "{\"username\":\"MrFoo\"}" http://localhost:8080/users/
* About to connect() to localhost port 8080 (#0)
* Trying ::1... Connessione rifiutata
* Trying 127.0.0.1... connected
> POST /users/ HTTP/1.1
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: localhost:8080
> Accept: */*
> Content-Type: application/json
> Content-Length: 20
>
* upload completely sent off: 20out of 20 bytes
< HTTP/1.1 422
< Content-Type: application/json
< Date: Sun, 28 Dec 2014 15:05:35 GMT
< Content-Length: 94
<
* Connection #0 to host localhost left intact
the code of the server I use for junit is:
#Before
public void setUpClient() throws Exception {
ResourceConfig rc = new UserResourceConfig();
rc.property("contextConfig", appContext);
server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, rc);
server.start();
....
Thanks in advance for your help.

Related

RestTemplate with Proxy with kerberos authentication in Java/Kotlin

I'm trying to access rest api through my companies proxy server this requires me authenticate with the proxy.
I can access the outside world using curl with the parameters:
curl -v -s -user $kerbrosId -x $ProxyServer:$proxyPort --proxy-negotiate https://google.com
I receive the following output:
Enter proxy password for user '$user':
* Trying $proxyIP:$proxyPort...
* Connected to $proxyURL ($proxyIP) port $proxyPort (#0)
* allocate connect buffer
* Establish HTTP proxy tunnel to google.com:443
* Proxy auth using Negotiate with user 'bradsw'
> CONNECT google.com:443 HTTP/1.1
> Host: google.com:443
> Proxy-Authorization: Negotiate ${shortBase64token}
> User-Agent: curl/7.83.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 407 Proxy Authentication Required
< Proxy-Authenticate: NEGOTIATE ${longerBase64token}
< Cache-Control: no-cache
< Pragma: no-cache
< Content-Type: text/html; charset=utf-8
< Proxy-Connection: Keep-Alive
< Connection: Keep-Alive
< Content-Length: 5621
<
* Ignore 5621 bytes of response-body
* Establish HTTP proxy tunnel to google.com:443
* Proxy auth using Negotiate with user '$user'
> CONNECT google.com:443 HTTP/1.1
> Host: google.com:443
> Proxy-Authorization: Negotiate ${evenLongerBase64token}
> User-Agent: curl/7.83.1
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed
* schannel: disabled automatic use of client certificate
* ALPN: offers http/1.1
* ALPN: server accepted http/1.1
> GET / HTTP/1.1
> Host: google.com
> User-Agent: curl/7.83.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Location: https://www.google.com/
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 29 Sep 2022 22:09:00 GMT
< Expires: Sat, 29 Oct 2022 22:09:00 GMT
< Cache-Control: public, max-age=2592000
< Server: gws
< Content-Length: 220
< X-XSS-Protection: 0
< X-Frame-Options: SAMEORIGIN
< Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
I have tried a million variations of
RestTemplate(HttpComponentsClientHttpRequestFactory(
HttpClientBuilder.create()
.setProxy(HttpHost(proxyUrl, proxyPort))
//other calls here to set things up
.build()
)
)
Nothing seems to authenticate correctly. I get back a 407 PROXY_AUTHENTICATION_REQUIRED with the companies default call the help desk if your browser doesn't work page in my stack trace.
Our systems are configured with an appropriate kbr5.config file so that should not be the issue & in other places in the code we are getting an SSO token a based on a ticket stored by kinit using the equivalent of RestTemplate().getForEntity("${sso-endpoint}", String::class.java).
I would ideally like to be able to delegate credentials to the OS via logged on user (either windows or REL based Linux systems) though I would consider simply authenticating at all a win at this point. I'm working in Kotlin but can easily translate a Java solution to Kotlin.
Any ideas appreciated?

Spring Boot redirecting POST in context path

The application return redirect (302) when i make a POST in base context path, and i get a error.
My application.properties
...
server.servlet.context-path=/api/v1/application
...
My controler
#RestController
public class RestService {
#PostMapping
#ResponseStatus(HttpStatus.CREATED)
public ResponseDTO myMethod(#RequestBody RequestDTO requestDTO) {
log.trace("m=myMethod");
return service.insert(requestDTO);
}
}
If I make POST in http://localhost:8080/api/v1/application
I get a Redirect 302 to http://localhost:8080/api/v1/application/ and if the client follow redirect the application return 405 (method not allowed)
Curl
C:\>curl -v -X POST http://localhost:8080/api/v1/customer
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /api/v1/customer HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 302
< Location: http://localhost:8080/api/v1/customer/
< Transfer-Encoding: chunked
< Date: Mon, 31 Aug 2020 23:34:07 GMT
<
* Connection #0 to host localhost left intact

Spring Boot returns "200 OK" (Empty Response) for resource directory, not file

I am building a basic Spring Boot app, using the built is resource handler.
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/public/")
.setCachePeriod(60 * 60 * 24 * 365)
.resourceChain(true)
.addResolver(versionResourceResolver);
The file structure is as follows:
src
main
java
..
resources
public
js
app.js
Making a request to localhost:8080/js/app.js works as expected, returning the contents of the file with the correct MIME type.
However, making a request to the container directory also returns 200 OK and an empty response!
$ curl -v http://localhost:8080/js/
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /js/ HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 28 Nov 2016 21:13:26 GMT
< X-Application-Context: application
< Last-Modified: Mon, 28 Nov 2016 21:06:28 GMT
< Cache-Control: max-age=31536000
< Accept-Ranges: bytes
< Content-Type: application/octet-stream
< Content-Length: 0
<
* Connection #0 to host localhost left intact
How can I get this to return 404 Not Found instead? It's not a huge issue, but definitely not what I'd expected.

Dropwizard resource error response

In my dropwizard resource, I'm using the built in Jackson JSON object mapping to bind my data.
public class WidgetServiceResource {
#POST
#Path("/widget")
#Produces(MediaType.APPLICATION_JSON)
public Response foo(ModelParameters c) {
return Response.ok(c.value).build();
}
What I noticed however, is when I POST a bad body, the JSON doesn't parse, and I'm served with a response that doesn't meet my company's communication standards. How can I customize the response?
You need to deregister all default exception mappers and then register your own to handle the exception you want:
For example, in your yaml, you need:
server:
registerDefaultExceptionMappers: false
rootPath: /api/*
requestLog:
appenders: []
applicationConnectors:
- type: http
port: 9085
logging:
level: INFO
Note: registerDefaultExceptionMappers: false will tell DW to not register any ExceptionMappers.
Then, you can implement them yourself. In my case, I will just do a catch-all handler:
public class MyExceptionMapper implements ExceptionMapper<Exception> {
#Override
public Response toResponse(Exception exception) {
return Response.status(400).entity("This makes no sense").build();
}
}
This reacts to any exception and responds with a 400 and a String.
Finally, registering in the main class:
environment.jersey().register(MyExceptionMapper.class);
And a test for proof:
artur#pandaadb:~/dev/eclipse/eclipse_jee$ curl -v "http://localhost:9085/api/viewTest"
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
> GET /api/viewTest HTTP/1.1
> Host: localhost:9085
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Date: Wed, 12 Oct 2016 10:16:44 GMT
< Content-Type: text/html
< Content-Length: 19
<
* Connection #0 to host localhost left intact
This makes no sense
Hope that helps,
-- Artur

cURL JSON + Cookies + Header Params + Jersey

I'm trying to send a request, I do the following in curl:
curl -v --header "location: 60.004:8.456" --cookie "sessionToken=~session" -i -X PUT -H 'Content-Type: application/json' -d '{"data":"{"FCT":"Welcome", "Uni":"Welcome to DI"}"}' localhost:8080/tester/apps/e39/data
and for some reason it matches the class but no this method:
#PUT
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response createDocumentRoot(JSONObject inputJsonObj,
#Context UriInfo ui, #Context HttpHeaders hh) {
}
Edit:
The class is defined with #Path("{appId}/data")
The problem isn't the paths, as I've debugged it and seen it identifies the class right, it just throws the bad request after going inside the class without entering any method.
Here is the curl verbose:
* About to connect() to localhost port 8080 (#0)
* Trying 127.0.0.1... connected
> PUT /tester/apps/e39/data HTTP/1.1
> User-Agent: curl/7.22.0 (i686-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
> Host: localhost:8080
> Accept: */*
> Cookie: sessionToken=~session
> location: 60.004:8.456
> Content-Type: application/json
> Content-Length: 60
>
* upload completely sent off: 60out of 60 bytes
< HTTP/1.1 400 Bad Request
HTTP/1.1 400 Bad Request
< Server: Apache-Coyote/1.1
Server: Apache-Coyote/1.1
< Content-Type: text/html;charset=utf-8
Content-Type: text/html;charset=utf-8
< Content-Length: 990
Content-Length: 990
< Date: Tue, 02 Jul 2013 21:46:56 GMT
Date: Tue, 02 Jul 2013 21:46:56 GMT
< Connection: close
Connection: close
The problem was in the json syntax that was incorrect, I had
'{"data":"{"FCT":"Welcome", "Uni":"Welcome to DI"}"}'
after changing to this, it worked fine:
'{"data":
{"FCT":"Welcome",
"Uni":"Welcome to DI"}}'
I used a JSON online parser to check the json syntax, here is the link incase someone needs it:
http://json.parser.online.fr/

Categories

Resources