How to setConstraintViolations on EditorDriver using return value of client side Validator Validate method call - gwt

Using GWT 2.5.0,
I would like to use Client side validation and Editors. I encounter the following error when trying to pass the ConstraintViolation java.util.Set to the EditorDriver as follows.
Validator a = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Person>> b = a.validate(person);
editorDriver.setConstraintViolations(b);
The method setConstraintViolations(Iterable<ConstraintViolation<?>>) in the type EditorDriver<Person> is not applicable for the arguments (Set<ConstraintViolation<Person>>)
The only somewhat relevant post I could find was Issue 6270!
Below is an Example which brings up a PopUpDialog with a Person Editor that allows you to specify a name and validate it against your annotations. Commenting out the personDriver.setConstraintViolations(violations); line in the PersonEditorDialog will allow you to run the example.
I don't have enough reputation points to post the image of the example.
Classes
Person
public class Person {
#NotNull(message = "You must have a name")
#Size(min = 3, message = "Your name must contain more than 3 characters")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PersonEditorDialog
public class PersonEditorDialog extends DialogBox implements Editor<Person> {
private static PersonEditorDialogUiBinder uiBinder = GWT
.create(PersonEditorDialogUiBinder.class);
interface PersonEditorDialogUiBinder extends
UiBinder<Widget, PersonEditorDialog> {
}
private Validator validator;
public PersonEditorDialog() {
validator = Validation.buildDefaultValidatorFactory().getValidator();
setWidget(uiBinder.createAndBindUi(this));
}
interface Driver extends SimpleBeanEditorDriver<Person, PersonEditorDialog> {
};
#UiField
ValueBoxEditorDecorator<String> nameEditor;
#UiField
Button validateBtn;
private Driver personDriver;
#UiHandler("validateBtn")
public void handleValidate(ClickEvent e) {
Person created = personDriver.flush();
Set<ConstraintViolation<Person>> violations = validator
.validate(created);
if (!violations.isEmpty() || personDriver.hasErrors()) {
StringBuilder violationMsg = new StringBuilder();
for (Iterator<ConstraintViolation<Person>> iterator = violations.iterator(); iterator.hasNext();) {
ConstraintViolation<Person> constraintViolation = (ConstraintViolation<Person>) iterator
.next();
violationMsg.append(constraintViolation.getMessage() + ",");
}
Window.alert("Detected violations:" + violationMsg);
personDriver.setConstraintViolations(violations);
}
}
#Override
public void center() {
personDriver = GWT.create(Driver.class);
personDriver.initialize(this);
personDriver.edit(new Person());
super.center();
}
}
SampleValidationFactory
public final class SampleValidationFactory extends AbstractGwtValidatorFactory {
/**
* Validator marker for the Validation Sample project. Only the classes and
* groups listed in the {#link GwtValidation} annotation can be validated.
*/
#GwtValidation(Person.class)
public interface GwtValidator extends Validator {
}
#Override
public AbstractGwtValidator createValidator() {
return GWT.create(GwtValidator.class);
}
}
EditorValidationTest
public class EditorValidationTest implements EntryPoint {
/**
* This is the entry point method.
*/
public void onModuleLoad() {
PersonEditorDialog personEditorDialog = new PersonEditorDialog();
personEditorDialog.center();
}
}
UiBinder
PersonEditorDialog.ui.xml
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:e="urn:import:com.google.gwt.editor.ui.client">
<ui:style>
.important {
font-weight: bold;
}
</ui:style>
<g:HTMLPanel>
<g:Label>Enter your Name:</g:Label>
<e:ValueBoxEditorDecorator ui:field="nameEditor">
<e:valuebox>
<g:TextBox />
</e:valuebox>
</e:ValueBoxEditorDecorator>
<g:Button ui:field="validateBtn">Validate</g:Button>
</g:HTMLPanel>
</ui:UiBinder>
GWT Module
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='editorvalidationtest'>
<inherits name='com.google.gwt.user.User' />
<inherits name='com.google.gwt.user.theme.clean.Clean' />
<inherits name="com.google.gwt.editor.Editor"/>
<!-- Validation module inherits -->
<inherits name="org.hibernate.validator.HibernateValidator" />
<replace-with
class="com.test.client.SampleValidationFactory">
<when-type-is class="javax.validation.ValidatorFactory" />
</replace-with>
<!-- Specify the app entry point class. -->
<entry-point class='com.test.client.EditorValidationTest' />
<!-- Specify the paths for translatable code -->
<source path='client' />
<source path='shared' />
</module>
Libs required on Classpath
hibernate-validator-4.1.0.Final.jar
hibernate-validator-4.1.0.Final-sources.jar
validation-api-1.0.0.GA.jar (in GWT SDK)
validation-api-1.0.0.GA-sources.jar (in GWT SDK)
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
log4j-1.2.16.jar

As discussed in the comments, the following cast was determined to be a valid workaround.
Set<?> test = violations;
editorDriver.setConstraintViolations((Set<ConstraintViolation<?>>) test);

This is what I do over and over again :
List<ConstraintViolation<?>> adaptedViolations = new ArrayList<ConstraintViolation<?>>();
for (ConstraintViolation<Person> violation : violations) {
adaptedViolations.add(violation);
}
editorDriver.setConstraintViolations(adaptedViolations);
The driver has a wild card generic type defined and you can not pass in the typed constraint violations.

Related

GWTP not displaying UI

I'm trying to use GWTP in my GWT 2.7 application but the UI in my uibinder is not displaying. My app compiles and runs in Super dev mode without any errors, but I get a blank screen. I expected the HTML in the LayoutView.ui.xml to show in the browser. I'm sure I'm missing something really basic. Any help would be great.
The following is included in my .gwt.xml file
<inherits name='com.google.gwt.inject.Inject' />
<!-- Other module inherits -->
<inherits name="com.google.gwt.uibinder.UiBinder" />
<inherits name='com.gwtplatform.mvp.Mvp' />
<entry-point class="com.clearwood.client.App" />
<define-configuration-property name="gin.ginjector" is-multi-valued="false" />
<set-configuration-property name="gin.ginjector"
value="com.clearwood.client.gin.MyGinjector" />
client/App.java
public class App implements EntryPoint {
public final MyGinjector ginjector = GWT.create(MyGinjector.class);
#Override
public void onModuleLoad() {
DelayedBindRegistry.bind(ginjector);
ginjector.getPlaceManager().revealCurrentPlace();
}
}
client/gin/ClientModule.java
public class ClientModule extends AbstractPresenterModule {
#Override
protected void configure() {
install(new DefaultModule());
install(new LayoutModule());
bindConstant().annotatedWith(DefaultPlace.class).to(NameTokens.LAYOUT);
bindConstant().annotatedWith(ErrorPlace.class).to(NameTokens.LAYOUT);
bindConstant().annotatedWith(UnauthorizedPlace.class).to(NameTokens.LAYOUT);
requestStaticInjection(NameTokens.class);
}
}
client/gin/Ginjector.java
#GinModules({ ClientModule.class })
public interface MyGinjector extends Ginjector {
EventBus getEventBus();
PlaceManager getPlaceManager();
Provider<LayoutPresenter> getLayoutPresenter();
}
client/place/NameTokens.java
public class NameTokens {
public static final String LAYOUT = "LAYOUT";
public static String getLAYOUT() {
return LAYOUT;
}
}
client/layout/LayoutView.ui.xml
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<g:SimplePanel width="600px" height="auto" ui:field="main">
<g:HTML width="100%" height="100%">TEST</g:HTML>
</g:SimplePanel>
</ui:UiBinder>
client/layout/LayoutView.java
class LayoutView extends ViewImpl implements LayoutPresenter.MyView {
interface Binder extends UiBinder<Widget, LayoutView> {
}
#UiField
SimplePanel main;
#Inject
LayoutView(Binder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
}
#Override
public void setInSlot(Object slot, IsWidget content) {
if (slot == LayoutPresenter.SLOT_Layout) {
main.setWidget(content);
} else {
super.setInSlot(slot, content);
}
}
}
client/layout/LayoutPresenter.java
public class LayoutPresenter extends Presenter<LayoutPresenter.MyView, LayoutPresenter.MyProxy> {
interface MyView extends View {
}
#ContentSlot
public static final Type<RevealContentHandler<?>> SLOT_Layout = new Type<RevealContentHandler<?>>();
#ProxyStandard
interface MyProxy extends Proxy<LayoutPresenter> {
}
#Inject
LayoutPresenter(
EventBus eventBus,
MyView view,
MyProxy proxy) {
super(eventBus, view, proxy, RevealType.Root);
}
}
client/layout/LayoutModule.java
public class LayoutModule extends AbstractPresenterModule {
#Override
protected void configure() {
bindPresenter(LayoutPresenter.class, LayoutPresenter.MyView.class, LayoutView.class, LayoutPresenter.MyProxy.class);
}
}
I generated the Layout presenter using the GWTP plugin.
I tried to follow the sample tutorials at
http://dev.arcbees.com/gwtp/sampletutorial/
and
https://code.google.com/p/gwt-platform/wiki/GettingStarted#Getting_the_sample_applications
but some of it seems to be deprecated
You don't have a presenter with a ProxyPlace and the annotation #NameToken on it. To get your code working quickly, you can change LayoutPresenter.MyProxy to:
#ProxyStandard
#NameToken(NameTokens.LAYOUT)
interface MyProxy extends ProxyPlace<LayoutPresenter> {}
Also the Google Code documentation is actually outdated by a lot. There are warnings all over the place, so I thought this was obvious.
The documentation on https://dev.arcbees.com/gwtp/sampletutorial/ is recent enough to help you develop a working application. You can also have a look at GWTP's Basic Sample for more examples: https://github.com/ArcBees/GWTP-Samples/tree/master/gwtp-samples/gwtp-sample-basic

custom submenu won't react on click

I am trying to implement an extension in JDeveloper. It creats a submenu when you click on a DB package.
THe issue comes when I click on an element of my custom submenu, it returns a null pointer Exception.
I can't figure out where I did wrong.
Would you please help me?
Here is how a I created the submenu:
submenu.xml File:
<?xml version="1.0" encoding="windows-1252" ?>
<!-- usage of a name space?-->
<items id="my.contextMenu">
<folder type="PACKAGE">
<name>User Defined Context Menu</name>
<item reloadparent="true"
action-ref="utilitytools.customSave">
<title>saveThisPackage</title>
</folder>
</items>
extension.xml file:
<?xml version="1.0" encoding="UTF-8" ?>
<extension id="utilitytools" version="1.0" esdk-version="1.0"
rsbundle-class="utilitytools.Res"
xmlns="http://jcp.org/jsr/198/extension-manifest">
<name>Utility Tools</name>
<owner>A name</owner>
<dependencies>
<import>oracle.sqldeveloper</import>
<import>oracle.ide</import>
</dependencies>
<hooks>
<jdeveloper-hook xmlns="http://xmlns.oracle.com/jdeveloper/1013/extension">
<addins>
<addin>utilitytools.UtilityToolsAddin</addin>
</addins>
<actions xmlns="http://xmlns.oracle.com/jdeveloper/1013/extension">
<action id="utilitytools.customSave">
<properties>
<property name="Name">saveThisPackage</property>
<property name="SmallIcon"></property>
<property name="LongDescription"></property>
</properties>
<controller-class>utilitytools.savePackageController</controller-class>
<command-class>utilitytools.savePackageCommand</command-class>
</action>
</actions>
</jdeveloper-hook>
<sqldev-navigator-hook xmlns="http://xmlns.oracle.com/sqldeveloper/sqldev-navigator">
<descriptor>submenu.xml</descriptor>
</sqldev-navigator-hook>
</hooks>
</extension>
SubmenuListener file:
public final class SubMenuListener implements ContextMenuListener {
public SubMenuListener() {
super();
}
public void menuWillShow(ContextMenu contextMenu) {
contextMenu.add( contextMenu.createMenuItem(
IdeAction.find( savePackageCommand.actionId() )
));
}
public void menuWillHide(ContextMenu contextMenu) {
//Nothing
}
public boolean handleDefaultAction(Context context) {
return false;
}
}
And the command file:
/**
* Command handler for utilitytools.customSave.
*/
#RegisteredByExtension("utilitytools")
public final class sauvegardePackageCommand extends Command {
public savePackageCommand() {
super(actionId());
}
public int doit() {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
showSaveWindow();
}
});
return OK;
}
/**
* Returns the id of the action this command is associated with.
*
* #return the id of the action this command is associated with.
* #throws IllegalStateException if the action this command is associated
* with is not registered.
*/
public static int actionId() {
final Integer cmdId = Ide.findCmdID(".utilitytools.customSave");
if (cmdId == null)
throw new IllegalStateException("Action esdksample.showElementClass not found.");
return cmdId;
}
private static void showSaveWindow(){
JFrame frame = new JFrame("SAVE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JPanelSavePackage());//Or any window you want to popup
frame.pack();
frame.setVisible(true);
}
}

JSF view displaying outdated value

I have two entities and a backing bean in my application. Following, a simplified version of it:
Controller and Models:
class BackingBean {
private List<A> collectionOfA;
private A currentA;
private B currentB;
private String newDescription;
// accessors
public void prepareForUpdate(ActionEvent e) {
currentA = (A) e.getComponent().getAttributes().get("a");
currentB = (B) e.getComponent().getAttributes().get("b");
}
public void save(ActionEvent e) {
// method to save b
b.setName("changing the name");
b.setSomeNumber(2);
b.setDescription(newDescription);
entityManager.merge(b);
}
}
#Entity
class A {
private String name;
#OneToMany
private List<B> bs;
}
#Entity
class B {
private String name;
private String description;
private int someNumber;
}
View:
<div>
<!-- some popup with inputs for updating B -->
<h:inputText value="#{backingBean.currentB}" />
<h:commandLink actionListener="#{backingBean.save}" />
</div>
<ui:repeat value="#{backingBean.collectionOfA}" var="a">
<h:outputText>#{a.name}</h:outputText>
<ui:repeat value="#{a.bs}" var="b">
#{b.name}
#{b.description}
#{b.someNumber}
<h:commandLink actionListener="#{backingBean.prepareForUpdate}">
<f:attribute name="a" value="#{a}" />
<f:attribute name="b" value="#{b}" />
</h:commandLink>
</ui:repeat>
</ui:repeat>
Assuming that, when I click the commandLink for prepareForUpdate(), the popup shows, my problem is this: when I save the currentB entity, every field of the entity is updated in the view. However, an instant after, the field b.description is rendered again with the old value. When I check the database, the description is, in fact, updated, as it is if I refresh the page.
Any thoughts on why this is happening?

GWT Editor Framework : custom LeafValueEditor implementing HasEditorErrors

I have implemented my own form field as IsEditor<LeafValueEditor<String>> that I'd like to use in the forms of my application.
public class FormField extends Composite implements IsEditor<LeafValueEditor<String>> {
interface FormFieldUiBinder extends UiBinder<Widget, FormField> {
}
private static FormFieldUiBinder uiBinder = GWT.create(FormFieldUiBinder.class);
interface FormFieldStyle extends CssResource {
String error();
}
#UiField
TextBox wrapped;
private String placeholder;
public FormField() {
initWidget(uiBinder.createAndBindUi(this));
wrapped.setTitle("");
}
#UiHandler("wrapped")
public void onFocus(FocusEvent event) {
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
wrapped.selectAll();
}
});
}
public String getText() {
return wrapped.getText();
}
public void setText(String text) {
wrapped.setText(text);
}
/**
* Gets the current placeholder text for the text box.
*
* #return the current placeholder text
*/
public String getPlaceholder() {
return placeholder;
}
/**
* Sets the placeholder text displayed in the text box.
*
* #param placeholder
* the placeholder text
*/
public void setPlaceholder(String text) {
placeholder = (text != null ? text : "");
wrapped.getElement().setPropertyString("placeholder", placeholder);
}
public String getTitle() {
return wrapped.getTitle();
}
public void setTitle(String title) {
wrapped.setTitle(title);
}
#Override
public LeafValueEditor<String> asEditor() {
return wrapped.asEditor();
}
public int getVisibleLength() {
return wrapped.getVisibleLength();
}
public void setVisibleLength(int length) {
wrapped.setVisibleLength(length);
}
public boolean isReadOnly() {
return wrapped.isReadOnly();
}
public void setReadOnly(boolean readOnly) {
wrapped.setReadOnly(readOnly);
}
public boolean isEnabled() {
return wrapped.isEnabled();
}
public void setEnabled(boolean enabled) {
wrapped.setEnabled(enabled);
}
public void setWidth(String width) {
wrapped.setWidth(width);
}
}
The corresponding UIBinder file is plain simple :
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<g:HTMLPanel>
<g:TextBox ui:field="wrapped" />
</g:HTMLPanel>
</ui:UiBinder>
This works smoothly in the forms I create like this :
<g:AbsolutePanel width="350px" height="225px"
styleName="{res.css.inputArea}">
<g:at left='10' top='0'>
<g:HTMLPanel width="350px">
<h1>Personalia</h1>
</g:HTMLPanel>
</g:at>
<g:at left='10' top='65'>
<f:FormLabel text="voornaam" />
</g:at>
<g:at left='10' top='80'>
<f:FormField ui:field="firstName" placeholder="voornaam" />
</g:at>
<g:at left='10' top='115'>
<f:FormLabel text="achternaam" />
</g:at>
<g:at left='10' top='130'>
<f:FormField ui:field="lastName" placeholder="achternaam"/>
</g:at>
</g:AbsolutePanel>
In my views, I can then use the EditorDriver like this :
interface EditorDriver extends SimpleBeanEditorDriver<Account, AccountPersonaliaEditor> {
}
private final EditorDriver editorDriver = GWT.create(EditorDriver.class);
And populating the form works fine too
editorDriver.initialize(editor);
editorDriver.edit(presenter.getAccount());
As well as getting the values after editing :
Account account = editorDriver.flush();
Now I would like to implement feedback on the errors. I have the GWT Bean validation framework working fine too. I just need to show the errors.
So, what I am trying next, is to have the FormField implement HasEditorErrors. Here is my problem/question.
public class FormField extends Composite implements IsEditor<LeafValueEditor<String>>, HasEditorErrors<String>
As soon as I implement this interface (even with a empty implementation), I run into the following compile time error :
[DEBUG] [klawtapp] - Rebinding com.example.screen.ui.center.AccountPersonaliaImpl.EditorDriver
[DEBUG] [klawtapp] - Invoking generator com.google.gwt.editor.rebind.SimpleBeanEditorDriverGenerator
[DEBUG] [klawtapp] - Creating Editor model for com.example.screen.ui.center.AccountPersonaliaImpl.EditorDriver
[DEBUG] [klawtapp] - Descending into firstName
[ERROR] [klawtapp] - Could not find a getter for path wrapped in proxy type java.lang.String
[DEBUG] [klawtapp] - Descending into lastName
[ERROR] [klawtapp] - Could not find a getter for path wrapped in proxy type java.lang.String
[ERROR] [klawtapp] - Unable to create Editor model due to previous errors
[ERROR] [klawtapp] - Deferred binding failed for 'com.example.screen.ui.center.AccountPersonaliaImpl.EditorDriver'; expect subsequent failures
This seemed so trivial. I have tried adding getter/setter for wrapped but that does not really help.
EDIT: for a moment, I thought the solution would be to implement HasEditorErrors<LeafValueEditor<String>> instead of HasEditorErrors<String> to prevent descending the hierarchy to the wrapped TextBox, but the results are similar :
[ERROR] [klawtapp] - Could not find a getter for path wrapped in proxy type com.google.gwt.editor.client.LeafValueEditor
Simply annotate your wrapped text box with #Editor.Ignore.
Alternatively, you could remove the implements IsEditor<LeafValueEditor<String>> and instead annotate the wrapped field with #Path("") (you'll have to test with null values though if you might face them, as I'm not sure it'll work well as-is).
Or you could choose to implement your own LeafValueEditor<String> instead of relying on the one from the TextBox.

Gin problem using GWT and Guice. - java.lang.RuntimeException: Deferred binding failed for

I have a problem using Gin. Here is a simple example.
#GinModules(AppModule.class)
public interface AppInjector extends Ginjector
{
MainForm getMainPanel();
TemplateForm getHeaderForm();
}
then here is Module
import com.google.inject.Singleton;
public class AppModule extends AbstractGinModule
{
#Override
protected void configure()
{
bind(MainForm.class).in(Singleton.class);
}
}
and the Entry point
public class MySampleApplication implements EntryPoint
private final AppInjector injector = GWT.create(AppInjector.class);
public void onModuleLoad()
{
MainForm mf = injector.getMainPanel();
RootPanel.get().add(mf);
}
}
And the module xml file
<module rename-to="MySampleApplication">
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Specify the app entry point class. -->
<entry-point class='com.mySampleApplication.client.MySampleApplication'/>
<inherits name="com.google.gwt.inject.Inject"/>
<!-- Specify the app servlets. -->
<servlet path='/MySampleApplicationService' class='com.mySampleApplication.server.MySampleApplicationServiceImpl'/>
</module>
After i run this code i got an exception :
ERROR: Failed to create an instance of 'com.mySampleApplication.client.MySampleApplication' via deferred binding . java.lang.RuntimeException: Deferred binding failed for 'com.mySampleApplication.client.gin.AppInjector' (did you forget to inherit a required module?).
I tried with gin 1.0 and guice 2.0.
Please, advice.
Thanks.
#GinModules(AppClientModule.class)
should probably be
#GinModules(AppModule.class)
Update:
The error is in line declaring AppInjector. It should be:
interface AppInjector extends Ginjector {