gwt, many listboxes on the form - gwt

I have a form with six listboxes. Data for every listbox loads through rpc.
I want load all data with one request to the server. I think to return Map< String, List < Seriliazible > > with data for all listboxes.
Other ideas ?

Astor's solution is really the best way to do it. I'd enhance it a little so you can have the data for each listbox separated (as I can see you want from your example):
public class ListDataForForms implements Serializable {
private List<String>[] dataList1;
private List<String>[] dataList2;
private List<String>[] dataList3;
getters and setters...
}
Doing it this way allows you to change your mind and send more or less information in the same request anytime you want

Related

Apache Isis: How to implement your custom submit form or page properly?

I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan

Ignore play framework form errors at different views

i'd like to know whether I could ignore play standard validation when I want to. For instance, let's imagine I have a Entity called Car just like
#Entity
public class Car{
#Id
private Long id;
#Required
private String model;
#Required
private String hiddenField; //important but doesn't appear in some cases (some usecases)
}
In order to make it clearer, then
Case 1
#(carForm : Form[Car])
#import helper._
#form(routes.controller.foo.bar) {
#inputText(carForm("model"))
<input type="submit">
}
Case 2
#(carForm : Form[Car])
#import helper._
#form(routes.controller.foo.bar) {
#inputText(carForm("model"))
#inputText(carForm("hiddenField"))
<input type="submit">
}
Then I have a Play.data.Form object, and it has errors cause i haven't filled model or the hiddenField that was given as exmple. But, actually, i have some situations that this hidden doesn't even appear (case 1), i mean, there's no input called that, as the user is not allowed to edit it that time. So, if I have two usecases, where at the first, all inputs are there and they are supposed to be filled, but the other one has no 'hiddenField' input, but, altought, it's still required by my model, and, of course, a form submitted without it has error as well, what should I do?. How was I supposed to deal with it? I have one model, but validation may be different in one case to another, and i wanna it to be server side, not jquery nor pure javascript.
I tried to discardErrors through
(Imagine it was submitted from case 1)
MyForm<Car> myCarForm = Form.form(Car.class).bindFromRequest();
//it has errors, sure it does, hiddenField was required and that field didn't even exist at screen.
myCarForm.discardErrors(); //ok, error hashmap is empty right now
myCarForm.get(); // anyway, no value here.
//myCarForm.data(); //for sure i could retrieve field by field and remount object that way, but that looks hacky and hardworking
Then, any solution? Thank u all
I got it reading Play for Java book.
6.4.2 Partial Validation
A common use case is having multiple validation constraints for the same object
model. Because we’re defining our constraint on the object model, it’s normal to have
multiple forms that refer to the same object model. But these forms might have different
validation constraints. To illustrate this use case, we can imagine a simple wizard in
which the user inputs a new product in two steps:
1 The user enters the product name and submits the form.
2 The user enters the product EAN number and the description.
We could validate the product’s name during step 2, but displaying an error message
for the product name at that point would be weird. Fortunately, Play allows you to perform
partial validation. For each annotated value, we need to indicate at which step it
applies. We can do that with the help of the groups attribute from our annotations.
Let’s change our Product model class to do that:
public Product extends Model {
public interface Step1{}
public interface Step2{}
#Required(groups = Step1.class)
public String name;
#Required(groups = Step2.class)
public String ean;
}
Then, at Controller
// We re//strict the validation to the Step1 "group"
Form<Product> productForm =
form(Product.class, Product.Step1.class).bindFromRequest();
Thanks!
Yes you can achieve the solution to this problem. what's happening in this case is every time you map your request to model car it will always look for JPA validations for every property then it looks for validate() method present inside that model, if that method returns null then it doesn't pass any error and perform the normal execution, but if it returns any thing then it maps it to form errors.
You can return error mapping to specific field or you can just return a string that will be considered as a global error.
In your case solution is :
#Entity
public class Car{
#Id
private Long id;
private String model;
private String hiddenField; //important but doesn't appear in some cases (some usecases)
public List<ValidationError> validate() {
List<ValidationError> errors = new ArrayList<ValidationError>();
.
.
.
#Some logic to validate fields#
#if field invalid#
errors.add(new ValidationError("model", "errorMessage"));
.
.
.
return errors.isEmpty() ? null : errors;
}
Note: Just remove the JPA validation and use your logic in validate function to check according to the situation.
Ignores validations, like this:
myCarForm.discardErrors().get();
and does the validation otherwise, Jquery for example.

Dynamic mask data for web project

Currently our web projects need to anonymize some data.
(for example a security number like 432-55-1111 might appear as 432-55-**)
These datas may contain email, id, price, date ,and so on.
The tables' name and columns that needed to be masked was saved in DB.
We are using spring security to judge a user whether he can see the data or not.
The data domain object(CMP) may be get from SQL or JPQL(named query or native query)or JPA Load method or Mainframe.
We need to find a best efficient way (not the DB end) to mask these data dynamically.
If we use a interceptor at the EJB method end , we need to annotation all the Object(DTO)
and all the columns. That's may be low efficiency.
Any body know how can we invoke a method(like a interceptor) when finish SQL executed and named query(native query) exectued, and we can call a method to mask the result by the query and user id.
Or other ways.
It would be good to have this in the lowest level, so that other applications like reporting would not need a separate solution.
Our project's architecture is JSF+Spring+EJB 3.0+JPA 1.0.We have many web projects.For JPA some projects using EclipseLink 2.2 ,some using Hibernate.
UPDATE:
More information about our projects. We have many web project about different feature.So we have many ejb projects associated with them. Every ejb has DAO to get their CMP by call JPQL or get(class, primarykey) metod.Like below:
Query query = em.createNamedQuery(XXXCMP.FIND_XXX_BY_NAME);
query.setHint(QueryHints.READ_ONLY, HintValues.TRUE);
query.setParameter("shortName", "XXX").getSingleResult();
Or
XXXCMP screen = entityManager.find(XXXCMP.class, id);
The new EJB services code converter to transfrom the data from CMP to DTO.
The converter as below:
/**
* Convert to CMP.
*
*/
CMP convertToCMP(DTO dto, EntityManager em);
/**
* Convert CMP to domain object with all fields populated, the default scenario is
* <code>EConvertScenario.Detail</code>.
*
*/
DTO convertFromCMP(CMP cmp, EntityManager em);
But some old services use their own methods to convert CMP.Also some domain services used for search lazy paing, they also don't use the converter.
We want to mask the data before the CMP convert to DTO.
You can try EntityListener to intercept entity loading into the persistence context with #PostLoad annotation.
Else, can try within accesor methods(getter/setter) which I think is suitable for masking/formatting etc.
Edit : (based on comments & question update)
You can share entity/DTO across appications
public String getSomethingMasked(){
return mask(originalString);
}
The data retrieval pattern isn't uniform across applications. If all the applications are using same database, it must be generalized. There is no point of writing same thing again with different tools. Each application might apply business logic afterwards.
Probably, you can have a separate project meant for interacting with database & then including it in other applications for further use. So it will be a common point to change anything, debug, enhance etc.
You are using Eclipselink, Hibernate & other custom ways for fetching data & you require minimal workaround, which from my perspective seems difficult.
Either centralize the data retrieval or make changes all over separately if possible, which I think is not feasible, compromising consistency.
In this case, you may intercept the JSF's conversion fase. This solution applies to JSF views, not to reportings.
#FacesConverter("AnonymizeDataConverter")
public class AnonymizeDataConverter implements Converter{
#Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
return getAnonymisedData(value);
}
#Override
public String getAsString(FacesContext context, UIComponent component,
Object value) {
return getAnonymisedData(value);
}
public static String getAnonymisedData(Object data) {
if (data == null)
return "";
String value = data.toString().trim();
if (!value.isEmpty())
return value.substring(0, value.lenght() - 4) + "**";
return "";
}
}

Wicket - FileUploadField, Ajax and Preview

Im using Wicket 1.5 and I need to build a component with a FileUploadField to load an image.
I need an Ajax behaviour to make a preview of image after selected it (without submiting the entire form).
Searching on Google, I found this Event that match when I select the file:
AjaxEventBehavior choose = new AjaxEventBehavior("onChange"){
private static final long serialVersionUID = 1L;
#Override
protected void onEvent(AjaxRequestTarget target) {
Request request = RequestCycle.get().getRequest();
}
};
What I need is the stream of image to put in a little panel that required:
byte[] imgBytes
And obviously I need the same stream to fill a PropertyModel for DB storing.
Thanks
You need to use either AjaxFormSubmitBehavior (will submit the entire form on the given event) or AjaxFormComponentUpdatingBehavior (will submit only the one form component. I'm not sure whether the latter works with file uploads, just give it a try. You can always use the former.
In the model of your FileUploadField you will find a (list of) FileUpload - look at the methods you get, there are input streams and other things available so you can do pretty much anything with the data.

GWT Editor Framework: Drop Down List

I'm looking for someone to point me in the right direction (link) or provide a code example for implementing a drop down list for a many-to-one relationship using RequestFactory and the Editor framework in GWT. One of the models for my project has a many to one relationship:
#Entity
public class Book {
#ManyToOne
private Author author;
}
When I build the view to add/edit a book, I want to show a drop down list that can be used to choose which author wrote the book. How can this be done with the Editor framework?
For the drop-down list, you need a ValueListBox<AuthorProxy>, and it happens to be an editor of AuthorProxy, so all is well. But you then need to populate the list (setAcceptableValues), so you'll likely have to make a request to your server to load the list of authors.
Beware the setAcceptableValues automatically adds the current value (returned by getValue, and defaults to null) to the list (and setValue automatically adds the value to the list of acceptable values too if needed), so make sure you pass null as an acceptable value, or you call setValue with a value from the list before calling setAcceptableValues.
I know it's an old question but here's my two cents anyway.
I had some trouble with a similar scenario. The problem is that the acceptable values (AuthorProxy instances) were retrieved in a RequestContext different than the one the BookEditor used to edit a BookProxy.
The result is that the current AuthorProxy was always repeated in the ValueListBoxwhen I tried to edit a BookProxy object. After some research I found this post in the GWT Google group, where Thomas explained that
"EntityProxy#equals() actually compares their request-context and stableId()."
So, as I could not change my editing workflow, I chose to change the way the ValueListBox handled its values by setting a custom ProvidesKey that used a different object field in its comparison process.
My final solution is similar to this:
#UiFactory
#Ignore
ValueListBox<AuthorProxy> createValueListBox ()
{
return new ValueListBox<AuthorProxy>(new Renderer<AuthorProxy>()
{
...
}, new ProvidesKey<AuthorProxy>()
{
#Override
public Object getKey (AuthorProxy author)
{
return (author != null && author.getId() != null) ? author.getId() : Long.MIN_VALUE;
}
});
}
This solution seems ok to me. I hope it helps someone else.