I have an object with fields of varying datatypes:
public class MyObject{
private String field1;
private CustomObject field2;
private int field3;
...
}
I want to create a tree view of MyObject that will have multiple MyObject nodes, each with the fields (field1, field2, field3..etc) as children.
I know I can make a TreeView of Strings and populate it myself with an addNode(MyObject obj) method in which I would add the individual TreeItems I need. However, I did this with a TableView where I was able to bind a column with a field property. Such as:
TableView<MyObject> table;
TableColumn<MyObject, String> myColumn;
myColumn.setCellValueFactory(new PropertyValueFactory<>("field1"));
Is there any way to do something similar for a TreeView<MyObject>? Im not opposed to creating a subclass that extends TreeItem<?>
The ending result I'm looking for would be something like this:
--> First My Object
->field1: "Value at Field 1"
->field2: "Value at Field 2"
->field3: 3
--> Second My Object
->field1: "Value at Field 1"
->field2: "Value at Field 2"
->field3: 3
Pretty much any time you use a TreeView with different types in different nodes of the tree, you will need some casting and/or type checking somewhere.
One possible approach here is to subclass TreeItem to provide a field for the property you want to show, and then to use a TreeCell that shows the string value of that property.
Here's a very basic example of that:
import java.util.Arrays;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.stage.Stage;
public class TreeViewWithProperties extends Application {
#Override
public void start(Stage primaryStage) {
List<SomeEntity> entities = Arrays.asList(
new SomeEntity("First object", "String value 1", 42),
new SomeEntity("Second object", "String value 2", 3)
);
TreeView<SomeEntity> tree = new TreeView<>();
tree.setShowRoot(false);
TreeItem<SomeEntity> treeRoot = new TreeItem<>();
tree.setRoot(treeRoot);
for (SomeEntity entity : entities) {
TreeItem<SomeEntity> item = PropertyTreeItem.baseItem(entity);
treeRoot.getChildren().add(item);
item.getChildren().add(new PropertyTreeItem<String>(entity, entity.getStringField()));
item.getChildren().add(new PropertyTreeItem<Integer>(entity, entity.getValue()));
}
tree.setCellFactory(tv -> new TreeCell<SomeEntity>() {
#Override
protected void updateItem(SomeEntity entity, boolean empty) {
super.updateItem(entity, empty);
PropertyTreeItem<?> item = (PropertyTreeItem<?>) getTreeItem();
if (empty) {
setText(null);
} else {
setText(item.getPropertyValue().toString());
}
}
});
Scene scene = new Scene(tree);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class PropertyTreeItem<T> extends TreeItem<SomeEntity> {
private final T propertyValue ;
public PropertyTreeItem(SomeEntity entity, T value) {
super(entity);
this.propertyValue = value ;
}
public static PropertyTreeItem<SomeEntity> baseItem(SomeEntity entity) {
return new PropertyTreeItem<>(entity, entity);
}
public T getPropertyValue() {
return propertyValue ;
}
}
public class SomeEntity {
private String name ;
private String stringField ;
private int value ;
public SomeEntity(String name, String stringField, int value) {
this.name = name;
this.stringField = stringField;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStringField() {
return stringField;
}
public void setStringField(String stringField) {
this.stringField = stringField;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
#Override
public String toString() {
return name ;
}
}
public static void main(String[] args) {
launch(args);
}
}
Some variations on this are possible, of course. If you wanted to use JavaFX properties in the entity class, and be able to change those values externally to the tree, you could bind the text to the property in the cell instead of simply setting it.
Using some ideas from the link I posted under your question. This example uses a helper Class to create the TreeItems.
Main
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* #author blj0011
*/
public class JavaFXApplication128 extends Application
{
#Override
public void start(Stage primaryStage)
{
MyObject myObject1 = new MyObject("myObject1", "field 1 a", new CustomObject("customObject 1", 3), 5);
MyObject myObject2 = new MyObject("myObject2", "field 1 b", new CustomObject("customObject 2", 36), 10);
MyObject myObject3 = new MyObject("myObject3", "field 1 c", new CustomObject("customObject 3", 23), 8);
List<MyObject> list = new ArrayList();
list.add(myObject1);
list.add(myObject2);
list.add(myObject3);
List<TreeItem<String>> treeItemsContainer = new ArrayList();
for (MyObject object : list) {
ObjectToTreeView objectToTreeView = new ObjectToTreeView(object);
treeItemsContainer.add(objectToTreeView.getRootItem());
}
TreeItem<String> rootItem = new TreeItem();
rootItem.setExpanded(true);
rootItem.getChildren().addAll(treeItemsContainer);
TreeView treeView = new TreeView(rootItem);
Scene scene = new Scene(treeView, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
ObjectToTreeView Class <- a helper class
import javafx.scene.control.TreeItem;
/**
*
* #author blj0011
*/
public class ObjectToTreeView
{
private final TreeItem<String> rootItem = new TreeItem();
public ObjectToTreeView(MyObject myObject)
{
rootItem.setValue(myObject.getTitle());
rootItem.getChildren().add(new TreeItem(myObject.getField1()));
CustomObject customObject = myObject.getField2();
rootItem.getChildren().add(new TreeItem(customObject.getName()));
rootItem.getChildren().add(new TreeItem(customObject.getNumber()));
rootItem.getChildren().add(new TreeItem(myObject.getField3()));
}
/**
* #return the rootItem
*/
public TreeItem<String> getRootItem()
{
return rootItem;
}
}
MyObject Class
/**
*
* #author blj0011
*/
public class MyObject
{
private String title;
private String field1;
private CustomObject field2;
private int field3;
public MyObject(String title, String field1, CustomObject field2, int field3)
{
this.title = title;
this.field1 = field1;
this.field2 = field2;
this.field3 = field3;
}
/**
* #return the title
*/
public String getTitle()
{
return title;
}
/**
* #param title the title to set
*/
public void setTitle(String title)
{
this.title = title;
}
/**
* #return the field1
*/
public String getField1()
{
return field1;
}
/**
* #param field1 the field1 to set
*/
public void setField1(String field1)
{
this.field1 = field1;
}
/**
* #return the field3
*/
public int getField3()
{
return field3;
}
/**
* #param field3 the field3 to set
*/
public void setField3(int field3)
{
this.field3 = field3;
}
/**
* #return the field2
*/
public CustomObject getField2()
{
return field2;
}
/**
* #param field2 the field2 to set
*/
public void setField2(CustomObject field2)
{
this.field2 = field2;
}
}
CustomObject Class
/**
*
* #author blj0011
*/
public class CustomObject
{
private String name;
private int number;
public CustomObject(String name, int number)
{
this.name = name;
this.number = number;
}
/**
* #return the name
*/
public String getName()
{
return name;
}
/**
* #param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
/**
* #return the number
*/
public int getNumber()
{
return number;
}
/**
* #param number the number to set
*/
public void setNumber(int number)
{
this.number = number;
}
}
I ended up just creating a helper function by doing the following:
public TreeItem<String> createNode(MyObject obj) {
TreeItem<String> node = null;
if(obj != null) {
node = new TreeItem<String>("MyObject:" + obj.getId());
node.getChildren().add(new TreeItem<String>("Field1: "+ obj.getField1()));
node.getChildren().add(new TreeItem<String>("Field2: "+ obj.getField2()));
node.getChildren().add(new TreeItem<String>("Field3: "+ obj.getField3()));
}
}
Related
I want add column to grid, when i click to button ("backBtn"). Then i get the value from the textfield ("filterText"), and that will be the name of the new column. Who can help me? The code is from tutorial, but i need add the new feature here. Thanks ! You can find my code in attachment. Grid is in class "MyUI"
This is clas Customer
package my.vaadin.app;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Date;
/**
* A entity object, like in any other Java application. In a typical real world
* application this could for example be a JPA entity.
*/
#SuppressWarnings("serial")
public class Customer implements Serializable, Cloneable {
private Long id;
private String firstName = "";
private String datum = "";
private String lastName = "";
private LocalDate birthDate;
private CustomerStatus status;
private String email = "";
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* Get the value of email
*
* #return the value of email
*/
public String getEmail() {
return email;
}
/**
* Set the value of email
*
* #param email
* new value of email
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Get the value of status
*
* #return the value of status
*/
public CustomerStatus getStatus() {
return status;
}
/**
* Set the value of status
*
* #param status
* new value of status
*/
public void setStatus(CustomerStatus status) {
this.status = status;
}
/**
* Get the value of birthDate
*
* #return the value of birthDate
*/
public LocalDate getBirthDate() {
return birthDate;
}
/**
* Set the value of birthDate
*
* #param birthDate
* new value of birthDate
*/
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
/**
* Get the value of lastName
*
* #return the value of lastName
*/
public String getLastName() {
return lastName;
}
/**
* Set the value of lastName
*
* #param lastName
* new value of lastName
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* Get the value of firstName
*
* #return the value of firstName
*/
public String getFirstName() {
return firstName;
}
/**
* Set the value of firstName
*
* #param firstName
* new value of firstName
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getDatum() {
return datum;
}
/**
* Set the value of firstName
*
* #param firstName
* new value of firstName
*/
public void setDatum(String datum) {
this.datum = datum;
}
public boolean isPersisted() {
return id != null;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (this.id == null) {
return false;
}
if (obj instanceof Customer && obj.getClass().equals(getClass())) {
return this.id.equals(((Customer) obj).id);
}
return false;
}
#Override
public int hashCode() {
int hash = 5;
hash = 43 * hash + (id == null ? 0 : id.hashCode());
return hash;
}
#Override
public Customer clone() throws CloneNotSupportedException {
return (Customer) super.clone();
}
#Override
public String toString() {
return firstName + " " + lastName;
}
}
This is clas MyUI
package my.vaadin.app;
import java.util.List;
import javax.servlet.annotation.WebServlet;
import javax.swing.text.TableView;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.shared.ui.ValueChangeMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.components.grid.HeaderCell;
import com.vaadin.ui.components.grid.HeaderRow;
import com.vaadin.ui.themes.ValoTheme;
/**
* This UI is the application entry point. A UI may either represent a browser window
* (or tab) or some part of a html page where a Vaadin application is embedded.
* <p>
* The UI is initialized using {#link #init(VaadinRequest)}. This method is intended to be
* overridden to add component to the user interface and initialize non-component functionality.
*/
#Theme("mytheme")
public class MyUI extends UI {
private CustomerService service = CustomerService.getInstance();
private Grid<Customer> grid = new Grid<>(Customer.class);
private TextField filterText = new TextField();
// private CustomerForm form = new CustomerForm(this);
#Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout();
Label tancore = new Label();
filterText.setPlaceholder("Meno ...");
//filterText.addValueChangeListener(e -> updateList());
//filterText.setValueChangeMode(ValueChangeMode.LAZY);
Button clearFilterTextBtn = new Button(FontAwesome.TIMES);
clearFilterTextBtn.setDescription("Clear the current name");
clearFilterTextBtn.addClickListener(e -> filterText.clear());
tancore.setCaption("TanCore s.r.o");
CssLayout filtering = new CssLayout();
filtering.addComponents(filterText, clearFilterTextBtn);
filtering.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
Button addCustomerBtn = new Button("Pridaj zamestnanca");
Button downloadXlsBtn = new Button("Stiahnuť ako .xls");
Button loginBtn = new Button("Prihlásiť sa");
// Button addEmplBtn = new Button("Pridaj");
Button backBtn = new Button("Vlož");
downloadXlsBtn.setVisible(false);
TextField name = new TextField();
PasswordField pass = new PasswordField();
// addEmplBtn.setVisible(false);
addCustomerBtn.setVisible(false);
backBtn.setVisible(false);
filtering.setVisible(false);
clearFilterTextBtn.setVisible(false);
filterText.setVisible(false);
addCustomerBtn.setStyleName(ValoTheme.BUTTON_PRIMARY);
//.setStyleName(ValoTheme.BUTTON_PRIMARY);
addCustomerBtn.setClickShortcut(KeyCode.ENTER);
backBtn.addClickListener(e -> {
//Here i want include the new data after click on the button
//grid.addColumn(filterText.getValue()); -> That it's not good, because after click the Java will Warning you
addCustomerBtn.setVisible(true);
backBtn.setVisible(false);
filtering.setVisible(false);
clearFilterTextBtn.setVisible(false);
filterText.setVisible(false);
});
addCustomerBtn.addClickListener(e -> {
addCustomerBtn.setVisible(false);
filtering.setVisible(true);
backBtn.setVisible(true);
clearFilterTextBtn.setVisible(true);
filterText.setVisible(true);
//addEmplBtn.setEnabled(true);
});
loginBtn.addClickListener(e -> {
if(name.getValue().equals("admin"))
{
if(pass.getValue().equals("admin"))
{
name.setVisible(false);
pass.setVisible(false);
loginBtn.setVisible(false);
addCustomerBtn.setVisible(true);
downloadXlsBtn.setVisible(true);
}
}
});
pass.setPlaceholder("Heslo ...");
name.setPlaceholder("Meno ...");
HorizontalLayout toolbar = new HorizontalLayout(name, pass, loginBtn,filtering, addCustomerBtn,backBtn,downloadXlsBtn);
// grid.setSelectionMode(SelectionMode.MULTI);
grid.setColumns("datum", "lastName","email","status");
// grid.setStyleName(ValoTheme.BUTTON_PRIMARY);
/*HeaderRow extraHeader = grid.prependHeaderRow();
HeaderCell joinedCell = extraHeader.join("datum", "lastName");
joinedCell.setText("Joined cell");*/
HorizontalLayout main = new HorizontalLayout(grid);
main.setSizeFull();
grid.setSizeFull();
// main.setExpandRatio(grid, 1);
grid.getColumn("datum").setWidth(100);
// grid.getColumn("datum").set
// grid.getColumn("datum").set
grid.getColumn("datum").setCaption("Dátum");
grid.getColumn("lastName").setCaption("Adam");
layout.addComponents(toolbar, main);
// fetch list of Customers from service and assign it to Grid
updateList();
setContent(layout);
// form.setVisible(false);
grid.asSingleSelect().addValueChangeListener(event -> {
//if (event.getValue() == null) {
// form.setVisible(false);
//} else {
// form.setCustomer(event.getValue());
//}
});
}
public void updateList() {
List<Customer> customers = service.findAll(filterText.getValue());
grid.setItems(customers);
}
#WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
#VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
}
This is clas CustomerForm.java
package my.vaadin.app;
import com.vaadin.data.Binder;
import com.vaadin.event.ShortcutAction.KeyCode;
import com.vaadin.ui.Button;
import com.vaadin.ui.DateField;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.NativeSelect;
import com.vaadin.ui.TextField;
import com.vaadin.ui.themes.ValoTheme;
public class CustomerForm extends FormLayout {
private TextField firstName = new TextField("First name");
private TextField lastName = new TextField("Last name");
private TextField email = new TextField("Email");
private NativeSelect<CustomerStatus> status = new NativeSelect<>("Status");
private DateField birthdate = new DateField("Birthday");
private Button save = new Button("Save");
private Button delete = new Button("Delete");
private CustomerService service = CustomerService.getInstance();
private Customer customer;
private MyUI myUI;
private Binder<Customer> binder = new Binder<>(Customer.class);
public CustomerForm(MyUI myUI) {
this.myUI = myUI;
setSizeUndefined();
HorizontalLayout buttons = new HorizontalLayout(save, delete);
addComponents(firstName, lastName, email, status, birthdate, buttons);
status.setItems(CustomerStatus.values());
save.setStyleName(ValoTheme.BUTTON_PRIMARY);
save.setClickShortcut(KeyCode.ENTER);
binder.bindInstanceFields(this);
save.addClickListener(e -> this.save());
delete.addClickListener(e -> this.delete());
}
public void setCustomer(Customer customer) {
this.customer = customer;
binder.setBean(customer);
// Show delete button for only customers already in the database
delete.setVisible(customer.isPersisted());
setVisible(true);
firstName.selectAll();
}
private void delete() {
service.delete(customer);
myUI.updateList();
setVisible(false);
}
private void save() {
service.save(customer);
myUI.updateList();
setVisible(false);
}
}
This is clas CustomerService.java
package my.vaadin.app;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* An in memory dummy "database" for the example purposes. In a typical Java app
* this class would be replaced by e.g. EJB or a Spring based service class.
* <p>
* In demos/tutorials/examples, get a reference to this service class with
* {#link CustomerService#getInstance()}.
*/
public class CustomerService {
private static CustomerService instance;
private static final Logger LOGGER = Logger.getLogger(CustomerService.class.getName());
private final HashMap<Long, Customer> contacts = new HashMap<>();
private long nextId = 0;
private CustomerService() {
}
/**
* #return a reference to an example facade for Customer objects.
*/
public static CustomerService getInstance() {
if (instance == null) {
instance = new CustomerService();
instance.ensureTestData();
}
return instance;
}
/**
* #return all available Customer objects.
*/
public synchronized List<Customer> findAll() {
return findAll(null);
}
/**
* Finds all Customer's that match given filter.
*
* #param stringFilter
* filter that returned objects should match or null/empty string
* if all objects should be returned.
* #return list a Customer objects
*/
public synchronized List<Customer> findAll(String stringFilter) {
ArrayList<Customer> arrayList = new ArrayList<>();
for (Customer contact : contacts.values()) {
try {
boolean passesFilter = (stringFilter == null || stringFilter.isEmpty())
|| contact.toString().toLowerCase().contains(stringFilter.toLowerCase());
if (passesFilter) {
arrayList.add(contact.clone());
}
} catch (CloneNotSupportedException ex) {
Logger.getLogger(CustomerService.class.getName()).log(Level.SEVERE, null, ex);
}
}
Collections.sort(arrayList, new Comparator<Customer>() {
#Override
public int compare(Customer o1, Customer o2) {
return (int) (o2.getId() - o1.getId());
}
});
return arrayList;
}
/**
* Finds all Customer's that match given filter and limits the resultset.
*
* #param stringFilter
* filter that returned objects should match or null/empty string
* if all objects should be returned.
* #param start
* the index of first result
* #param maxresults
* maximum result count
* #return list a Customer objects
*/
public synchronized List<Customer> findAll(String stringFilter, int start, int maxresults) {
ArrayList<Customer> arrayList = new ArrayList<>();
for (Customer contact : contacts.values()) {
try {
boolean passesFilter = (stringFilter == null || stringFilter.isEmpty())
|| contact.toString().toLowerCase().contains(stringFilter.toLowerCase());
if (passesFilter) {
arrayList.add(contact.clone());
}
} catch (CloneNotSupportedException ex) {
Logger.getLogger(CustomerService.class.getName()).log(Level.SEVERE, null, ex);
}
}
Collections.sort(arrayList, new Comparator<Customer>() {
#Override
public int compare(Customer o1, Customer o2) {
return (int) (o2.getId() - o1.getId());
}
});
int end = start + maxresults;
if (end > arrayList.size()) {
end = arrayList.size();
}
return arrayList.subList(start, end);
}
/**
* #return the amount of all customers in the system
*/
public synchronized long count() {
return contacts.size();
}
/**
* Deletes a customer from a system
*
* #param value
* the Customer to be deleted
*/
public synchronized void delete(Customer value) {
contacts.remove(value.getId());
}
/**
* Persists or updates customer in the system. Also assigns an identifier
* for new Customer instances.
*
* #param entry
*/
public synchronized void save(Customer entry) {
if (entry == null) {
LOGGER.log(Level.SEVERE,
"Customer is null. Are you sure you have connected your form to the application as described in tutorial chapter 7?");
return;
}
if (entry.getId() == null) {
entry.setId(nextId++);
}
try {
entry = (Customer) entry.clone();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
contacts.put(entry.getId(), entry);
}
/**
* Sample data generation
*/
public void ensureTestData() {
if (findAll().isEmpty()) {
for (int i = 31; i > 0; i--) {
Customer c = new Customer();
c.setDatum(i+".7");
save(c);
}
}
}
}
I want have this in my WebApp
This is actualy my WebApp
I'm trying to display some info using Apache velocity , however it does not seem to work.
Follwing is the code snippet.
package velocitydemo;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
class Vehicle {
private String vname;
private Wheel wheel;
private String type;
/**
* #return the vname
*/
public String getVname() {
return vname;
}
/**
* #param vname the vname to set
*/
public void setVname(String vname) {
this.vname = vname;
}
/**
* #return the wheel
*/
public Wheel getWheel() {
return wheel;
}
/**
* #param wheel the wheel to set
*/
public void setWheel(Wheel wheel) {
this.wheel = wheel;
}
/**
* #return the type
*/
public String getType() {
return type;
}
/**
* #param type the type to set
*/
public void setType(String type) {
this.type = type;
}
/**
* #return the model
*/
public int getModel() {
return model;
}
/**
* #param model the model to set
*/
public void setModel(int model) {
this.model = model;
}
private int model;
public Vehicle(String name, Wheel wheel, String type, int model) {
super();
this.vname = name;
this.wheel = wheel;
this.type = type;
this.model = model;
}
}
class Wheel {
private String type;
private String name;
/**
* #return the type
*/
public String getType() {
return type;
}
/**
* #param type the type to set
*/
public void setType(String type) {
this.type = type;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
public Wheel(String type, String name) {
super();
this.type = type;
this.name = name;
}
}
public class HelloWorld {
private static List<String> list = new ArrayList<String>();
public static void main(String[] args) throws Exception {
Vehicle vh = constructVehicle("Model S", "Vinyl", "JK", "Electric", 2014);
VelocityEngine ve = new VelocityEngine();
ve.init();
/* next, get the Template */
Template t = ve.getTemplate("helloworld.vm");
/* create a context and add data */
VelocityContext context = new VelocityContext();
context.put("name", "World");
context.put("name2", "foobar");
context.put("name3", "flash");
context.put("vehicle", vh);
StringWriter writer = new StringWriter();
t.merge(context, writer);
System.out.println(writer.toString());
}
public static Vehicle constructVehicle(String vehicleName, String wheelType, String wheelName, String vhType, int model) {
Wheel wl = new Wheel(wheelType, wheelName);
Vehicle vh = new Vehicle(vehicleName, wl, vhType, model);
return vh;
}
}
The velocity template is helloworld.vm with the following info
Hello $name! Welcome to Velocity!
Hello $name2! Welcome to Velocity!
Hello $name3! Welcome to Velocity!
Car is $vehicle.vname
Car is $vehicle.getVname()
Car is $vehicle.hashCode() and model is $vehicle.getModel()
However the output is :
Hello World! Welcome to Velocity!
Hello foobar! Welcome to Velocity!
Hello flash! Welcome to Velocity!
Car is $vehicle.vname
Car is $vehicle.getVname()
Car is 14872264 and model is $vehicle.getModel()
I don't understand why variables of class Vehicle are not getting resolved.
I have an array of objects which contain a number of fields. I have a class with the constructors, setters and getters. One of the fields is name. I want to sort alphabetically all the names in the array and list them. Can anyone be of help? This is in java.
Thanks
You can do so with the Comparable interface. Lets assume we have a Class Car, which can be of a certain brand (name in this example)
public class Car implements Comparable<Car> {
private String name;
private String color;
/**
* Names
*/
public enum Name {
FIAT("fiat"), RENAULT("renault"), HONDA("honda");
private final String name;
private Name(final String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
/**
* Colors
*/
public enum Colors {
BLUE("blue"), RED("red"), YELLOW("yellow");
private final String color;
private Colors(final String color) {
this.color = color;
}
public String toString() {
return this.color;
}
}
/**
* Construct car with name and color
* #param name
* #param color
*/
public Car(Name name, Colors color) {
this.name = name.toString();
this.color = color.toString();
}
/**
* return name
* #return
*/
public String getName() {
return this.name;
}
/**
* compare to other car
*/
#Override
public int compareTo(Car car2) {
return this.name.compareTo(car2.getName());
}
}
And the main:
import java.util.Arrays;
public class Main {
//private static List<Car> cars = new ArrayList<Car>();
private static Car[] cars = new Car[3];
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("Create cars in array");
cars[0] = new Car(Car.Name.RENAULT, Car.Colors.YELLOW);
cars[1] = new Car(Car.Name.HONDA, Car.Colors.BLUE);
cars[2] = new Car(Car.Name.FIAT, Car.Colors.RED);
// System.out.println("Create cars in arraylist");
// cars.add(new Car(Car.Name.RENAULT, Car.Colors.YELLOW));
// cars.add(new Car(Car.Name.HONDA, Car.Colors.BLUE));
// cars.add(new Car(Car.Name.FIAT, Car.Colors.RED));
System.out.println("Print cars");
for (Car car : cars) {
System.out.println("Car name: "+car.getName());
}
// sort cars, see Car class
Arrays.sort(cars);
System.out.println("Print cars after sort");
for (Car car : cars) {
System.out.println("Car name: "+car.getName());
}
}
}
See the console for output.
I need a way to deserialize this object:
{
"rows": [
{
"id": 0,
"name": "qwe"
}
],
"total": 0
}
to Row[] (i don't need "total") WITHOUT USING OF WAPPER OBJECT:
public class ReviewsWrapper {
private Row[] rows;
#JsonIgnore
private Integer total;
}
directly deserializing it to Rows[]? If there was no "total" object, i would just deserialize using this method:
public static <T> T fromJsonWithRootName(InputStream is, Class<T> type, String rootName) {
try {
return objectMapper.reader(type).withRootName(rootName).readValue(is);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
passing "rows" as a rootName and will get Row[] as output. Is there any way to avoid using WrapperObject for Row[]? It's an Android project I define entities using Jackson Annotations.
Your JSON data Model classes should be like this
package com.example;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"rows",
"total"
})
public class ReviewsWrapper {
#JsonProperty("rows")
private List<Row> rows = new ArrayList<Row>();
#JsonProperty("total")
private long total;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
/**
*
* #return
* The rows
*/
#JsonProperty("rows")
public List<Row> getRows() {
return rows;
}
/**
*
* #param rows
* The rows
*/
#JsonProperty("rows")
public void setRows(List<Row> rows) {
this.rows = rows;
}
public ReviewsWrapper withRows(List<Row> rows) {
this.rows = rows;
return this;
}
/**
*
* #return
* The total
*/
#JsonProperty("total")
public long getTotal() {
return total;
}
/**
*
* #param total
* The total
*/
#JsonProperty("total")
public void setTotal(long total) {
this.total = total;
}
public ReviewsWrapper withTotal(long total) {
this.total = total;
return this;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
public ReviewsWrapper withAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
return this;
}
}
-----------------------------------com.example.Row.java-----------------------------------
package com.example;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"id",
"name"
})
public class Row {
#JsonProperty("id")
private long id;
#JsonProperty("name")
private String name;
#JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
/**
*
* #return
* The id
*/
#JsonProperty("id")
public long getId() {
return id;
}
/**
*
* #param id
* The id
*/
#JsonProperty("id")
public void setId(long id) {
this.id = id;
}
public Row withId(long id) {
this.id = id;
return this;
}
/**
*
* #return
* The name
*/
#JsonProperty("name")
public String getName() {
return name;
}
/**
*
* #param name
* The name
*/
#JsonProperty("name")
public void setName(String name) {
this.name = name;
}
public Row withName(String name) {
this.name = name;
return this;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
public Row withAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
return this;
}
}
Then in Java Class to de-serialize using Jackson use below code
ObjectMapper mapper = new ObjectMapper();
JsonFactory jf = new JsonFactory();
JsonParser jp = jf.createJsonParser("your json data as a String");
ReviewsWrapper reviewWrapper = mapper.readValue(jp,ReviewsWrapper.class);
after this You can get all your response from "ReviewsWrapper.class"
Here is Example using JsonNode try this. is this what you want?
Here is one Example using Nodes.
public class App {
public static class Foo {
public int foo;
}
public static void main(String[] args) {
String json = "{\"someArray\":[{\"foo\":5},{\"foo\":6},{\"foo\":7}]}";
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(json);
node = node.get("someArray");
TypeReference<List<Foo>> typeRef = new TypeReference<List<Foo>>(){};
List<Foo> list = mapper.readValue(node.traverse(), typeRef);
for (Foo f : list) {
System.out.println(f.foo);
} }}
Can anybody say where I am doing wrong. I have json like that
[{"name":"foo","slug":"foo2","locales":["foo3"],"hostname":"foo4","region_tag":"foo5"},{"name":"foo","slug":"foo2","locales":["foo3"],"hostname":"foo4","region_tag":"foo5"},{"name":"foo","slug":"foo2","locales":["foo3"],"hostname":"foo4","region_tag":"foo5"},{"name":"foo","slug":"foo2","locales":["foo3"],"hostname":"foo4","region_tag":"foo5"}]
And I parse to this class.
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
#JsonPropertyOrder({
"shards"
})
public class ShardsResponse extends Response{
#JsonProperty("shards")
private List<Shards> shards = new ArrayList<Shards>();
/**
*
* #return
* The shards
*/
#JsonProperty("shards")
public List<Shards> getShards() {
return shards;
}
/**
*
* #param shards
* The shards
*/
#JsonProperty("shards")
public void setShards(List<Shards> shards) {
this.shards = shards;
}
}
And Shards class is :
/**
*
* #return
* The locales
*/
#JsonProperty("locales")
public List<String> getLocales() {
return locales;
}
/**
*
* #param locales
* The locales
*/
#JsonProperty("locales")
public void setLocales(List<String> locales) {
this.locales = locales;
}
/**
*
* #return
* The name
*/
#JsonProperty("name")
public String getName() {
return name;
}
/**
*
* #param name
* The name
*/
#JsonProperty("name")
public void setName(String name) {
this.name = name;
}
/**
*
* #return
* The hostname
*/
#JsonProperty("hostname")
public String getHostname() {
return hostname;
}
/**
*
* #param hostname
* The hostname
*/
#JsonProperty("hostname")
public void setHostname(String hostname) {
this.hostname = hostname;
}
/**
*
* #return
* The slug
*/
#JsonProperty("slug")
public String getSlug() {
return slug;
}
/**
*
* #param slug
* The slug
*/
#JsonProperty("slug")
public void setSlug(String slug) {
this.slug = slug;
}
}
So I'm using ObjectMapper.readValue(jsontext, responseclass)
JSONObject object = new JSONObject(JsonString);
JsonString = "";
Iterator<String> keys= object.keys();
while (keys.hasNext()){
String keyValue = (String)keys.next();
JsonString= JsonString+ object.getString(keyValue);
}
JsonString= JsonString.substring(1, JsonString.length()-1);
Object response = ObjectMapper.readValue(JsonString, ShardsResponse.class);
At the last I am getting out of START_ARRAY token. Please anybody tell me what's wrong.
Cause I'm trying so much things, but I never find the solution.
How can I fix it.
Your json string is correct, but not for the object you expect, as someone mentioned already, you need to use a List
import java.io.IOException;
import java.util.List;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;
public class ParseJson {
private static final String jsonString = "[{\"name\":\"foo\",\"slug\":\"foo2\",\"locales\":[\"foo3\"],\"hostname\":\"foo4\",\"region_tag\":\"foo5\"},{\"name\":\"foo\",\"slug\":\"foo2\",\"locales\":[\"foo3\"],\"hostname\":\"foo4\",\"region_tag\":\"foo5\"},{\"name\":\"foo\",\"slug\":\"foo2\",\"locales\":[\"foo3\"],\"hostname\":\"foo4\",\"region_tag\":\"foo5\"},{\"name\":\"foo\",\"slug\":\"foo2\",\"locales\":[\"foo3\"],\"hostname\":\"foo4\",\"region_tag\":\"foo5\"}]";
public static void parse() {
try {
TypeReference<List<Shards>> typeRef = new TypeReference<List<Shards>>() { };
ObjectMapper mapper = new ObjectMapper();
List<Shards> list = mapper.readValue(jsonString, typeRef);
for ( Shards s : list )
{
s.printDebug();
}
ShardsResponse sr = new ShardsResponse(list);
String srString = mapper.writeValueAsString(sr);
System.out.println("srString: " + srString );
TypeReference<ShardsResponse> typeRef2 = new TypeReference<ShardsResponse>() { };
ShardsResponse sr2 = mapper.readValue(srString, typeRef2);
sr2.printDebug();
} catch ( IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ParseJson.parse();
}
}
Edit:
If you expect a ShardsResponse back, your json string should look like this:
{"shards":[{"locales":["foo3"],"name":"foo","hostname":"foo4","slug":"foo2","region_tag":"foo5"},{"locales":["foo3"],"name":"foo","hostname":"foo4","slug":"foo2","region_tag":"foo5"},{"locales":["foo3"],"name":"foo","hostname":"foo4","slug":"foo2","region_tag":"foo5"},{"locales":["foo3"],"name":"foo","hostname":"foo4","slug":"foo2","region_tag":"foo5"}]}
Easiest way to figure out what the json will look like is to dump it out:
ShardsResponse sr = new ShardsResponse(list);
String srString = mapper.writeValueAsString(sr);
System.out.println("srString: " + srString );
Edit:
Adding additional Classes for clarity:
ShardsResponses.java
import java.util.ArrayList;
import java.util.List;
public class ShardsResponse {
private List<Shards> shards = new ArrayList<Shards>();
public ShardsResponse() { }
public ShardsResponse( List<Shards> shards)
{
this.shards = shards;
}
public List<Shards> getShards() {
return shards;
}
public void setShards(List<Shards> shards) {
this.shards = shards;
}
public void printDebug()
{
for ( Shards s : shards)
{
s.printDebug();
System.out.println("");
}
}
}
Shards.java:
import java.util.List;
public class Shards {
private List<String> locales;
private String name;
private String hostname;
private String slug;
private String region_tag;
public List<String> getLocales() {
return locales;
}
public void setLocales(List<String> locales) {
this.locales = locales;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public String getSlug() {
return slug;
}
public void setSlug(String slug) {
this.slug = slug;
}
public void printDebug()
{
System.out.println("name: " + name);
System.out.println("hostname: " + hostname);
System.out.println("slug: " + slug);
System.out.println("region_tag: " + region_tag);
for ( String s : locales )
{
System.out.println("Locals: " + locales);
}
}
public String getRegion_tag() {
return region_tag;
}
public void setRegion_tag(String region_tag) {
this.region_tag = region_tag;
}
}
you have an jsonArray but you are trying to parse a jsonObject. change your method to return a list of objects instead of one object.