How to catch already caught exception? - java

I have the follow the following filter:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
try {
chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
} catch (XssAttackException e) {
request.getRequestDispatcher("/XssAttack").forward(request, response);
}
}
and the class XssAttackException is:
public class XssAttackException extends RuntimeException {
private static final long serialVersionUID = 1L;
}
after debugging the code, I realized that somewhere in the spring framework all the exceptions are being caught. Now I need a way that my catch bock also run.
UPDATE
inside XSSRequestWrapper we have:
#Override
public String getHeader(String name) {
String value = super.getHeader(name);
return stripXSS(value);
}
And
private String stripXSS(String value) {
if (value != null) {
value = persianUtf8(value);
if (!value.equals(Jsoup.parse(value).text())) {
throw new XssAttackException();
}
value = Jsoup.parse(value).text();
for (Pattern scriptPattern : patterns) {
if (scriptPattern.matcher(value).matches()) {
throw new XssAttackException();
}
value = scriptPattern.matcher(value).replaceAll("");
}
}
return value;
}

Please don't assume this is answer for your question.Assumed too long comment.
I created my CustomException class.
public class CustomException extends RuntimeException {
}
and created custom Servlet class as your XSSRequestWrapper and throw my custom exception in constructor.
public class MyServlet implements ServletRequest {
public MyServlet() {
throw new CustomException();
}
// other override methods go here
}
and in my filter class
try {
chain.doFilter(new MyServlet(), response);
} catch (CustomException e) {
System.out.println("xxxxxxxxxxxxxxx I got it xxxxxxxxxxxxxxxxxxx");
}
This code work fine. At your program , I think there has some exception has occured and you did not catch on them. So , this exception object has miss from your try block of your filter class and handled by Spring container.

Related

Data inconsistency in multithreaded environment

I have created an application which reads & writes into a remote file. I have different files (A.properties, B.properties, C.properties) in different directories (folder-1, folder-2, folder-3). Each directory has the same filename with different data.
I have implemented concurrency in my application by using the LockRegistry provided by this other answer. The issue is that if a thread is accessing A.properties while another thread accesses B.properties, the propertyMap displayed to the end user will contain both data from property files. How can I resolve this issue?
My code:
public class UDEManager
{
private Map<String, String> propertyMap = new TreeMap<>();
HttpSession session = null;
public UDEPropertyManager()
{
super();
}
public void init(ServletConfig config) throws ServletException
{
super.init(config);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// Code for calling thread for read/write operations into remote
// file and fill the propertyMap
}
}
class WebAppProperty implements Runnable
{
private WebApp webapp; // folder-1
private String propertyFile; // A.properties
private String keyValue; //messages-title=Messages
private LockType mode;
public String getPropertyFile()
{
return propertyFile;
}
public void setPropertyFile(String propertyFile)
{
this.propertyFile = propertyFile;
}
#Override
public void run()
{
try {
LockRegistry.INSTANCE.acquire(propertyFile, mode);
if (this.mode == LockType.WRITE) {
writeToPropertyFile();
} else if (this.mode == LockType.READ) {
getProperty(this.webapp, this.propertyFile);
}
} catch (Exception ie) {
sysoutAndLog("Thread is Interrupted");
ie.printStackTrace();
} finally {
LockRegistry.INSTANCE.release(propertyFile, mode);
}
}
private boolean getProperty(WebApp webapp, String property)
{
try {
// read from file and put it into Map instance variable
// of calling class (UDEManager)
propertyMap.put(key, value);
} catch(Exception e) {
sysoutAndLog("Error while reading property ");
e.printStackTrace();
}
return false;
}
private void writeToPropertyFile()
{
try {
// Write data into remote file
} catch (Exception e) {
sysoutAndLog("exception while writing to file.");
e.printStackTrace();
}
}
}
You should associate the properties map with the user session or request

Is an evaluated function in Nashorn reusable from different threads?

Is it possible to reuse one and the same Nashorn engine and one and the same JavaScriptObject, which results as the evaluation of a JS-function, for all servlet requests, if the function does not change any shared object but uses only the arguments given with the call? Look at the following example:
public class MyServlet extends HttpServlet {
private ScriptEngineManager factory;
private ScriptEngine engine;
private ScriptObjectMirror script;
#Override
public void init() throws ServletException {
try {
factory = new ScriptEngineManager();
engine = factory.getEngineByName("nashorn");
script = (ScriptObjectMirror)engine.eval("function(writer) {writer.print('Hello, World!');}");
} catch (ScriptException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
try (PrintWriter writer = res.getWriter()) {
script.call(null, writer);
writer.close();
} catch (IOException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
Is this thread-safe?
This is a follow-up to Reuse Nashorn ScriptEngine in Servlet
Edit:
I'm not sure what difference this makes for the question at hand, but to focus on the more interesting question, under which circumstances a call to an evaluated js-function is thread save, I made all fields final now. So the code is:
public class MyServlet extends HttpServlet {
final private ScriptEngineManager factory;
final private ScriptEngine engine;
final private ScriptObjectMirror script;
public MyServlet() {
factory = new ScriptEngineManager();
engine = factory.getEngineByName("nashorn");
ScriptObjectMirror _script = null;
try {
_script = (ScriptObjectMirror) engine.eval("function(writer) {writer.print('Hello, World!');}");
} catch (ScriptException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
script = _script;
}
#Override
public void init() throws ServletException {
}
#Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
try (PrintWriter writer = res.getWriter()) {
script.call(null, writer);
writer.close();
} catch (IOException ex) {
Logger.getLogger(MyServlet.class.getName()).log(Level.SEVERE, null, ex);
}
}
None of your instance variables are safely published, so that's a big "no" right there. Also none of the documentation says that the classes you use are thread safe, so without some further documentation saying differently you have to assume that they are not thread safe.
Answer: nope.

How to make Jackson throw exception as is when deserialization mapping fail

Jackson has a weird behavior in handling Exceptions that occur during deserialization mapping: it throws a JsonMappingException whose .getCause() returns the innermost of the exception chain.
//in main
ObjectMapper jsonMapper = new ObjectMapper();
String json = "{\"id\": 1}";
try {
Q q = jsonMapper.readValue(json, Q.class);
} catch (JsonMappingException e) {
System.out.println(e.getCause()); //java.lang.RuntimeException: ex 2
}
//class Q
public class Q {
#JsonCreator
public Q(#JsonProperty("id") int id) {
throw new RuntimeException("ex 0",
new RuntimeException("ex 1",
new RuntimeException("ex 2")));
}
}
In the code above, I use jsonMapper.readValue(..) to map the String json to an instance of class Q whose the constructor, marked #JsonCreator, throws a chain of RuntimeException: "ex 0", "ex 1", "ex 2". When the mapping fail, I expected the line System.out.println(e.getCause()); to print out ex 0, but it prints ex 2.
Why Jackson decides to do this and is there a way to configure it so that it doesn't discard my ex 0? I have tried
jsonMapper.configure(DeserializationFeature.WRAP_EXCEPTIONS, false);
but it doesn't do anything.
Inside of Jackson's StdValueInstantiator this method gets hit when an exception is thrown during deserialization:
protected JsonMappingException wrapException(Throwable t)
{
while (t.getCause() != null) {
t = t.getCause();
}
if (t instanceof JsonMappingException) {
return (JsonMappingException) t;
}
return new JsonMappingException("Instantiation of "+getValueTypeDesc()+" value failed: "+t.getMessage(), t);
}
As you can see, this will iterate through each "level" of your nested runtime exceptions and set the last one it hits as the cause for the JsonMappingException it returns.
Here is the code I needed to get this working:
Register a new module to the ObjectMapper.
#Test
public void testJackson() {
ObjectMapper jsonMapper = new ObjectMapper();
jsonMapper.registerModule(new MyModule(jsonMapper.getDeserializationConfig()));
String json = "{\"id\": \"1\"}";
try {
Q q = jsonMapper.readValue(json, Q.class);
System.out.println(q.getId());
} catch (JsonMappingException e) {
System.out.println(e.getCause()); //java.lang.RuntimeException: ex 2
} catch (JsonParseException e) {
} catch (IOException e) {
}
}
Create a custom module class.
public class MyModule extends SimpleModule {
public MyModule(DeserializationConfig deserializationConfig) {
super("MyModule", ModuleVersion.instance.version());
addValueInstantiator(Q.class, new MyValueInstantiator(deserializationConfig, Q.class));
addDeserializer(Q.class, new CustomDeserializer());
}
}
Create a custom ValueInstantiator class to override wrapException(...). Add the instantiator to the module.
public class MyValueInstantiator extends StdValueInstantiator {
public MyValueInstantiator(DeserializationConfig config, Class<?> valueType) {
super(config, valueType);
}
#Override
protected JsonMappingException wrapException(Throwable t) {
if (t instanceof JsonMappingException) {
return (JsonMappingException) t;
}
return new JsonMappingException("Instantiation of "+getValueTypeDesc()+" value failed: "+t.getMessage(), t);
}
}
Create a custom deserializer to get the module to work properly. Add this class to the module initialization as well.
public class CustomDeserializer extends StdScalarDeserializer<Q> {
public CustomDeserializer() {
super(Q.class);
}
#Override
public Q deserialize(JsonParser jp, DeserializationContext context) throws IOException {
JsonNode node = jp.getCodec().readTree(jp);
return new Q(node.get("id").asText());
}
#Override
public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException {
return deserialize(jp, ctxt);
}
}
For anyone looking for a different solution, this worked for me on Spring Boot 2.2.8.RELEASE. NB: This is example is when you have a rest controller with request body that is has an enum and clients could send a wrong field string gender and you want to provide proper error message:
#PostMapping
public ResponseEntity<ProfileResponse> updateProfile(#RequestBody #Valid ProfileRequest profileRequest) {
ProfileResponse profile = //do something important here that returns profile object response
return ResponseEntity
.status(HttpStatus.OK)
.body(profile);
}
ProfileRequest looks like
#Data //Lombok getters and setters
public class ProfileRequest{
private GenderEnum gender;
//some more attributes
}
Add this property to the aplication.properties file to make sure that our custom exception GlobalRuntimeException (see later for definition) is not wrapped in JsonMappingException exception.
spring.jackson.deserialization.WRAP_EXCEPTIONS=false
Then create a class which spring boot will auto create a bean for (This will be used for Deserializing the field gender of type enum). If we don't find an the enum, then we know to throw an error.
#JsonComponent
public class GenderEnumDeserializer extends JsonDeserializer<GenderEnum> {
#Override
public GenderEnum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String val = p.getValueAsString();
GenderEnum genderEnum = GenderEnum.fromName(val);
if(genderEnum == null){
throw new GlobalRuntimeException("Invalid gender provided. Valid values are MALE | FEMALE | OTHER");
}
return genderEnum;
}
}
The "forName" method in GenderEnum looks like below.
public static GenderEnum fromName(String name) {
GenderEnum foundGenderEnum = null;
for (GenderEnum genderEnum : values()) {
if (genderEnum.name().equalsIgnoreCase(name)) {
foundGenderEnum = genderEnum;
}
}
return foundGenderEnum;
}
We would then setup catching the GlobalRuntimeException in our ControllerAdvice:
#ResponseBody
#ExceptionHandler(GlobalRuntimeException.class)
ResponseEntity<?> handleInvalidGlobalRuntimeException(HttpServletRequest request, GlobalRuntimeException ex) {
LOGGER.error("Error " + ex);
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(new ErrorMessage(ex.getCustomMessage));
}
That's it.

Is it clean code to return in a catch block?

I have a java servlet which checks for URL parameters (last uri part, wildcard). Given these parameters, I want to respond with a 404 or an actual response. Is it clean code to do a return; in the catch block?
#WebServlet("/processes/edit/*")
public class ProcessEditServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
try {
id = StringManipulation.removeSlashes(request.getPathInfo());
numid = Integer.parseInt(id);
} catch (NumberFormatException e) {
response.sendError(404);
return;
}
request.getRequestDispatcher("/WEB-INF/processEdit.jsp").forward(
request, response);
}
}
as dognose say, its much about the personal feeling. I would refactor this code as following:
#WebServlet("/processes/edit/*")
public class ProcessEditServlet extends HttpServlet {
// you may get a logger over Dependency Injection or joust create one here...
private final Logger logger;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
if(validateRequest(request,logger){
request.getRequestDispatcher("/WEB-INF/processEdit.jsp").forward(
request, response);
}else{
response.sendError(404);
}
}
public static boolean validateRequest(Request request,Logger logger){
try {
id = StringManipulation.removeSlashes(request.getPathInfo());
numid = Integer.parseInt(id);
} catch (Exception e) {
logger.log(e); // you should at least log the exception
return false;
}
return true;
}
}
Because, its testabler, and the whole try/catch-block bloat the code and made it less readable - i know peoples encapsulating each try and catch in its own method. However, cleancode means maintainable and readable code - in my opinion its ok when you return in a catch, as long as it makes sense.
Edit1: added logger
I'm pretty sure that if you actually catch an exception here, your return statement is going to cause this line of code:
request.getRequestDispatcher("/WEB-INF/processEdit.jsp").forward(
request, response);
not to execute. If you omit the return statement, it will execute even if an exception is caught.
This is what I see wrong with the code:
No logging to tell later what happened.
A generic exception.
Where are you returning this to? How about redirect to an error
page?
But I wouldn't mind the return within the catch block if there is need to do further processing.
I think that having a return on the catch can create bugs if after the code evolves catching more exceptions and forgets the return command.
Also looking on a more expressive code, I would say that you want to validate if the request path is numeric or not. So what do you think about this code?
#WebServlet("/processes/edit/*")
public class ProcessEditServlet extends HttpServlet {
// you may get a logger over Dependency Injection or joust create one here...
private final Logger logger;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(pathIsNotNumeric(request.getPathInfo())) {
response.sendError(404);
return;
}
request.getRequestDispatcher("/WEB-INF/processEdit.jsp").forward(request, response);
}
public boolean pathIsNotNumeric(final String pathInfo){
boolean isNotNumeric = true;
try {
Integer.parseInt(StringManipulation.removeSlashes(pathInfo));
isNotNumeric = false;
} catch (NumberFormatException e) {
logger.log(e); // logging the exception
}
return isNotNumeric;
}

FacesMessages in MyFacesServlet Wrapper

I throw NullPointerException in a java bean and catch the exception in FacesServletWrapper.
in FacesServletWrapper I gets always only ServletException.
how can I catch the specific exception that I throw?
How can I continue from where I throws the exception?
in my bean:
public String getSize() {
try {
Object object = null;
object.equals("");
} catch (Exception e) {
throw new NullPointerException();
}
}
my servlet:
public class FacesServletWrapper extends MyFacesServlet {
public static final String CONFIG_FILES_ATTR = "javax.faces.CONFIG_FILES";
public static final String LIFECYCLE_ID_ATTR = "javax.faces.LIFECYCLE_ID";
private ServletConfig servletConfig;
private FacesContextFactory facesContextFactory;
private Lifecycle lifecycle;
#Override
public void service(ServletRequest request, ServletResponse response) throws IOException, ServletException {
FacesContext facesContext = facesContextFactory.getFacesContext(servletConfig.getServletContext(), request, response, (javax.faces.lifecycle.Lifecycle) lifecycle);
try {
super.service(request, response);
} catch (Throwable e) {
Locale locale = (Locale) facesContext.getExternalContext().getSessionMap().get(Constants.LOCALE);
ServletContext context = servletConfig.getServletContext();
RequestDispatcher dispatcher = context.getRequestDispatcher("/errors/error.jsf");
if (e instanceof NullPointerException) {
//here I catch only ServletException
String error = ResourceUtil.getMessage("Login_failed", locale);
facesContext.getExternalContext().getSessionMap().put("error", error);
dispatcher.forward(request, response);
((HttpServletResponse) response).sendRedirect(((HttpServletRequest) request).getContextPath() + "/errors/error.jsf");
}
}
}
public void destroy() {
servletConfig = null;
facesContextFactory = null;
lifecycle = null;
}
public ServletConfig getServletConfig() {
return servletConfig;
}
private String getLifecycleId() {
String lifecycleId = servletConfig.getServletContext().getInitParameter(LIFECYCLE_ID_ATTR);
return lifecycleId != null ? lifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE;
}
#Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
this.servletConfig = servletConfig;
facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
lifecycle = (Lifecycle) lifecycleFactory.getLifecycle(getLifecycleId());
}
}
Thanks!
You're calling FacesServlet#service() here:
try {
super.service(request, response);
} catch (Throwable e) {
// ...
}
Here's an extract from its javadoc to learn what kind of exception it may throw:
If a FacesException is thrown in either case, extract the cause from the FacesException. If the cause is null extract the message from the FacesException, put it inside of a new ServletException instance, and pass the FacesException instance as the root cause, then rethrow the ServletException instance. If the cause is an instance of ServletException, rethrow the cause. If the cause is an instance of IOException, rethrow the cause. Otherwise, create a new ServletException instance, passing the message from the cause, as the first argument, and the cause itself as the second argument.
In other words, it will always throw either ServletException or IOException. You need to use Throwable#getCause() to extract the desired cause from the catched ServletException and then determine it further. E.g.
if (e.getCause() instanceof NullPointerException) {
// ...
}

Categories