I'm a bit of a newbie to the Play Framework, but I don't see any documentation on how to approach this. Basically I've got a form to upload a text file to the server, here's the relevant snippet:
#{form #Sprockets.upload() , enctype:'multipart/form-data' }
<input type="file" name="sprocketFile" size="chars" />
<input type="submit" value="Submit Sprocket" />
#{/form}
On the controller side, here's the upload method:
public static void upload(File sprocketFile) {
}
My issue is that if the user doesn't bother populating the form and just hits "Submit Sprocket", Play automagically generates an NPE as it tries to convert the form data to a file. How I can work around this? This happens even before the controller validation code kicks in, so simply throwing in a #Required doesn't help:
#64m30kf1p
Internal Server Error (500) for request POST /sprockets/upload
Oops: NullPointerException
An unexpected error occured caused by exception NullPointerException: null
play.exceptions.UnexpectedException: Errors serializationProblem
at play.data.validation.ValidationPlugin.save(ValidationPlugin.java:146)
at play.data.validation.ValidationPlugin.onActionInvocationResult(ValidationPlugin.java:65)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:293)
at Invocation.HTTP Request(Play!)
Caused by: java.lang.NullPointerException
at play.data.validation.ValidationPlugin.save(ValidationPlugin.java:136)
... 3 more
My end goal is to show a pretty error message back to the user, but Play is preventing me from doing this. This is with Play 1.1 on OS X if it makes a difference.
Possible workaround would be an #Before-Interceptor. There you can check the paramter and redirect to an error page. This should work. Please create a ticket at http://play.lighthouseapp.com with a small example application.
You form and controller do not match
<input type="file" name="sprocketFile" size="chars" />
Says you are uploading a File object to a variable named sprocketFile
But, your code says you are storing in an object named licenceFile
public static void upload(File licenseFile) {
Try making the two match.
I've found the source of the problem, and it's my own fault. The issue at hand is naturally part of the source I didn't include in the original question. Here's the sample code:
public static void upload(#Required File sprocketFile) {
try {
if (sprocketFile == null || validation.hasErrors()) {
validation.addError("Upload Error", "Please select a sprocket to upload", sprocketFile);
params.flash();
validation.keep();
index();
}
The issue was using the sprocketFile as the last parameter in validation.addError(). I discovered this while running the app in debug mode in NetBeans. Thanks for your help #niels.
Related
I am overriding the addArticle and updateArticle methods of JournalArticleServiceImpl using a Hook. I am checking for all articles with a particular ddmStructureKey and that the current article has a unique value in a particular field.
I am throwing DuplicateEntryException exception when I find non-uniqueness. Within the curresponding catch method, I gave return null;. But it threw a NullPointerException. Then I tried to throw SystemException like follows.
try {
// logic
} catch (DuplicateEntryException e) {
LOG.error("Value already present", e);
throw new SystemException("Value already present", e);
}
But the result for the end users was as shown below. Even though in the logs, it displayed the actual error, it is not possible for users to understand what exactly happened in the background from this message.
I do not know how to display a custom error message to the end users from a Hook. Also to return to the same page to edit the same article.
Display error messages in Liferay:
You may use session messages, like <liferay-ui:error> tag.
For example in the jsp page:
<%# taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
...
<liferay-ui:error key="err1" message="Third message" translateMessage="false"/>
or with exception, like in edit_article.jsp:
<liferay-ui:error exception="<%= ArticleContentSizeException.class %>" message="you-have-exceeded-the-maximum-web-content-size-allowed" />
You can define your own exception class and your own message-key and the value for the key in Language.properties.
And in the render method:
SessionErrors.add(renderRequest, "err1");
or when catching an exception (e) use this:
SessionErrors.add(renderRequest, e.getClass());
A complete example on github - portlet, github - hook
As the UI layer seems to not expect any exception from these methods, this might call for changes in the UI- or Action-layer as well. When you do that, you might even get well along without service changes (because you can check upfront).
A hacky idea might be to not return null, but the duplicated value - simulating a successful update but returning the already existing article. Note that this is hacky, I'm not sure if it works always. If it breaks, please let me know how it breaks.
when i execute the below controller action I get the error attached at end of this question.
when getting this error and if i refresh the page in browser the controller view page displays with no error.
i'm not sure what causes this error at first request of beleow controller action?
/**
* controller to register new user.
* Shows registration screen.
*/
public static void registration() throws Exception {
ObjectType type = ObjectType.forClass("models.User");
Constructor<?> constructor = type.entityClass.getDeclaredConstructor();
constructor.setAccessible(true);
Model object = (Model) constructor.newInstance();
/*System.out.print("type=");
System.out.println(type);
System.out.print("object=");
System.out.println(object);*/
render(type, object);
}
----Exception error trace--------------
23:12:14,229 ERROR ~
#69bf92hlc
Internal Server Error (500) for request GET /registration
Template execution error (In {module:crud}/app/views/tags/crud/types.tag around line 3)
Execution error occured in template {module:crud}/app/views/tags/crud/types.tag. Exception raised was NullPointerException : null.
play.exceptions.TemplateExecutionException
at play.templates.BaseTemplate.throwException(BaseTemplate.java:86)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:257)
at play.templates.GroovyTemplate$ExecutableTemplate.invokeTag(GroovyTemplate.java:379)
at {module:crud}/conf/routes.(line:4)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:232)
at play.templates.Template.render(Template.java:26)
at play.templates.GroovyTemplate.render(GroovyTemplate.java:187)
at play.mvc.Router.parse(Router.java:162)
at play.mvc.Router.parse(Router.java:190)
at play.mvc.Router.parse(Router.java:164)
at play.mvc.Router.load(Router.java:48)
at play.mvc.Router.detectChanges(Router.java:219)
at Invocation.HTTP Request(Play!)
Caused by: java.lang.NullPointerException
at play.classloading.ApplicationCompiler$2.acceptResult(ApplicationCompiler.java:266)
at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:478)
at play.classloading.ApplicationCompiler.compile(ApplicationCompiler.java:282)
at play.classloading.ApplicationClassloader.getAllClasses(ApplicationClassloader.java:424)
at play.classloading.ApplicationClassloader.getAssignableClasses(ApplicationClassloader.java:453)
at play.classloading.ApplicationClassloader$getAssignableClasses.call(Unknown Source)
at {module:crud}/app/views/tags/crud/types.tag.(line:3)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:232)
... 11 more
I think the reason for you error is that when you first try display the form there's no object created yet, so the Exception raised was NullPointerException : null.
Unluckily I'm not familiar with Play 2.* and do not plan on starting before it's more stable, but I think I understood that CRUD generation is not included nor fully supported there, so you are probably using code from play1 crud?
I think the solution in your case is to better cover the New(blank) / View / Save pattern; seeing your Routes might also help to understand this precise issue.
In any case, considering you are not generating an unknown model type, rather always a User one, what is the real advantage of going through this complicated pattern?
You should do something like
blank
User user = null
render()
view/edit
User user = User.findById(id);
save
public static void save(#Valid User object) {
if(validation.hasErrors()) {
params.flash(); // add http parameters to the flash scope
User user = object;
render("User/show.html", user);
}
}
I am new to wicket and trying to get some things working.
One thing that annoys me a lot is that I get a blank (0 chars of text) page whenever there is a syntax error on a page.
Striped down example:
Test.html
header stuff: doctype ... html ... head ... body ...
<span wicket:id="msgTest" id="message">MSG</span>
footer stuff: /body ... /html
Test.java
public class Test extends WebPage {
public Test() {
add(new Label("msgTest", "Hello, World!"));
}
}
This will output the page as expected.
Now, lets introduce an error:
header stuff: doctype ... html ... head ... body ...
<span wicket:id="msgTest2" id="message">MSG</span>
footer stuff: /body ... /html
I changed the label-id to something different then what the source-file expects.
If I run this code I get the already mentioned blank page.
However, for every request to a page with such a syntax error I get an error report in the log-file of around 1000+ lines. This error-report is basically just wicket-generated html of a page which describes the error.
This makes me wonder why wicket isn't displaying the error-stuff instead of the blank page. I'm not very experienced with wicket but to me it somehow looks like wicket is having trouble rendering its own error-page code.
It would be nice to know how one goes about finding syntax-errors with wicket.
Reading through a 1000+ line error-report for a small error like a misplaced character seems a bit tedious.
Thanks in advance for guiding me into the right direction :)
PS:
wicket-version: 1.4.9
stage: development
I can not confirm that behavior. I went to http://wicket.apache.org/quickstart.html and created a quickstart. Changed the wicket id from 'message' to 'message1' and got a nice descriptive page in jetty:
WicketMessage: Unable to find component with id 'message' in [Page class = com.mycompany.HomePage, id = 0, version = 0]. This means that you declared wicket:id=message in your markup, but that you either did not add the component to your page at all, or that the hierarchy does not match.
How did you create your project?
What I like to do is write unit tests with WicketTester to at least verify that things render, and usually also write assertions to check the components. Something along the lines of
#Test
public void testMessageLabel(
WicketTester tester = new WicketTester();
tester.startPage(Test.class);
tester.assertLastRenderedPage(Test.class);
tester.assertComponent("msgTest", Label.class);
tester.assertLabel("msgTest", "Hello, World!");
)
Then if as in your example the code contains "msgTest" and the html contains "msgTest2" you at least get a test failure instead of seeing it as part of a failing app after deploy.
It's certainly not a complete solution, since this error will make any rendering test for the page fail and the particular failure will just give a long error message in the test result, but at least you don't have to search log files.
I have a JSP that takes an Arraylist from the session object and removes the items from it. It seemed to be working fine and then out of nowhere when I navigate to that page, the page is blank. I checked the Tomcat log files and in catalina.out I am receiving a JasperException an it is showing it as being on a line with the following
for(int i; i < agentItems.size(); i++)
agentItems is the name of the ArrayList I am using. I have been debugging it and can't seem to figure out what the problem might be. I have read that a JasperException is sometiems thrown as a JSP's NullPointerException. Is this true or am I just completely overlooking the problem?
I have the web application running on a local machine and a intermediate server for development in which both of them have had no trouble. Why could it be that only on this server it is giving me problems?
That can be everything. You need to look a bit further in the stacktrace, peek to the caused by or root cause part and the trace which comes thereafter. It can be caused by many things. The JSP basically get compiled into one large try block and any catched Throwable will be wrapped into a servletcontainer specific exception like JasperException in Tomcat and clones. It boils down to this:
try {
// All translated JSP code comes here. Max 64K.
} catch (Throwable t) {
throw new JasperException(t);
}
Check the .java filename in the 1st line of the stacktrace, locate this in the work directory of the servletcontainer and open the file in an editor. Do you see it?
That said, using scriptlets is a bad practice. Use Servlets to control/preprocess/postprocess requests, use Javabeans to represent data models, use Taglibs in JSP to control the page flow and output, use Expression Language (EL) in JSP to access backend data. In your specific case, you can loop over an array or List using JSTL's c:forEach tag.
<c:forEach items="${agents}" var="agent">
<p>Agent: ${agent.name}
</c:forEach>
jasperexception can also occur when JSP is not able to access an element or item it's obtaining from outside and here it maybe is unable to access agentItems. Try to provide fully qualified class name or import the package otherwise.
I am using Struts 2.1.8 and facing validation problem in IE. I am getting the following error
An exception occurred: Error. Error message: Invalid argument.
I tried out to figure out the cause and found the following. My generated javascript code is:
field = form.elements['district.name'];
var error = "Enter only alphabets for district";
if (continueValidation && field.value != null && !field.value.match("^[a-zA-Z ]*$")) {
addError(field, error);
errors = true;
}
I tried to mock up by putting the same code in a function and calling it in onclick event. The method addError() throws the exception and the reason is field variable. If I change it to field[0], it works fine. How to fix this error?
Check the generated HTML source. Open the page in webbrowser, rightclick and choose View Source. Is the input field's name really district.name? Isn't it prefixed/suffixed with some other autogenerated key (possibly the ID/name of the <form>) like as many other MVC frameworks do? If so, you'll need to change the JavaScript code accordingly that it uses the right element name as it appears in the HTML DOM tree. You know, JavaScript runs at the client machine and only sees the generated HTML DOM tree, not the "original" server-side code which is responsible for generating the HTML.