Jersey: what does "couldn't find grammar element" mean? - java

After upgrading Jersey from version 1.15 to 1.17 it started to log the following messages:
Apr 2, 2013 5:13:06 PM com.sun.jersey.server.wadl.generators.AbstractWadlGeneratorGrammarGenerator attachTypes
INFO: Couldn't find grammar element for class java.lang.String
An example of a service that produces such a message:
#GET
#Path("/bla/{a}")
#Produces("application/json")
public String doStuff(#PathParam("a") String a) {
return a;
}
My first impression would be to consider this an error message, purely based on the way the message is phrased ("couldn't find"). However, it's logged at a level of INFO, and it doesn't seem to have any effects in practice since all services continue to work.
So my question is whether these log messages indicate a (potential) problem with the way we are configuring or using Jersey. Since it didn't happen with the previous version I already checked the release notes, but didn't find anything related.

I had the same "info" message as well. I didn't manage to fix it (yet) for basic java types (Boolean, String...) but for my own custom classes if I add the #XmlRootElement annotation and a default no-param constructor the message dissapears.
Digging into jersey source code I noticed the class "WadlGeneratorJAXBGrammarGenerator" the following code :
Object parameterClassInstance = null;
try {
Constructor<?> defaultConstructor = type.getDeclaredConstructor();
defaultConstructor.setAccessible(true);
parameterClassInstance = defaultConstructor.newInstance();
} catch (InstantiationException ex) {
LOGGER.log(Level.FINE, null, ex);
} catch (IllegalAccessException ex) {
LOGGER.log(Level.FINE, null, ex);
} catch (IllegalArgumentException ex) {
LOGGER.log(Level.FINE, null, ex);
} catch (InvocationTargetException ex) {
LOGGER.log(Level.FINE, null, ex);
} catch (SecurityException ex) {
LOGGER.log(Level.FINE, null, ex);
} catch (NoSuchMethodException ex) {
//getting here for Boolean/String and some other primitive data type
LOGGER.log(Level.FINE, null, ex);
}
if (parameterClassInstance==null) {
return null;
}
So basically there is no default constructor for String, Boolean and few others then it throws a NoSuchMethodException therefore it return nulls and log the info message.
So still no idea why it happens but in my case the solution was to disable the wadl generation since I was not using it.
Just add the following param to your web.xml
<init-param>
<param-name>com.sun.jersey.config.feature.DisableWADL</param-name>
<param-value>true</param-value>
</init-param>

Related

Testing if custom exception was thrown when a run time exception is thrown using mockito

I have this code where I'm catching some exception and throwing a custom exception instead.
#Override
public void config() throws CustomException{
File jsonFile = new File("config.json");
try {
ConfigMapper config = mapper.readValue(jsonFile, ConfigMapper.class);
try {
this.instanceId = Integer.parseInt(config.getConfig().getClientId());
this.configParams = config.getConfig().getConfigParams();
} catch (NumberFormatException ex) {
throw new CustomException("Please provide a valid integer for instance ID", ex);
//LOGGER.log(Level.SEVERE, "error initializing instanceId. Should be an integer " + e);
}
} catch (IOException ex) {
throw new CustomException("Error trying to read/write", ex);
// LOGGER.log(Level.SEVERE, "IOException while processing the received init config params", e);
}
}
I need to write a unit test for this and below is how I wrote it.
#Test
public void should_throw_exception_when_invalid_integer_is_given_for_instanceID(){
boolean isExceptionThrown = false;
try{
Mockito.doThrow(new NumberFormatException()).when(objectMock).config();
barcodeScannerServiceMock.config();
} catch (CustomException ex) {
isExceptionThrown = true;
}
assertTrue(isExceptionThrown);
}
But its throwing a number format exception and not the CustomException as I want it to be. But this makes sense as I'm using the mock object to throw the exception as a result of which my code logic is not executed. But if that's the case, how do I test this scenario? Please advice.
1.) Remove the line Mockito.doThrow(new NumberFormatException()).when(objectMock).config();
2.) Change the Client-ID in your JSON-File to something that cannot be converted to an Integer.
this.instanceId = Integer.parseInt(config.getConfig().getClientId()); will fail due to that and thus throw an exception.
One advice regarding names: The name of your test method should be what's written in the Java-Doc. Just name it "testCustomException" & explain the methods function in the Java-Documentation. There are Naming-Conventions in Java (click here) which are basically general guidelines.
Practicing these is very helpful as it allows you to quickly get into your code again after not working on it for a month or so due to the increased readability.

Play framework - Set default language on server side

In my Play application I have an independent job which runs on server side in background. That job uses messages from messages.pl, but the problem is the server's default language is English so my messages cannot be reached. How can I change global default language for my application?
I have already tried Lang.apply("pl") in my Global class, but it doesn't work. I have also tested Controller.changeLang("pl") at user request, but since my job doesn't depends on any request it doesn't work as well.
Of course my application.conf file contains application.langs="pl".
EDIT
I forgot to mension, I'm using Play Framework 2.3.9.
Here is the code where I'm using messages (last line of each catch block). This function is called from the job (Akka scheduler):
public String processText(String text, String LPMN) {
lastError = "";
try {
String idt = nlpTextUpload(text);
return process(idt, LPMN);
} catch (NullPointerException ex) {
Logger.getLogger(SerelServiceRs.class.getName()).log(Level.WARNING, "Text to process is empty", ex);
play.Logger.warn("Text to process is empty", ex);
lastError = lastError.concat(Messages.get("error.process.emptyText")).concat("\n");
} catch (IOException ex) {
Logger.getLogger(SerelService.class.getName()).log(Level.SEVERE, "Problems in processing LPMN", ex);
play.Logger.error("Problems in processing LPMN", ex);
lastError = lastError.concat(Messages.get("error.process.lpmnProblem")).concat("\n");
} catch (InterruptedException ex) {
Logger.getLogger(SerelService.class.getName()).log(Level.SEVERE, null, ex);
play.Logger.error("Processing interrupt", ex);
lastError = lastError.concat(Messages.get("error.process.interrupt")).concat("\n");
}
return "";
}
And here is text from messages.pl:
error.process.emptyText=[BŁĄD]: Tekst do przetworzenia jest pusty
error.process.fileNotFound=[BŁĄD]: Plik nie został prawidłowo wczytany
error.process.lpmnProblem=[BŁĄD]: Błąd podczas wywoływania Web Serwisu
error.process.interrupt=[BŁĄD]: Przetwarzanie zostało przerwane

How to handle exception in my servlet correct

I have some problems making the exception do that i want!. I have created a servlet, which i want to handle all exceptions. My class building for this scenario that i need help too you see under here:
Servlet:
This exception handling is only for 1 method,
try {
completed = func.addNewOperator(userId, name, ini, cpr, password, role);
}catch (Exception e) {
Error = "There was a problem with database access";
response.sendRedirect("SystemError.jsp?Error_resultat=" + Error);
} catch (IOException e) {
Error = "Error found with connection";
response.sendRedirect("SystemError.jsp?Error_resultat=" + Error);
} catch (RuntimeException e) {
Error = "Error found with entered values";
response.sendRedirect("SystemError.jsp?Error_resultat=" + Error);
} catch (Exception e) {
Error = "Serious error found!";
response.sendRedirect("SystemError.jsp?Error_resultat=" + Error);
The func.addNewOperator is called in my function class:
Function:
A small example from my function method you see under here:
public boolean addNewOperator(String userId, String name, String ini, String cpr, String password, String role ) throws Exception {
int id = Integer.parseInt(userId);
}
So lets say if it can't parse it to and integer, it should throws the exception to my servlet, but this is not working. I want to throw the exception to the servlet, and then the servlet should send a response to open SystemError.jsp with an error message as parameter.
Can anyone see if i forgot something??
The order is whatever matches first, get's executed (as the JLS clearly explains).
If the first catch matches the exception, it executes, if it doesn't, the next one is tried and on and on until one is matched or none are.
So, when catching exceptions you want to always catch the most specific first and then the most generic (as RuntimeException or Exception).
Read more Order of catching exceptions in Java
catch (Exception e) should be last catch block in the chain.
It's worth reading Oracle Java Tutorial - Exceptions
Try in this way and don't forget to log the exception in log file.
try {
completed = func.addNewOperator(userId, name, ini, cpr, password, role);
}catch (SQLException e) {
Error = "There was a problem with database access";
} catch (IOException e) {
Error = "Error found with connection";
} catch (RuntimeException e) {
Error = "Error found with entered values";
} catch (Exception e) {
Error = "Serious error found!";
}
if(Error != null){
response.sendRedirect("SystemError.jsp?Error_resultat=" + Error);
}
NumberFormatException is a RuntimeException.
First, you should never redirect to a jsp page, but forward to it. Normally, jsp files are placed under WEB-INF and are never called directly but allways through server. Here is one example of forwarding (derived from from Java Tips - How to forward requests from Servlet to JSP :) :
request.setAttribute("error", error);
getServletConfig().getServletContext().getRequestDispatcher("/WEB-INF/SystemError.jsp")
.forward(request,response);
and your get error (first letter lowercased because it's a variable) in your jsp via ${error}
And anyway, you shouldn't deal with that at your servlet level but delegates this low level job to the container as explained in that other post from SO : How to Properly Handle Exceptions in a JSP/Servlet App?.

retrieve openID-url using openid4java

Consider the following code excerpt:
String openIDProviderURL = "https://www.google.com/accounts/o8/id";
try {
URI loc = getUI().getPage().getLocation();
List discoveries = manager.discover(openIDProviderURL);
DiscoveryInformation discovered = manager.associate(discoveries);
getUI().getSession().setAttribute("openid-disc", discovered);
AuthRequest authReq = manager.authenticate(discovered, "http://"+loc.getHost()+":"+loc.getPort()+loc.getPath());
FetchRequest fetch = FetchRequest.createFetchRequest();
authReq.addExtension(fetch);
System.out.println("DEST URL: "+authReq.getDestinationUrl(true));
getUI().getPage().setLocation(authReq.getDestinationUrl(true));
} catch (DiscoveryException ex) {
Logger.getLogger(NavigatorUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (MessageException ex) {
Logger.getLogger(NavigatorUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (ConsumerException ex) {
Logger.getLogger(NavigatorUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
Authentication with Google works, however, can anyone tell me how to extract the actual openID-identifier-URL from the objects I'm using here? When the authentication succeeds, it lets me now by writing "INFO: Verification succeeded for: https://www.google.com/accounts/o8/id?blablabla", but so far, I haven't found a way to access this very URL in the program. Could someone help me out please?
PS: I have been going through older posts dealing with openID4java. However, they all deal with failed authentication and the likes, which for me isn't the problem. If this very question has been asked before, I apologise.

Trasferring files and data with Jersey

I'm trying to develop some rest services with Jersey to upload and download files (something like a file manager). If my services produce/consume only File class as "application/octet-stream", like in the code below, they work.
#GET
#Produces("application/octet-stream")
public File getFile(String id) {
try {
File file = new File(System.getProperty("user.home"), id);
return file;
} catch (FileNotFoundException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
But if I try to transfer a custom object that contains a File field and some other data (FileEnvelope in the sample) I obtain an error.
#GET
#Produces("application/octet-stream")
public FileEnvelope getXml(String id) {
try {
File file = new File(System.getProperty("user.home"), id);
FileEnvelope fileEnvelope = new FileEnvelope(file, "text");
return fileEnvelope;
} catch (FileNotFoundException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
The error is
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class com.mycompany.restdemo.FileEnvelope, and Java type class com.mycompany.restdemo.FileEnvelope, and MIME media type application/octet-stream was not found
Where I'm wrong? Is this the right way to manage this case? My client could not be a "Jersey client".
Jersey has no idea how to serialize your domain object into an octet-stream unless you tell it how. In this case if you want to include extra information beyond the file data you should consider how the client should be expected to read it. You could:
Embed the information directly in the octet stream by creating your own MessageBodyWriter. The client would need to know where to look for this information in the resulting file.
Include the information as part of the HTTP response header using ResponseBuilder. The client would just need to know which response headers to check for the information.
You can send different types of data in one message using multipart/* media types. For example this article shows how: http://aruld.info/handling-multiparts-in-restful-applications-using-jersey/

Categories

Resources