I am using Jersey 2.5.1 with Jackson 2.2. for building JSON Rest web services. I kind of got it up and running also with 2 ExceptionMappers but for a "not-json" request the application is not throwing any exception!
ExceptionMapper
Will be invoked if e.g. a NullPointerException is thrown
ExceptionMapper
Will be invoked if there s a problem with the JSon Mapping
My Problem:
1. Request Body: {} works
2. Request Body: {} with an application side NullPointer invoked the first exception mapper
3. Request Body: "jibberish" does not invoke anything (not caught by any ExceptionMapper) cause no Exception is thrown. Unfortunately the response body is sth like : Unrecognized field "xxx" (class com.sample.MyDto), not marked as ignorable (9 known properties...
....> but I want to customize the error msg since I am always returning a JSon object.
Ok, I solved it. What finally made me think the right way was, that sometimes it worked so it had to be some overwrite class loading issue.
In my ApplicationClass I registered Providers based on packages like this
#ApplicationPath("resources")
public class JerseyApplication extends ResourceConfig {
public JerseyRestApplication() {
packages("com.sample", "com.fasterxml.jackson.jaxrs.json");
}
}
If you look sharp you might see the error! I am putting "com.fasterxml.jackson.jaxrs.json" on the search path because I want to use the JacksonJsonProvider.class. What I did not know is, that in that package there are also some JSonMappers for JSonParseException etc. and those do not log :)
So sometimes the application was loading mine first and sometimes the one from jackson.
So I am going to stick with the following now:
#ApplicationPath("resources")
public class JerseyRestApplication extends ResourceConfig {
public JerseyApplication() {
register(JacksonJsonProvider.class); // Do it manually
packages("com.sample");
}
}
Hope that helps sb :D
I also found sometime coustom ExceptionMapper not work, and it's not always work or not work.
so i debug the jersey's source code .
class: org.glassfish.jersey.server.ServerRuntime, methed:mapException
...
final long timestamp = tracingLogger.timestamp(ServerTraceEvent.EXCEPTION_MAPPING);
**ExceptionMapper mapper = runtime.exceptionMappers.findMapping(throwable);**
if (mapper != null) {
request.getRequestEventBuilder().setExceptionMapper(mapper);
...
if the mapper is null, the coustom ExceptionMapper will be not work.
class: org.glassfish.jersey.internal.ExceptionMapperFactory methed: ExceptionMapperFactory
the Exception Mapper :(there two Exception mapping one same Exception: java.lang.Exception)
org.glassfish.jersey.server.mvc.internal.ErrorTemplateExceptionMapper#6473fc2,class
java.lang.Exception
...
com.baidu.ssp.web.ws.exception.BaseExceptionMapper#7a84639c,class
java.lang.Exception
it's because in MvcFeature:
#Override
public boolean configure(final FeatureContext context) {
final Configuration config = context.getConfiguration();
if (!config.isRegistered(ErrorTemplateExceptionMapper.class)) {
context.register(ErrorTemplateExceptionMapper.class);
context.register(new MvcBinder());
return true;
}
return false;
}
the ErrorTemplateExceptionMapper is also add to ExceptionMapper.
so i change my custom MapperException's genericity type :
ExceptionMapper
to
ExceptionMapper
may be my resolution is not fit for you ,
the main problem is the ExceptionMapper.
Related
I have a multi-module maven Springboot project in Java.
Resource classes are generated from yaml, so that, e.g.
type: object
required:
- myFlag
properties:
myFlag:
type: boolean
example: false
yields a resource class with a Boolean property
#JsonProperty("myFlag")
private Boolean myFlag;
My problem begins when I test ways someone could post this resource with wrong values (I expect success only when this field is posted with JSON yielding a boolean, e.g.
{
"main": "whatever",
"subpart": {
"myFlag": false
}
}
).
However, jackson evidently tolerates numbers instead of booleans. I'd like it not to. I have looked for tuning settings that might have a bearing on this, but didn't find any obvious ones (for example
spring.jackson.deserialization.accept-float-as-int=false
solved a related problem of parsing that was too lenient for our taste.) I tried setting several but haven't been able to get a HttpMessageNotReadableException exception -- the usual variety for these kinds of events -- to fire.
Incidentally, these exceptions fire as hoped for in unit tests such as:
#Test
public void post_with_Integer_instead_of_Boolean_yields_400_Status() throws Exception {
ResultActions resultActions = mockMvc
.perform(MockMvcRequestBuilders
.post(PATH)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content("{\"main\": \"whatever\", \"subpart\": {\"myFlag\": 123}}"));
resultActions.andExpect(status().is(400));
}
but, alas, not when the service is "really" running. This would seem to be a clue, but I haven't been able to figure out how to use it.
I'd be grateful for any pointers that would help me get a handle on this.
I'm a bit confused about those things I currently see in our Spring MVC application and I hope someone can tell me what we're making wrong. Since google doesn't have an answer for me I'm sure we're making wrong.
We've a simple Spring 4.1.5.RELEASE application. Nothing special to mention about it. There is a MappingJackson2HttpMessageConverter configured to deliver JSON to the clients in RestControllers via Jackson ObjectMapper.
All entities which get serialized via jackson have the following annotation on tpe level
#JsonIdentityInfo(generator = IntSequenceGenerator.class, property = "#jsonObjectId")
Now the strange part:
There is a spring integration test which does the following (objectMapper gets autowired from the web application context, it is the same instance which converts the request paylod)
objectMapper.writeValueAsString(dummy) // generate json from dummy object
mockMvc.perform(post(...)) // make a post request with JSON payload generated
evaluate reponse
Executing the test once is okay. If I copy that test case and execute it twice then I get a 400 from the server back saying IllegalArgumentExecption -> Already had POJO for id ... Problem can be reproduced in real world application so it seems to be no test problem.
I've figured out, that on serialization process the IntSequenceGenerator which is in charge of generating the "jsonObjectId" properties gets created every time an object needs to be serialized. Ok so far. But the corrresponding counterpart, in our case the default used SimpleObjectIdResolver from jackson is always the same instance. So the second server request (the second deserialization process) leads to that exception in SimpleObjectIdResolver.
I would be very thankful if anybody could give me a hint, what we're making wrong ...
Forgot to mention: Jackson-Core 2.4.1 was used. We now upgraded to version 2.7.0 of jackson and the SimpleObjectIdResolver now gets recreated for every deserialization. This seemed to be a bug in jackson before 2.7.0.
Edit: I was able to reduce the issue to the following small test:
public class DummyTest {
private Dummy dummy = new Dummy();
#Before
public void setUp() {
dummy.setFoo("Foo");
}
#Test
public void testApp() throws Exception {
ObjectMapper mapper = new ObjectMapper();
String dummyAsJsonString = mapper.writeValueAsString(dummy);
mapper.readValue(dummyAsJsonString, Dummy.class);
mapper.readValue(dummyAsJsonString, Dummy.class);
}
}
where Dummy.class is defined as
#JsonIdentityInfo(generator = IntSequenceGenerator.class, property = "#jsonObjectId")
public class Dummy {
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
You will get an IllegalStateException when executing it with jackson 2.4.1
I would like to know what is the best way to handle validation errors in medium/big Java EE application.
Suppose I have managed bean and facade as it is below.
class SomeManagedBean {
#EJB
SomeFacade someFacade;
public void performSomeAction() {
(...)
someFacade.businessAction(loggedUser, editedEntity);
(...)
}
}
class SomeFacadeImpl {
public Object businessAction(User user, Entity entity) {
if (!isInCorrectStateToDoAction(entity)) {
// error A
}
(...)
if (!hasRightToDoAction(user, entity)) {
// error X
}
doAction(user, entity);
}
}
I expect that businessAction from SomeFacade should validate their inputs and check if it can do this business action with given arguments. It's because I may use this business method in several places in application and I do not want copy validation code.
Suppose I would like to use FacesMessage to provide to client informations about validation errors.
Some solutions:
exceptions - when something is wrong with arguments I simply throw an Exception
so I have to throw IncorrectStateForActionException, NoRightToDoActionException
why not: I can throw only one exception so I can't notify user about several things: "You don't have rights", (...), "Entity is incorrect state"
beside exception shouldn't be used to provide logic of our application
some Result class
class Result<T> {
T returnedValueFromMethod;
List<ProcessingError> errors;
}
now definition of my business method looks like:
public Result<Object> businessAction(User user, Entity entity)
when something is wrong I add error information to Result
when everything is all right I put returned value to my Result object and return this object
why not: this seems like kind of "error code" in pretty complex structure. Because of that recommendation which tells "change error codes into exception" it's understandable why we would like to avoid it.
we can do validation in facade and controller
why not: duplicated code
validation only in controller and action in facade
why not: it could be dangerous when we use this businessAction method from other place in code
we can do two methods in facade: validation and action (Query Command Separation)
result from validation should contain every possible error which may occur so it's pretty strange structure
we can do several methods for validation (errors from A to X)
it's easy to provide error messages
but this solutions seems just stupid
any other ideas?
What would be the best solution?
Do authentication/validation in business layer and let it throw an exception in case of failure. You can just handle it in JSF action method.
E.g.
#EJB
private SomeService service;
public void someAction() {
try {
service.doSomething();
addGlobalInfoFacesMessage("Doing something succeed!");
} catch (SomeBusinessException e) {
addGlobalErrorFacesMessage("Doing something failed with {0}", e.getMessage());
}
}
Or, you can let it go and have the container handle it by an <error-page> on the specific <exception-type>.
As to performing authentication and validation all by itself, the Java EE stack offers annotations like JAAS #RolesAllowed for authentication and JSR303 #NotNull, #Size, etc for model. This should reduce the if check boilerplate inside the service methods itself.
Sorry I am new to Spring and Java and this may be covered lots of times but I wanted to get some advice.
I'm creating a Spring web application which needs to retrieve user data from an existing REST based XML web service. I am going to create a domain object, service and DAO which uses the Spring REST template to invoke the web service.
In the DAO I was going to create a method like this:
public User getUser(String userId)
If there is a problem (for example if the user account is locked or been deleted), the web service returns a 200 response and puts an error code in the XML response. These errors should be displayed in the application and I will need to be able to identify the error so I can show custom error message to the user. What is the recommended way to handle these error, should I:
Define different exceptions (runtime) for each of the error response codes and add these to the method signature
Use a single exception (e.g. UserException) and use different messages.
Do something else
Any help would be highly appreciated.
You want to use different exception for each error type by extending Extension. if you have many different ones, try to group them using class inheritance. An example would make it simpler. Suppose you have these 2 kinds of errors, account deleted and account locked, you would do :
class AccountException
extends Exception {
}
then you extend Account extension for all the errors involving account problems, eg:
class AccountLockedException
extends AccountException {
}
and
class AccountDeletedException
extends AccountException {
}
etc... This way you make it crystal clear and don't have to look through all your exceptions. Not sure I'm clear enough, It's my first answer here. GL!
I would create a single Exception class for a category. For instance, for all user related exceptions, you can create something like below:
This way, it will be clean to catch one exception and verify the error code to find what caused the exception.
public class MyException extends Exception{
public static final int ERR_USER_NOT_FOUND = 101;
public static final int ERR_DB_ACCESS_ERR = 500;
private int errorCode;
public MyException(int errCode){
this.errorCode = errCode;
}
public int getErrorCode() {
return errorCode;
}
}
I've faced an interesting aim, this aim targets the exception handling in existing web application written with wicket and hibernate frameworks,
suppose we have web app which is deployed in server and sometimes it produces runtime exceptions, the problem is how to get and save their stacktrace to db without modifying all classes(about 80 models and 150 views).
Hope i gave all clear.
Thanks in advance.
You can use an IRequestCycleListener to log/handle your exceptions:
public class MyExceptionReporter extends AbstractRequestCycleListener {
#Override
public IRequestHandler onException(RequestCycle cycle, Exception ex) {
// log exception here
return null;
// if you want to also show an error page:
// return new RenderPageRequestHandler(new PageProvider(new ExceptionPage(ex)));
}
}
Then register it in WebApplication#init:
getRequestCycleListeners().add(new MyExceptionReporter());
Wicket 1.4 and earlier
Override Application.newRequestCycle() and return a custom subclass of WebRequestCycle that overrides RequestCycle.logRuntimeException() in order to provide additional logging behavior for all RuntimeExceptions in your application. Notice that any uncaught Exception will be wrapped by Wicket in a WicketRuntimeException (as stated in the Exception handling section of Request cycle and request cycle processor) :
There, use a Service/DAO component that will insert the exception message along with the stacktrace into the database. Remember that depending on the dbms, you might want to use a CLOB instead of a varchar type (for instance, in Oracle, a varchar column cannot hold more than 4000 bytes).
Here's an (untested) example:
public class myApplication extends WebApplication {
...
#Override
public RequestCycle newRequestCycle(Request request, Response response) {
return new myRequestCycle(this, (WebRequest) request, (WebResponse) response);
}
}
public class myRequestCycle extends WebRequestCycle {
...
#Override
protected void logRuntimeException(RuntimeException rex) {
super.logRuntimeException(rex);
Writer w = new StringWriter();
t.printStackTrace(new PrintWriter(w));
String stackTrace = w.toString();
someService.logExceptionToDB(rex.getMessage(),stackTrace);
}
}
Wicket 1.5 and later
See #Cristoph's answer
Write a utility which uses StackTraceElement[] to give you the complete stacktrace. Use an implementation of OutputStream to push it to a CLOB object. (I don't think BLOB is needed)