I have a TableView and a form with some TextBox and ComboBox in my javafx application. I am trying to populate the form components with selected rows data from TableView. I can populate all the TextBox without any error or exception. But while setting values to ComboBoxes, it's throwing an ClassCastException, java.lang.ClassCastException: java.lang.String cannot be cast to entity.StockUOM.
This is my StringCoverter
unitCombo.setConverter(new StringConverter<StockUOM>() {
#Override
public String toString(StockUOM object) {
return object.getStockUOM();
}
#Override
public StockUOM fromString(String string) {
return null;
}
});
This is my entity.StockUOM class
#Entity
#Access(AccessType.PROPERTY)
#NamedQueries({
#NamedQuery(name = StockUOM.findStockUOM, query = "SELECT s from StockUOM s")
})
public class StockUOM implements Externalizable{
public final static String PREFIX = "entity.StockUOM.";
public final static String findStockUOM = PREFIX + "findStockUOM";
private IntegerProperty id;
private int _id;
private StringProperty stockUOM;
private String _stockUOM;
public StockUOM() {
if (id == null) {
id = new SimpleIntegerProperty(this, "id", _id);
}
if( stockUOM== null){
stockUOM= new SimpleStringProperty(this,"stockUOM",_stockUOM);
}
}
public StockUOM(String stockUOM) {
this();
this.stockUOM.set(stockUOM);
}
public IntegerProperty idProperty() {
if (id == null) {
id = new SimpleIntegerProperty(this, "id", _id);;
}
return id;
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public final int getId() {
if (id == null) {
return _id;
} else {
return id.get();
}
}
public final void setId(int id) {
if (this.id == null) {
_id = id;
} else {
this.id.set(id);
}
}
public StringProperty stockUOMProperty() {
if( stockUOM== null){
stockUOM= new SimpleStringProperty(this,"stockUOM",_stockUOM);
}
return stockUOM;
}
public final String getStockUOM() {
if(stockUOM == null){
return _stockUOM;
}else{
return stockUOM.get();
}
}
public void setStockUOM(String stockUOM) {
if (this.stockUOM == null) {
_stockUOM=stockUOM ;
} else {
this.stockUOM.set(stockUOM);
}
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getId());
out.writeChars(getStockUOM());
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
setId(in.readInt());
setStockUOM((String)in.readObject());
}
#Override
public String toString() {
return getStockUOM();
}
}
This is how i am setting values to ComboBox
unitCombo.setValue(newValue.getUnit());
Here newValue is the instance of StockUOM of ChangeListner which is listening on TableView row selection.
So what's wrong i am doing ? And what's the solution.
Thanks.
The problem is that most probably you defined your ComboBox like:
ComboBox unitCombo = new ComboBox();
So you missed to define the generic argument and you ended up with the raw type (your IDE most probably gives you a warning on this line).
At this point it is not specified what kind of objects do you want to display in the ComboBox.
When you do the following:
unitCombo.setValue(newValue.getUnit());
you set the valueProperty as a String value.
And then comes your converter:
unitCombo.setConverter(new StringConverter<StockUOM>() {
#Override
public String toString(StockUOM object) {
return object.getStockUOM();
}
#Override
public StockUOM fromString(String string) {
return null;
}
});
which expects StockUOM object being displayed, which does not happen hence the error.
You have to decide what kind of object do you want to display: if it is StockUOM, then declare the ComboBox as ComboBox<StockUOM> unitCombo = new ComboBox<StockUOM>();. After this you will have a compile time error on the line where you set the value for a String value, to fix that error you have to modify that line as unitCombo.setValue(newValue);. If you want to display String objects, the methodology is the same.
Related
I've created CRUD methods but i have some problems with that.
This is my add method code:
public Product addProduct(Product content) {
Product item = new Product();
item.setName(content.getName());
item.setCalories(content.getCalories());
item.setFat(content.getFat());
item.setCarbo(content.getCarbo());
item.setProtein(content.getProtein());
item.setProductKinds(content.getProductKinds());
item.setAuthor(content.getAuthor());
item.setMedia(content.getMedia());
item.setApproved(content.getApproved());
databaseController.saveTest(item);
logger.log("Item created");
return item;
}
This is my editProduct method:
public Product editProduct(Product product) {
Product databaseProduct = databaseController.get(Product.class, product.getId());
databaseProduct.setAllProducts(product);
databaseController.save(databaseProduct);
return databaseProduct;
}
In model class I think that I have made everything right :
package pl.javamill.model.kitchen;
import com.amazonaws.services.dynamodbv2.datamodeling.*;
import pl.javamill.model.Request;
import pl.javamill.model.common.Author;
import pl.javamill.model.common.AuthorConverter;
import pl.javamill.model.common.Media;
import pl.javamill.model.common.MediaConverter;
import java.util.List;
#DynamoDBTable(tableName = "product")
public class Product extends Request {
/**
* Id of kitchen content
*/
private String id;
/**
* Name of product
*/
private String name;
/**
* Calories in 100g
*/
private Integer calories;
/**
* Fat in 100g
*/
private Double fat;
/**
* Total carbo in 100g
*/
private Double carbo;
/**
* Total Protein in 100g
*/
private Double protein;
/**
* Labels of product for example gluten fee product
*/
private List<ProductKind> productKinds;
/**
* Author of content.
*/
private Author author;
/**
* Address of content image.
*/
private Media media;
private Boolean approved;
#DynamoDBHashKey(attributeName = "id")
#DynamoDBAutoGeneratedKey
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#DynamoDBAttribute(attributeName = "Name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#DynamoDBAttribute(attributeName = "Calories")
public Integer getCalories() {
return calories;
}
public void setCalories(Integer calories) {
this.calories = calories;
}
#DynamoDBAttribute(attributeName = "Fat")
public Double getFat() {
return fat;
}
public void setFat(Double fat) {
this.fat = fat;
}
#DynamoDBAttribute(attributeName = "Carbo")
public Double getCarbo() {
return carbo;
}
public void setCarbo(Double carbo) {
this.carbo = carbo;
}
#DynamoDBAttribute(attributeName = "Protein")
public Double getProtein() {
return protein;
}
public void setProtein(Double protein) {
this.protein = protein;
}
#DynamoDBTypeConvertedEnum
#DynamoDBTypeConverted(converter = ProductKindConverter.class)
#DynamoDBAttribute(attributeName = "ProductKinds")
public List<ProductKind> getProductKinds() {
return productKinds;
}
public void setProductKinds(List<ProductKind> productKinds) {
this.productKinds = productKinds;
}
#DynamoDBTypeConverted(converter = AuthorConverter.class)
#DynamoDBAttribute(attributeName = "Author")
public Author getAuthor() {
return author;
}
public void setAuthor(Author author) {
this.author = author;
}
#DynamoDBTypeConverted(converter = MediaConverter.class)
#DynamoDBAttribute(attributeName = "Media")
public Media getMedia() {
return media;
}
public void setMedia(Media media) {
this.media = media;
}
#DynamoDBAttribute(attributeName = "Approved")
public Boolean getApproved() {
return approved;
}
public void setApproved(Boolean approved) {
this.approved = approved;
}
public void setAllProducts(Product product) {
if (!getName().equals(product.getName())) {
setName(product.getName());
}
if (!getCalories().equals(product.getCalories())) {
setCalories(product.getCalories());
}
if (!getFat().equals(product.getFat())) {
setFat(product.getFat());
}
if (!getCarbo().equals(product.getCarbo())) {
setCarbo(product.getCarbo());
}
if (!getProtein().equals(product.getProtein())) {
setProtein(product.getProtein());
}
if (!getProductKinds().equals(product.getProductKinds())) {
setProductKinds(product.getProductKinds());
}
if (!getAuthor().equals(product.getAuthor())) {
setAuthor(product.getAuthor());
}
if (!getMedia().equals(product.getMedia())) {
setMedia(product.getMedia());
}
if (!getApproved().equals(product.getApproved())) {
setApproved(product.getApproved());
}
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
if (name != null ? !name.equals(product.name) : product.name != null) return false;
if (calories != null ? !calories.equals(product.calories) : product.calories != null) return false;
if (fat != null ? !fat.equals(product.fat) : product.fat != null) return false;
if (carbo != null ? !carbo.equals(product.carbo) : product.carbo != null) return false;
if (protein != null ? !protein.equals(product.protein) : product.protein != null) return false;
if (productKinds != null ? !productKinds.equals(product.productKinds) : product.productKinds != null)
return false;
if (author != null ? !author.equals(product.author) : product.author != null) return false;
if (media != null ? !media.equals(product.media) : product.media != null) return false;
return approved != null ? approved.equals(product.approved) : product.approved == null;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (calories != null ? calories.hashCode() : 0);
result = 31 * result + (fat != null ? fat.hashCode() : 0);
result = 31 * result + (carbo != null ? carbo.hashCode() : 0);
result = 31 * result + (protein != null ? protein.hashCode() : 0);
result = 31 * result + (productKinds != null ? productKinds.hashCode() : 0);
result = 31 * result + (author != null ? author.hashCode() : 0);
result = 31 * result + (media != null ? media.hashCode() : 0);
result = 31 * result + (approved != null ? approved.hashCode() : 0);
return result;
}
}
ProductKindConventor:
public class ProductKindConverter implements DynamoDBTypeConverter<String, List<ProductKind>> {
#Override
public String convert(List<ProductKind> objects) {
//Jackson object mapper
ObjectMapper objectMapper = new ObjectMapper();
try {
String objectsString = objectMapper.writeValueAsString(objects);
return objectsString;
} catch (JsonProcessingException e) {
//do something
}
return null;
}
#Override
public List<ProductKind> unconvert(String objectsString) {
ObjectMapper objectMapper = new ObjectMapper();
try {
List<ProductKind> objects = objectMapper.readValue(objectsString, new TypeReference<List<ProductKind>>(){});
return objects;
} catch (JsonParseException e) {
//do something
} catch (JsonMappingException e) {
//do something
} catch (IOException e) {
//do something
}
return null;
}
}
Save method in dbcontroller:
public void saveTest(Product product){
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(regions).build();
mapper = new DynamoDBMapper(client);
mapper.save(product);
}
Get product from DB method:
public Product getTest(String id) {
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(regions).build();
mapper = new DynamoDBMapper(client);
Product retrivedProduct = mapper.load(Product.class, id);
return retrivedProduct;
}
Unit test passed, everything seems to be ok, but when I was using POSTMAN to test, i got some errors. I send product as json and it seems like that:
{"id":null,"name":"yoloornotyolo","calories":1000,"fat":400.0,"carbo":20.0,"protein":40.0,"productKinds":["MEAT"],"author":{"name":"Plejer Annołn","id":"testID2"},"media":{"name":"heheszki","url":"http://blabla.pl","mediaType":"IMAGE"},"approved":false}
Then I got ""message": "Internal server error"", so I check log file and that what I can see:
not supported; requires #DynamoDBTyped or #DynamoDBTypeConverted:
com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException
I dont know what is wrong. Can someone explain me what I suppose to do?
It would be useful to see your saveProduct method. You are using DynamoDBMapper annotations but it looks like you are trying to save an item object, not a Product object. Rather than
Item item = new Item()
Use
Product item = new Product();
item.setName...
One thing I would mention is that you can offload the handling of your generated id to DyanmoDBMapper using the DynamoDBAutoGeneratedKey annotation
In your model class do this:
#DynamoDBHashKey(attributeName = "Id")
#DynamoDBAutoGeneratedKey
public String getId() { return id; }
public void setId(String id) { this.id = id; }
And then you dont need to handle id in your addProduct method
EDIT: Your saveProduct method should be along the lines of
DynamoDBMapper mapper = new DynamoDBMapper(dynamoDBClient);
mapper.save(item)
I doubt you need to be passing a tablename as that is an annotation on your Product object. You shouldn't be using putItem.
EDIT:
Your saveProduct method should take a Product object, not an item object. Dont use putItem because this doesn't know about your model class. Use DynamoDBMapper save function. You dont need to specify the table name as that's an annotation on your Product class (the table is called 'product'). You should use AmazonDynamoDB for interfacing to DynamoDB. The method below return is void, so you will need to update the addProduct method.
public void saveProduct(Product item) {
logger.log("Starting to save an item");
//You need a new method to return an AmazonDynamoDB interface
AmazonDynamoDB dynamoDB = getAmazonDynamoDB();
DynamoDBMapper mapper = new DynamoDBMapper(dynamoDB);
mapper.save(item)
logger.log("Item stored");
return saved;
}
EDIT:
You build an AmazonDynamoDB interface like this
// Set to your chosen region
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard()
.withRegion(Regions.US_WEST_2)
.build();
EDIT:
DynamoDBMapper only supports certain data types.
You have three complex data types there; productKind, author and media. If you want to store these in your database, you will need to write a Convertor Class for each one. The convertor class typically define how you convert your object to a string and back again.
EDIT: Your set, ProductKind, will need a convertor that looks like this. Just change 'MyObject' to ProductKinds.
It would be useful to have a stack trace for the exception. In the intermediate message it contains the data type and field information which can not be converted.
Usually you do not need to make any convertors, just be sure to have #DynamoDBDocument on all custom classes, and #DynamoDBTypeConvertedEnum on all custom enums used.
I also had this error and it is a bit misleading, all we need to do is use #DynamoDBDocument on the class file of the referenced classes.
For your case, just put this annotation on ProductKind, like this:
#DynamoDBDocument
class ProductKind {
...
}
It should persist into dynamoDB as a map in the product table.
you will run into this error if the mapper class is
missing a No-Arg constructor
or has
invalid Setters/Getters
that do not comply with the camel case convention.
(Solved) Error: could not unconvert attribute dynamodb
Anybody help me? I want to change row color in TableView depending on value.
For example: i want to change row color to green color when value in column colType is equal to "good"
This is my method where Im filling TableView with data from database:
public void setCustomers() {
List<Customer> list = customer.getTable(); //getting results from database
data = FXCollections.observableArrayList();
Integer count = 1;
for (Customer customer1 : list) {
data.add(new CustomerObj(count++, customer1.getId(), customer1.getName(),
form.formatDate(customer1.getBorn().toString()), customer1.getStreet(),
customer1.getCity(), customer1.getIdCustomerType().getPhrase()));
}
tblCustomer.setItems(data);
tblCustomer.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
colID.setCellValueFactory(cell -> cell.getValue().getPropertyId());
colName.setCellValueFactory(cell -> cell.getValue().getPropertyName());
colBorn.setCellValueFactory(cell -> cell.getValue().getPropertyBorn());
colAddr.setCellValueFactory(cell -> cell.getValue().getPropertyAddr());
colCity.setCellValueFactory(cell -> cell.getValue().getPropertyCity());
colType.setCellValueFactory(cell -> cell.getValue().getPropertyType());
rowOptions.setCellValueFactory(new PropertyValueFactory<>("Button"));
editCust(); //just filling TableCell with Button
rowOptions1.setCellValueFactory(new PropertyValueFactory<>("Button"));
deleteCust(); //just filling TableCell with Button
}
And this is the CustomerObj class:
package sk.evka.fp.obj;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
public class CustomerObj {
private SimpleIntegerProperty id;
private SimpleIntegerProperty idDB;
private SimpleStringProperty name;
private SimpleStringProperty born;
private SimpleStringProperty addr;
private SimpleStringProperty city;
private SimpleStringProperty type;
public CustomerObj(Integer i, Integer id, String n, String b, String a, String c, String t) {
this.id = new SimpleIntegerProperty(i);
this.idDB = new SimpleIntegerProperty(id);
this.name = new SimpleStringProperty(n);
this.born = new SimpleStringProperty(b);
this.addr = new SimpleStringProperty(a);
this.city = new SimpleStringProperty(c);
this.type = new SimpleStringProperty(t);
}
public Integer getId() {
return id.get();
}
public Integer getIdDB() {
return idDB.get();
}
public String getName() {
return name.get();
}
public String getBorn() {
return born.get();
}
public String getAddr() {
return addr.get();
}
public String getCity() {
return city.get();
}
public String getType() {
return type.get();
}
public void setId(Integer i) {
this.id = new SimpleIntegerProperty(i);
}
public void setIdDB(Integer i) {
this.idDB = new SimpleIntegerProperty(i);
}
public void setName(String n) {
name = new SimpleStringProperty(n);
}
public void setBorn(String b) {
born = new SimpleStringProperty(b);
}
public void setAddr(String a) {
addr = new SimpleStringProperty(a);
}
public void setCity(String c) {
city = new SimpleStringProperty(c);
}
public void setType(String t) {
type = new SimpleStringProperty(t);
}
public SimpleIntegerProperty getPropertyId() {
return id;
}
public SimpleIntegerProperty getPropertyIdDB() {
return idDB;
}
public SimpleStringProperty getPropertyName() {
return name;
}
public SimpleStringProperty getPropertyBorn() {
return born;
}
public SimpleStringProperty getPropertyAddr() {
return addr;
}
public SimpleStringProperty getPropertyCity() {
return city;
}
public SimpleStringProperty getPropertyType() {
return type;
}
public void setPropertyId(SimpleIntegerProperty i) {
this.id = i;
}
public void setPropertyIdDB(SimpleIntegerProperty i) {
this.idDB = i;
}
public void setPropertyName(SimpleStringProperty n) {
name = n;
}
public void setPropertyBorn(SimpleStringProperty b) {
born = b;
}
public void setPropertyAddr(SimpleStringProperty a) {
addr = a;
}
public void setPropertyCity(SimpleStringProperty c) {
city = c;
}
public void setPropertyType(SimpleStringProperty t) {
type = t;
}
}
i havent found an answer to this nowhere.
If you want to color the whole row, use a rowFactory that changes the color of the TableRows it creates according to item property.
Furthermore you better use JavaFX properties appropriately:
Properties are not meant to be replaced themselfs. The property getter should always return the same property instance or at least instances that store listeners in a common data structure; Otherwise the value could be modified without the possibility of being notified of that fact (replacing the property with a property containing a new value).
public static class Item {
// property only assigned once
private final StringProperty type;
public Item(String type) {
this.type = new SimpleStringProperty(type);
}
// getter for value wrapped in property
public final String getType() {
return this.type.get();
}
// setter for value wrapped in property
public final void setType(String value) {
this.type.set(value);
}
// property getter
public final StringProperty typeProperty() {
return this.type;
}
}
public static Color typeToColor(String type) {
if (type == null) {
return Color.WHITESMOKE;
}
switch (type) {
case "bad":
return Color.RED;
case "good":
return Color.LIME;
default:
return Color.WHITESMOKE;
}
}
TableView<Item> table = new TableView<>(FXCollections.observableArrayList(
new Item("ok"),
new Item("bad"),
new Item("good")));
TableColumn<Item, String> typeColumn = new TableColumn<>("type");
typeColumn.setCellValueFactory(new PropertyValueFactory<>("type"));
table.setRowFactory(tv -> {
TableRow<Item> row = new TableRow<>();
StringBinding typeBinding = Bindings.selectString(row.itemProperty(), "type");
row.backgroundProperty().bind(Bindings.createObjectBinding(()
-> new Background(new BackgroundFill(typeToColor(typeBinding.get()), CornerRadii.EMPTY, Insets.EMPTY)), typeBinding));
return row;
});
table.getColumns().add(typeColumn);
Finally I have done this thing:
Callback<TableColumn<CustomerObj, String>, TableCell<CustomerObj, String>> cellFactory
= new Callback<TableColumn<CustomerObj, String>, TableCell<CustomerObj, String>>() {
public TableCell call(TableColumn p) {
TableCell cell = new TableCell<CustomerObj, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
CustomerObj obj = this.getTableView().getItems().get(getIndex());
setText(obj.getType());
switch (obj.getType()) {
case "good":
setStyle("-fx-background-color: rgba(71, 209, 71, .7)");
break;
case "problem":
setStyle("-fx-background-color: rgba(255, 51, 51, .7)");
break;
case "ViP":
setStyle("-fx-background-color: rgba(255, 219, 25 .7)");
break;
default:
break;
}
} else {
setText(null);
}
}
private String getString() {
return getItem() == null ? "" : getItem().toString();
}
};
return cell;
}
};
colType.setCellFactory(cellFactory);
Works fine and looks so much better, but thanks it brought me closer to the solution.
I have a java bean class 'MenuItem' which consist of list of children .
I want to display iterate and render through this object in jsp and display the menu tree.
I tried the json data creation, but it needs ajax call. And in my case, I need to submit the page instead of ajax.
I am using struts 2. Can anyone please suggest how can I render and iterate through my bean object in jsp ?
Thanks in Advance.
Here is my Menu bean object:
public class MenuItem implements Serializable {
private static final long serialVersionUID = 8690828081102943225L;
private Long id;
private String name;
private Collection<MenuItem> children;
private String url;
private String actionHoverLabel;
private String actionLabel;
private Long displayOrder;
private Boolean isLeaf;
private Boolean isVisible;
private Long menuLevel;
private Long parentId;
public String getActionHoverLabel() {
return actionHoverLabel;
}
public void setActionHoverLabel(String actionHoverLabel) {
this.actionHoverLabel = actionHoverLabel;
}
public String getActionLabel() {
return actionLabel;
}
public void setActionLabel(String actionLabel) {
this.actionLabel = actionLabel;
}
public Long getDisplayOrder() {
return displayOrder;
}
public void setDisplayOrder(Long displayOrder) {
this.displayOrder = displayOrder;
}
public Boolean getIsLeaf() {
return isLeaf;
}
public void setIsLeaf(Boolean isLeaf) {
this.isLeaf = isLeaf;
}
public Boolean getIsVisible() {
return isVisible;
}
public void setIsVisible(Boolean isVisible) {
this.isVisible = isVisible;
}
public Long getMenuLevel() {
return menuLevel;
}
public void setMenuLevel(Long menuLevel) {
this.menuLevel = menuLevel;
}
public Long getParentId() {
return parentId;
}
public void setParentId(Long parentId) {
this.parentId = parentId;
}
public MenuItem() {
children = new ArrayList<MenuItem>();
isVisible = true;
}
public MenuItem(Long id, String name) {
this.id = id;
this.name = name;
children = new ArrayList<MenuItem>();
isVisible = true;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Collection<MenuItem> getChildren() {
return this.children;
}
public void setChildren(Collection<MenuItem> children) {
this.children = children;
}
public boolean isLeaf() {
if (children != null && children.size() > 0) {
return false;
} else {
return true;
}
}
public void addChild(MenuItem child) {
if (child != null && children != null) {
children.add(child);
child.setParentId(this.getId());
}
}
public void removeChild(MenuItem child) {
if (child != null && children != null) {
children.remove(child);
child.setParentId(null);
}
}
public void setUrl(String url) {
this.url = url;
}
public String getUrl() {
if (url == null) {
return name;
} else {
return url;
}
}
#Override
public boolean equals(Object obj) {
MenuItem m = null;
boolean isEqual = false;
if (id != null && id >= 0) {
m = (MenuItem) obj;
if (m.getId().equals(id)
isEqual = true;
} else {
isEqual = super.equals(obj);
}
return isEqual;
}
#Override
public int hashCode() {
if (id != null && id >= 0) {
return id.hashCode();
} else {
return super.hashCode();
}
}
#Override
public String toString() {
return "name: " + name + " id: " + id;
}
If you want to operate on the bean in JSP, you can very well do that with struts tags. The bean has to be in the scope.
Why do you need JSON in this case?
If you still want JSON, the check for GSON library and Jackson mapper library.
On the JSP, you can store the JSON object in a variable and then operate on that.
On page submit Struts action would form the JSON and then set it in a page bean variable.
Go to www.json.org
Download Java Library for JSON encoding.
Compile it (build a jar for convenience).
Write a method alike this to JSON Serialize your bean:
public static String toJson(SomeBean bean)
{
JSONObject jo = new JSONObject(bean);
return jo.toString();
}
Deserialization is a little tricky but should work like:
JSONObject jo = new JSONObject(jsonString);
SomeBean res = new SomeBean();
res.someProperty = jo.getString("someProperty");
res.someIntProperty= jo.getInt("someIntProperty");
Obviously you have to take care of complex properties, but for simple beans it should work out like a charm.
Straight from sources:
/**
* Construct a JSONObject from an Object using bean getters.
* It reflects on all of the public methods of the object.
* For each of the methods with no parameters and a name starting
* with <code>"get"</code> or <code>"is"</code> followed by an uppercase letter,
* the method is invoked, and a key and the value returned from the getter method
* are put into the new JSONObject.
*
* The key is formed by removing the <code>"get"</code> or <code>"is"</code> prefix.
* If the second remaining character is not upper case, then the first
* character is converted to lower case.
*
* For example, if an object has a method named <code>"getName"</code>, and
* if the result of calling <code>object.getName()</code> is <code>"Larry Fine"</code>,
* then the JSONObject will contain <code>"name": "Larry Fine"</code>.
*
* #param bean An object that has getter methods that should be used
* to make a JSONObject.
*/
public JSONObject(Object bean) {
this();
this.populateMap(bean);
}
Are you sure you've everything set up correctly (Classpath) ?
I have a question about the handling of node properties in an outlineview.
I have three level of nodes, the rootNode, the node and each node may have sub-nodes. Apart from the rootNode, all nodes and subnodes shall have the same (Boolean => checkbox) property. In my outlineview I have two columns, the node(s) column, and a property column with checkboxes.
What I need now is the behaviour, that when I activate the checkbox of a node, all its sub-nodes checkboxes shall be activated as well, when I deactivate the checkbox of a node, all its sub-nodes checkboxes shall be de-activated as well. If I expand the tree to see the sub-nodes, each sub-node may be selected as well.
My current code looks like the following (some parts are found on the internet):
The main api
public class Category {
private String name;
private Boolean x;
public Category() {
this("empty");
}
public Category(String name) {
this.name = name;
}
public Category(String name, Boolean x) {
this.name = name;
this.x = x;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getx() {
return x;
}
public void setx(Boolean x) {
this.x = x;
}
}
My ChildFactory for the nodes (category) looks like
public class CategoryChildrenFactory extends ChildFactory.Detachable<Category> {
/* detachable has no real effect on the current code, used to control
the life cylce */
#Override
protected boolean createKeys(List<Category> toPopulate) {
toPopulate.add(new Category("Cat1", false));
toPopulate.add(new Category("Cat2", false));
toPopulate.add(new Category("Cat3", false));
return true;
}
#Override
protected Node createNodeForKey(Category key) {
AllNode cn = new AllNode(key);
return cn;
}
}
and for the sub-nodes
public class MovieChildrenFactory extends ChildFactory<String>{
Category category;
public MovieChildrenFactory(Category category) {
this.category = category;
}
#Override
protected boolean createKeys(List<String> toPopulate) {
toPopulate.add("m_1");
toPopulate.add("m_2");
toPopulate.add("m_3");
return true;
}
#Override
protected Node createNodeForKey(String key) {
return new AllNode(category, key);
}
}
The nodes creation is put into a single class for both types (nodes, subnodes)
public class AllNode extends AbstractNode {
Category category;
String title;
private Sheet.Set set;
public AllNode(Category category) {
this(category, null);
this.category = category;
set = Sheet.createPropertiesSet();
}
public AllNode(Category category, String title) {
super(Children.LEAF, Lookups.singleton(category));
if (title == null) {
this.setChildren(Children.create(new MovieChildrenFactory(category), true));
}
this.title = title;
set = Sheet.createPropertiesSet();
}
#Override
public String getHtmlDisplayName() {
String name = "";
if (title == null) {
name = category.getName();
} else {
name = title;
}
return name;
}
#Override
protected Sheet createSheet() {
Sheet sheet = Sheet.createDefault();
Category obj = getLookup().lookup(Category.class);
PlotMathProperties pmp = new PlotMathProperties(obj, title);
set.put(pmp.getMyProperty());
sheet.put(set);
return sheet;
}
}
The properties are handled by
public class PlotMathProperties {
private MyProperty myProperty;
private String categoryName;
private String title;
public PlotMathProperties(Category category, String title) {
this.categoryName = category.getName();
this.title= title;
this.myProperty= new MyProperty ();
}
public XProperty getMyProperty () {
return myProperty;
}
public class MyProperty extends PropertySupport.ReadWrite<Boolean> {
private Boolean isMyProp = false;
public MyProperty () {
super("x", Boolean.class, "XPROP", "Is this a coloured or black and white movie");
}
#Override
public Boolean getValue() throws IllegalAccessException, InvocationTargetException {
return isMyProp ;
}
#Override
public void setValue(Boolean val) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
isMyProp = val;
if (isMyProp) {
System.out.println("active: " + categoryName + ", " + title);
} else {
System.out.println("de-active: " + categoryName + ", " + title);
}
}
}
}
Together with a TopComponent the outlineview looks nice and works well.
Has anyone an idea how to setup the the behaviour for the check-boxes
regards
I have a DropDownChoice :
DropDownChoice timePeriod = new DropDownChoice("timePeriod", Arrays.asList(new TimePeriod(1, "Weekly"), new TimePeriod(2, "Bi-Weekly"), new TimePeriod(3, "Semi-Monthly"), new TimePeriod(4, "Monthly"), new TimePeriod(5, "Yearly")), new IChoiceRenderer() {
private static final long serialVersionUID = 10102L;
#Override
public String getIdValue(Object object, int index) {
return ((TimePeriod) object).getId() + "";
}
#Override
public Object getDisplayValue(Object object) {
return ((TimePeriod) object).getPeriodType();
}
});
timePeriod.setNullValid(false);
My question is:
How to set the selected index to 2 or any other?
How to remove first default blank option?
Thank you.
You should be able to set the selected index by using a PropertyModel instead of hard-coding the values of the dropdown. I can't test at the moment, but it would be something like
String timePeriodValue = "Bi-Weekly";
DropDownChoice timePeriod = new DropDownChoice("timePeriod",
new PropertyModel(this, "timePeriodValue"),
Arrays.asList(/* your options */),
new IChoiceRenderer() {
// ...
// Again, this is pseudocode only
As a bonus, the very act of setting a default value should eliminate the blank option problem.
DropDownChoice has a constructor which accepts the default value.
Or in your code you can add timePeriod.setModel(Model.of(new TimePeriod(2, "Bi-Weekly")))
I guess TimePeriod has proper #equals() and #hashCode() implementations.
About the blank option: see org.apache.wicket.markup.html.form.AbstractSingleSelectChoice.isNullValid()
Lord Torgamus and martin-g thank you both of you. I did a small test. And it is working perfectly. As Lord Torgamus indicated,
#SuppressWarnings({ "unchecked", "rawtypes", "serial" })
public class MyPage extends WebPage {
public MyPage() {
add(new MyForm("form"));
}
private class MyForm extends Form {
public MyForm(String id) {
super(id);
setOutputMarkupPlaceholderTag(true);
setModel(new Model(new FormModel()));
final DropDownChoice timePeriod = new DropDownChoice("timePeriod", new PropertyModel(getModel(), "timePeriod"), Arrays.asList(new TimePeriod(1, "Weekly"), new TimePeriod(2, "Bi-Weekly"), new TimePeriod(3, "Semi-Monthly"), new TimePeriod(4, "Monthly"), new TimePeriod(5, "Yearly")), new IChoiceRenderer() {
private static final long serialVersionUID = 10102L;
#Override
public String getIdValue(Object object, int index) {
return ((TimePeriod) object).getId() + "";
}
#Override
public Object getDisplayValue(Object object) {
return ((TimePeriod) object).getPeriodType();
}
});
timePeriod.setNullValid(false);
add(timePeriod);
timePeriod.setOutputMarkupPlaceholderTag(true);
timePeriod.add(new AjaxFormComponentUpdatingBehavior("onChange") {
#Override
protected void onUpdate(AjaxRequestTarget target) {
MyForm form = (MyForm) timePeriod.getParent();
FormModel formModel = (FormModel) form.getModelObject();
formModel.setTimePeriod(new TimePeriod(4, "Monthly"));
form.setModel(new Model(formModel));
target.addComponent(form);
}
});
}
#Override
public void onSubmit() {
System.out.println(getModelObject());
}
}
private class FormModel implements Serializable {
private TimePeriod timePeriod = new TimePeriod(2, "Bi-Weekly");
public FormModel() {
}
public TimePeriod getTimePeriod() {
return timePeriod;
}
public void setTimePeriod(TimePeriod timePeriod) {
this.timePeriod = timePeriod;
}
#Override
public String toString() {
return "FormModel [timePeriod=" + timePeriod + "]";
}
}
private class TimePeriod implements Serializable {
private int id;
private String periodType;
public TimePeriod(int id, String periodType) {
super();
this.id = id;
this.periodType = periodType;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPeriodType() {
return periodType;
}
public void setPeriodType(String periodType) {
this.periodType = periodType;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + id;
result = prime * result + ((periodType == null) ? 0 : periodType.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
TimePeriod other = (TimePeriod) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (id != other.id)
return false;
if (periodType == null) {
if (other.periodType != null)
return false;
} else if (!periodType.equals(other.periodType))
return false;
return true;
}
private LoginPage getOuterType() {
return LoginPage.this;
}
#Override
public String toString() {
return "TimePeriod [id=" + id + ", periodType=" + periodType + "]";
}
}
}
The above code is provided for other users as it might be helpful and I wrote it for testing purpose so all the classes are written in one .java file although it is not advisable.
Thank you.