playframework random CRUD error - java

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);
}
}

Related

Play 2.5: Form validation - on error, value of form is "Optional.empty"

I am developing an application with Play 2.5. Models and Form data are separate classes, so I have a class "Page" and "PageForm".
In PageForm is a method "validate()" which returns null if there was no error or a List if the validation failed:
public List<ValidationError> validate() {
List<ValidationError> errors = new ArrayList<>();
Page checkForDuplicatePage = PageRepository.getInstance().getByName(name);
if(checkForDuplicatePage != null && checkForDuplicatePage.id != id) {
errors.add(new ValidationError("name", "The name is already in use by another page"));
}
// ...
return errors.isEmpty() ? null : errors;
}
In my controller I call:
Form<PageForm> form = formFactory(PageForm.class).bindFromRequest();
This works really well if the data in the form is correct. However, if validate() finds an error (and it really doesn't matter what kind, even a return new ArrayList<>() triggers this), the "value" attribute of my form is Optional.empty. The "data" attribute actually has all the data passed to the form.
This means I can't use the form to pass it to my view, which should display the data with error messages. Instead I get a [CompletionException: java.util.NoSuchElementException: No value present]. Sometimes (I haven't figured out why that happens yet) it also says [CompletionException: java.util.NoSuchElementException: None.get].
I compared my code with other projects and the official docs, but they all seem to be doing what I have here.
I use Scala Play rather than Java, so YMMV. But to me, I don't think that validate should return null at all. It should return the empty ArrayList if there are no errors. I suspect that this will eliminate the None.get error message. I'm not sure how much I can help, though, because I don't really understand very well what your code is intended to do. For example, the sentence
However, if validate() finds an error (and it really doesn't matter what kind, even a return new ArrayList<>() triggers this)
seems kind of ambiguous to me. Where is the return new ArrayList<>() call that triggers the error?

How to get the status code out of a Result in Play Framework

I'm working on a Java project in the Play framework, version 2.2.1
I'm trying to implement a batch operation on my models, with a message being returned showing the status code of the query on each model instance. So that's one controller method calling another and getting the Result from it.
The thing is, I need to get that status code from that return, since it has to be in the message.
There doesn't seem to be a way to get this status code.
I tried this: check that a result is an ok playframework
But it won't compile, Java says the cast cannot be done.
So, how do I get that number out of the Result?
Once again, this is a Java project and all my Results are play.mvc.Result, not play.mvc.api.Result.
EDIT:
Let's say you have a route that does a DELETE:
DELETE /url/delete/:id/ myapp.mycontroller.delete(id: Long)
The controller method would look like:
public static Result delete(Long id) {
Mymodel m = MyModel.get(id);
if (m.hasDependencies) {
throw new CustomException(statusCode, message);
}
m.delete();
return ok();
}
So either it passes an ok() or an exception with a custom statuscode.
The batch functionality I am talking about would be another method in the same controller. This would receive a batch of IDs via a form element. The goal would then be to call the required function on all these ids.
The whole point is using the existing controller methods, as they contain other checks and fail-safes that need to be taken in to account for certain models.
So I have another method that receives this list of Ids and then calls the proper function in a loop, in a try/catch block.
The idea is that I want to find out what the statuscode of the Result is. That's it. Nothing more. I want the statuscode of the result.
play.mvc.Result is just a wrapper for play.mvc.api.Result so after all you will need to work with it.
public static Result batch() {
try {
Result result = delete(1L);
play.api.mvc.SimpleResult res = Await.result(result.getWrappedResult(), Duration.Inf());
int status = res.header().status();
//handle status
} catch (Exception e) {
//handle exception
}
}
Await and Duration are Scala classes
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;

CConvertException in Play! Framework

I'm fixing up a HTML template for rendering a PDF file. The problem is that the new code I'm using works for one template but throws a CConvertException in another. The console doesn't give me any hints other than the following error:
Oops: CConvertException
An unexpected error occured caused by exception CConvertException:
ERROR: An unhandled exception occured: ERROR: An Exception occured while reconstructing the pdf document: ERROR: An unhandled exception occured: null
The new code involves using a new Java Extension that converts a String into another, as follows:
#{if person?.name != null} ${person?.name.getInitials().toString()} #{/if}
For some reason, this exact code breaks one template but works just fine in another. What am I doing wrong?
Don't know for sure if this is the cause, but your use of the safe navigation operator ?. is kind of weird here. And wouldn't getInitials() automatically return a String?
Why not just write (without the surrounding if statement):
// Returns the name or an empty String if name or person is null.
${person?.name?.getInitials() ?: ""}

Uploading an empty file automatically results in an NPE

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.

struts validation problem in IE

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.

Categories