Error in onSubmit, feedback not rendering - wicket-1.5

I have some logic in onSubmit of the button (which is in Form), which may fail, so I would like to show a message using error(myMessage). But it doesn't work, and it seems that it is normal:
Feedback panel added but does not show all messages
Is there any possibility to render feedback panels with errors reported in onSubmit?
There is no ajax used on the page. I am using wicket 1.5.6
EDIT:
MyPage.java
public class MyPage extends WebPage {
private static final Logger logger = Logger.getLogger(MyPage.class);
private static final long serialVersionUID = -8874964120018036584L;
public MyPage(PageParameters parameters) {
super(parameters);
logger.debug("Creating new login page");
add(new MyLoginForm("loginForm"));
}
}
MyLoginForm.java
public class MyLoginForm extends StatelessForm<Void> {
private static final Logger logger = Logger.getLogger(MyLoginForm.class);
private static final long serialVersionUID = -8694389090804630170L;
private MyUser user = new MyUser();
public MyLoginForm(String id) {
super(id);
setOutputMarkupId(true);
logger.debug("Creating new stateless login form");
add(new RequiredTextField<String>("login", new PropertyModel<String>(user, "login")));
add(new PasswordTextField("password", new PropertyModel<String>(user, "password")));
add(new Button("submit"));
add(new FeedbackPanel("feedback"));
}
#Override
public void onSubmit() {
info("test info");
}
}
MyPage.html
<body>
<form wicket:id="loginForm">
<fieldset>
<legend><wicket:message key="form.login.legend"/></legend>
<input type="text" wicket:id="login" />
<input type="password" wicket:id="password" />
<input type="submit" wicket:id="submit" />
<span wicket:id="feedback"></span>
</fieldset>
</form>
</body>
catalina.out
16 May 2012 15:24:20:860 WARN [http-8080-2] [WebSession:135] Component-targetted feedback message was left unrendered. This could be because you are missing a FeedbackPanel on the page. Message: [FeedbackMessage message = "test info", reporter = loginForm, level = INFO]
The same happens when I try to overwrite the onSubmit method in Button instead of the one in MyLoginForm...

You need to add a FeedbackPanel to your Page. Feedback messages 'bubble' up in the component hierarchie. The easiest way is to have one feedbackpanel on your page.
But, you can also display errors close to the FormComponent that reports the error. See this pdf for inspiration or for a possible implementation.
Edit: I just build a very simple test, using the wicket quickstart. Changed the HomePage as below and it worked (I saw all error / info messages)
html:
<form wicket:id="form">
<div wicket:id="feedback"></div>
<input wicket:id="submit" type="button" value="submit">
</form>
Java:
Form<Void> form = new Form<Void>("form") {
#Override
protected void onSubmit() {
super.onSubmit();
error("test error from form");
error("test info from form");
}
};
add(form);
form.add(new FeedbackPanel("feedback"));
form.add(new SubmitLink("submit") {
#Override
public void onSubmit() {
super.onSubmit();
error("an error occurred in button submit");
info("test info from the button");
}
});
Edit 2: It turns out, that a StatelessForm is used (I overlooked that detail). Switching back to (normal) Form, the messages should be displayed correctly.

I have checked twice, Wicket 1.5.6 FeedbackPanel (and SignInForm where I have problem) works worse than 1.5.4
I have no idea, what is backgroud of this behaviour.
EDIT: version 1.5.5 work good.
EDIT2: https://issues.apache.org/jira/browse/WICKET-4536

I found another way for anyone else who stumbles into this issue..
I have a base class that I inherit from and then I have the feedback messages print out as part of the base class.. I too ran into this issue, and just had a method inside my base class return an instance of itself (return this), and then I just access the info method through this method... so, getMethod().info("some message").. and it worked for me. My feedbackPanel is also set in the base class..
So I'd imagine you can do the same thing.. Just get access to an instance of the page you want to stamp the feedback message to.

Related

How to redirect springboot error page to vaadin error UI?

I have an error page in vaadin UI. But sometimes we can write a wrong url and we see the springboot error page.
I want to show vaadin UI error page in this case. By the way, I have already have a rendered 404 page for springboot. But I don't want to show it.
This is my vaadin error UI. But this works into the application. (http://localhost:7001/MyApplication/#!error)
sometimes I write an invalid url like this: http://localhost:7001/MyApplication/blablablabla
in this case I want to redirect vaadin error page (http://localhost:7001/MyApplication/#!error) But the springboot redirects me to rendered 404 page.
It is possible?
#UIScope
#SpringView(name = ErrorView.VIEW_NAME)
public class ErrorView extends VerticalLayout implements View {
public static final String VIEW_NAME = "error";
private Label explanation;
public ErrorView() {
Label header = new Label("The view could not be found");
header.addStyleName(MaterialTheme.LABEL_H1);
addComponent(header);
addComponent(explanation = new Label());
}
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
explanation.setValue(String.format("You tried to navigate to a view ('%s') that does not exist.", event.getViewName()));
getUI().getNavigator().navigateTo(ErrorView.VIEW_NAME);
}
}
you can put 404/500 page under resources/error/ folder, Spring boot will redirect those page automatic when have error
I think SpringNavigator can solve your problem. While defining your Navigator, you can also define error View. See the example below
#SpringUI(path = "ui")
public class DemoUI extends com.vaadin.ui.UI {
#Override
protected void init(VaadinRequest vaadinRequest) {
SpringNavigator navigator = new SpringNavigator();
navigator.setErrorView(new ErrorView());
setNavigator(navigator);
}
}

wicket form event onsubmit not working at V6.X

I have a page like this.
HTML
<form wicket:id="form" onsubmit="alert('form submit')">
<input type="text" name="name">
<!-- Wicket1.5.X form.onsubmit working -->
<!-- Wicket6.X form.onsubmit can not work -->
<input wicket:id="ajaxFallbackButton" type="submit">
<!-- form.onsubmit works fine -->
<input wicket:id="submitBtn" type="submit">
</form>
Java
Form<Void> form = new Form<Void>("form");
form.setOutputMarkupId(true);
add(form);
AjaxFallbackButton ajaxFallbackButton = new AjaxFallbackButton("ajaxFallbackButton", new Model<String>("AjaxFallbackButton"), form) {
private static final long serialVersionUID = 1L;
#Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
System.out.println("ajaxFallbackButton onSubmit");
}
};
form.add(ajaxFallbackButton);
Button button = new Button("submitBtn", new Model<String>("Button"));
form.add(button);
Why the event of form onsubmit defined int the html can not work when I used Wicket V6.X?
Thanks for svenmeier, I fixed it by override the AjaxFallbackButton.updateAjaxAttributes method.
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
AjaxCallListener ajaxCallListener = new AjaxCallListener();
ajaxCallListener.onPrecondition("alert('form submit')");
attributes.getAjaxCallListeners().add(ajaxCallListener);
}
Wicket 6 uses JavaScript event handlers, so your inline JavaScript is not executed.
Read here for further explanation and solutions:
Wicket AjaxButton and javascript condition

Validating dimensions of an uploaded image in file upload listener in PrimeFaces

I'm uploading images using <p:fileUpload> as follows.
<p:outputLabel for="txtCatImage" value="#{messages['category.image']}"/>
<p:fileUpload id="txtCatImage" mode="advanced"
dragDropSupport="true" required="true"
sizeLimit="1000000" fileLimit="1" multiple="false"
cancelLabel="#{messages['fileupolad.cancelLabel']}"
label="#{messages['fileupolad.label']}"
uploadLabel="#{messages['fileupolad.uploadLabel']}"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
invalidFileMessage="#{messages['fileupolad.invalidFileMessage']}"
invalidSizeMessage="#{messages['fileupolad.invalidSizeMessage']}"
fileLimitMessage="#{messages['fileupolad.fileLimitMessage']}"
fileUploadListener="#{categoryManagedBean.fileUploadListener}"/>
<p:message for="txtCatImage" showSummary="false"/>
<p:commandButton id="btnSubmit" update="panel messages"
actionListener="#{categoryManagedBean.insert}"
value="#{messages['button.save']}"/>
fileUploadListener in the corresponding managed bean decorated with #ViewScoped is as follows.
//This is just a utility method and can be placed anywhere in the application.
private static boolean validateImageDimensions(byte[] bytes) throws IOException {
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(bytes));
return bufferedImage.getHeight()>=750 || bufferedImage.getWidth()>=650;
}
public void fileUploadListener(FileUploadEvent event) throws IOException {
UploadedFile uploadedFile = event.getFile();
byte[] bytes = IOUtils.toByteArray(uploadedFile.getInputstream());
if(!Utility.validateImageDimensions(bytes)) {
FacesContext context = FacesContext.getCurrentInstance();
context.validationFailed();
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_FATAL, "Message summary", "Error message");
FacesContext.getCurrentInstance().addMessage(event.getComponent().getClientId(context), message);
}
else {//Do something.}
}
The listener of <p:commandButton> is as follows which should not be invoked, if validation in fileUploadListener() fails.
public void insert() {
//Code to invoke an EJB to insert a new row along with the uploaded file.
}
If if(!Utility.validateImageDimensions(bytes)) is evaluated to true then, the action listener of <p:commandButton> (the insert() method above) should not be invoked but it is invoked and this kind of validation implies no effect at all.
As already stated, PrimeFaces file upload validators don't work.
What am I doing wrong here? What is the way to validate dimensions of an uploaded image?
Your concrete problem is caused because the upload action took place in a different HTTP request than the save action. You first choosed the file and then pressed Upload (request #1) and then the Save button (request #2), right? The network monitor in browser's builtin developer toolset (press F12) should also confirm it. The FacesContext#validationFailed() is in essence request scoped, like the FacesContext itself. So, when you set it during the request which invokes the upload action, then it's just "reset" during the request which invokes the save action.
This is indeed somewhat awkward. As the <p:fileUpload mode="advanced"> doesn't support Validators, as you already found out, there's not really a clean solution to this problem. You should be fiddling with a view scoped bean property to maintain the validation state across the requests on the same view.
private boolean validationFailed;
public void fileUploadListener(FileUploadEvent event) throws IOException {
// ...
validationFailed = !Utility.validateImageDimensions(bytes);
if (validationFailed) {
// Add message.
}
else {
// Process upload.
}
}
public void insert() {
if (validationFailed) {
// Add message.
}
else {
// Process insert.
}
}
By the way, I'd rather not set those messages as FATAL, but as ERROR. The enduser is namely capable of fixing it all by itself.

dotlesscss does not show errors

There's something wrong with my css because no styles are being added to my website after compilation.
How do I get dotlesscss to show errors? Regular .less shows you a nice message that's very handy.
You can do this very easily with web.config. In your dotless configuration section, add the following: logger="dotless.Core.Loggers.AspResponseLogger". This will make dotless output the errors instead of blank css.
I've included the following as an example. ("..." represents existing stuff in your web.config). In my example below cache is set to false. This is useful for debugging purposes. It should probably be set to true under normal circumstances.
<configuration>
<configSections>
...
<section name="dotless" type="dotless.Core.configuration.DotlessConfigurationSectionHandler,dotless.Core" />
</configSections>
<dotless minifyCss="false" cache="false"
logger="dotless.Core.Loggers.AspResponseLogger" />
...
</configuration>
I just faced this today in my RequestReduce project. I was getting blank less -> css transforms because there were parse errors that appeared to be going into the ether. Thanks to
this related answer How can I output errors when using .less programmatically? I was able to work out a solution where I could write the errors to the response stream. You have to create a Logger derriving from dotless.Core.Loggers.ILogger:
public class LessLogger : ILogger
{
public void Log(LogLevel level, string message)
{
}
public void Info(string message)
{
}
public void Debug(string message)
{
}
public void Warn(string message)
{
}
public void Error(string message)
{
Response.Write(message);
}
public HttpResponseBase Response { get; set; }
}
You pass this into the Configuration sent to the EngineFactory:
var engine = new EngineFactory(new DotlessConfiguration
{
CacheEnabled = false,
Logger = typeof (LessLogger)
}
).GetEngine();
For unit testing purposes I wanted to pass in my HttpResponseBase that would write the error. This is where I felt things getting ugly with some nasty casting to get a reference to my logger:
((LessLogger)((LessEngine)((ParameterDecorator)engine).Underlying).Logger).Response = response;
I hope this helps you out.

JSF - Example login-ajax - Why it send the form?

Im trying JSF framework. Im a beginner. So i start with a easy tutorial. This is the code :
<h:form id="form1" prependId="false">
<h:outputScript name="jsf.js" library="javax.faces" target="head" />
<h:inputText value="#{user.name}" id="name"/>
<h:inputSecret value="#{user.password}" id="password"/>
<h:outputText value="#{user.greeting}" id="out"/>
<br/>
<h:commandButton value="Login" type="button" onclick="jsf.ajax.request(this, event, {execute: 'name password', render: 'out'}); return false;" />
</h:form>
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name = "user")
#RequestScoped
public class UserBean {
private String name = "";
private String password;
public String getName() { return name; }
public void setName(String newValue) { name = newValue; }
public String getPassword() { return password; }
public void setPassword(String newValue) { password = newValue; }
public String getGreeting() {
if(name.length()==0) {
return "Inserisci nickname";
} else {
return "Benvenuto "+name;
}
}
}
In "less words" (when i click on button) :
1 - thanks to execute: 'name password, I call the setName and setPassword (JavaBean methods) with an asynch call;
2 - than, thanks to render: 'out' I call getGreeting
So, execute will be translate as SET and render as GET.
What I would like to know is if I have well understand the process.
Because I have a misunderstanding : if I scan the traffik from client to server, I see that (trought the ajax call) it sends from client to server the form1, name and password (and, as MAGIC, name and password have got the value inserted by me).
So how is this possible?
Thanks to all!
That isn't magic. That's normal. Those values are entered in webbrowser. JS/Ajax has access to those values. JS/Ajax will send those values along. How else should server side/JSF know about the newly entered values?

Resources