How to deal with a bean containing #Id #GeneratedVaule in Vaadin? - java

I'm trying to make a form that will send data to the database in Vaadin.
Bean Person.java is a typical JavaBean:
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
public class Person implements Serializable {
#Id
#GeneratedValue
private Long id;
private String firstName;
private String lastName;
public Person(Long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
public Person() {
}
-- getters and setters --
The Vaadin FieldGroup looks like this:
FieldGroup fieldGroup = new BeanFieldGroup<Person>(Person.class);
// from the tutorial: "We need an item data source before we create the fields to be able to
// find the properties, otherwise we have to specify them by hand"
fieldGroup.setItemDataSource(new BeanItem<Person>(new Person(1L,
"John", "Doe")));
for (Object propertyId : fieldGroup.getBoundPropertyIds()) {
layout.addComponent(fieldGroup.buildAndBind(propertyId));
}
There is nothing on the page. Nothing is generated, no form fields. Am I missing something? I'm completely new to Vaadin to be honest. On the second hand, I'm wondering how to deal with the ID field. It is generated automatically, so the user shall have NO impact on this vaule... I'm lost.

My advice is this:
public class MyUI extends UI {
#Override
protected void init(VaadinRequest request) {
VerticalLayout layout = new VerticalLayout();
FieldGroup fieldGroup = new BeanFieldGroup<Person>(Person.class);
fieldGroup.setItemDataSource(new BeanItem<Person>(new Person(1L, "John", "Doe")));
for (Object propertyId : fieldGroup.getUnboundPropertyIds()) {
Field<?> field = fieldGroup.buildAndBind(propertyId);
if ("id".equals(propertyId)) {
field.setReadOnly(true);
}
layout.addComponent(field);
}
setContent(layout);
}
}
You should use getUnboundPropertyIds(), because you haven't bound any propertyId to field before the iteration.

Related

How to load a combobox with vaadin fusion

Hi I'm using the vaadin starter in order to learn more about vaadin.
I just started a new project (Java+Typescript)
I am having issues to solve an issue.
I have a Users and Rol Entity, being Rol an attribute of User, the thing is when I am setting the views created with vaading start I am trying to set up a combo box to load Roles to be used to create a new user but nothing work so far.
In the tutorial in vaading web page they solve this in a way that is way different to the arch and files created by the vaadin start so I thought that maybe would be another way to do it.
My entities
User
package com.example.application.data.entity;
import com.vaadin.fusion.Nonnull;
import com.example.application.data.AbstractEntity;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
#Entity
public class Users extends AbstractEntity {
#ManyToOne
#Nonnull
private Rol rol;
public Rol getRol() {
return rol;
}
public void setRol(Rol rol) {
this.rol = rol;
}
}
Rol
package com.example.application.data.entity;
import com.vaadin.fusion.Nonnull;
import com.example.application.data.AbstractEntity;
import javax.persistence.Entity;
#Entity
public class Rol extends AbstractEntity{
#Nonnull
private String name;
#Nonnull
private String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
What should I do to load this with all roles in order to select one in my users-view.ts
<vaadin-combo-box label="Rol" id="rol" ${field(this.binder.model.rol)} item-label-path="name"></vaadin-combo-box>
Right now I'getting this
How the combobox shows
Thanks in advance guys.
My Solution was:
added tis lines to my typescrypt class
#state()
private roles: Rol[] = [];
#state from 'lit/decorators.js'
then in the connectedCallback function added this line
this.roles = await RolesEndpoint.listAll();
listAll() is a method that I created on my endpint class.
like this:
#Nonnull
public List<#Nonnull Rol> listAll() {
return service.listAll();
}
and in my service class
public List<Rol> listAll() {
return repository.findAll();
}
Now you can call the data in your combobox element
<vaadin-combo-box .items=${this.roles} label="Rol" id="rol" ${field(this.binder.model.rol)} item-label-path="name" item-value-path="id"></vaadin-combo-box>
I hope this can be helpful.

There is an empty array in the http response body if I just return an array of Java Instances in Spring Boot

I return an array of Java Instances in my Spring-Boot-Get-Started project.
package com.wepay.business.resource;
import com.wepay.business.model.Good;
import com.wepay.business.repo.GoodRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
#CrossOrigin(origins = {"http://localhost:3000", "http://localhost:9000", "http://localhost:8083"})
#RestController
#RequestMapping("/api")
public class GoodResource {
#Autowired
GoodRepository repository;
#GetMapping("/getGood")
public List<Good> getAllGoods() {
List<Good> goods = new ArrayList<>();
repository.findAll().forEach(goods::add);
return goods;
}
}
package com.wepay.business.repo;
import com.wepay.business.model.Good;
import org.springframework.data.repository.CrudRepository;
public interface GoodRepository extends CrudRepository<Good, Long> {
}
package com.wepay.business.model;
import javax.persistence.*;
#Entity
#Table(name = "good")
public class Good {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "name")
private String name;
#Column(name = "price")
private double price;
#Column(name = "img")
private String img;
#Column(name = "info")
private String info;
#Column(name = "amount")
private int amount;
#Column(name = "address")
private String address;
#Column(name = "soldAmount")
private String soldAmount;
#Column(name = "sellerId")
private String sellerId;
public Good(){
}
public Good(String name, Double price, String info, int amount) {
this.name = name;
this.price = price;
this.info = info;
this.amount = amount;
}
public Good(Long id, String goodName, Double unitPrice, String goodInfo, int amount) {
this(goodName, unitPrice, goodInfo, amount);
this.id = id;
}
public void setId(Long id) {
this.id = id;
}
}
The value of goods is an array of Java Instacnes
But there is only an empty array in the http response body.
I guess that I should return an array of JSON objects rather than Java Instances.
Do I need to convert the Java Instances to JSON objects? If so, is there any framework to help us to do this job?
I have been blocked by this issue since last week. Thanks in advance.
The problem resides in the fact that your Good class has no getters (atleast by what I see in your post). Add the getters and this should work.
I think you can use JpaRepository<T, ID> instead of CrudRepository<T, ID> so in this case there's no need to instantiate another List<Good>, because the repository.findAll() already returns List<Good> inside the JpaRepository, although by the way you're doing, it should also work normally.
Do I need to convert the Java Instances to JSON objects? If so, is there any framework to help us to do this job?
No. Spring already do it for you by using Jackson's serializer.
try return repository.findAll();
If there is no specific reason to use CrudRepository you can change it to JpaRepository
By doing this you can avoid conversion of Iterator to List and use like this.
public interface GoodRepository extends JpaRepository<Good, Long> {
}
// Controller
#GetMapping("/getGood")
public List<Good> getAllGoods() {
return repository.findAll();
}
Also, Make sure Getter Setter is in place for each persistable field.

By default, don't expose field in Entity class, using Spring Data Rest and Jpa

I have an entity class Account. It has a bunch of fields. Most of them for now are exposed in REST calls except where I explicitly ignore the password field with #JsonIgnore, but I will be adding more fields and I don't want to forget adding #JsonIgnore to something new that shouldn't be exposed.
Can I invert the exposure, so that I explicitly have to enable fields to be exported, with the default being that it won't be exposed?
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.Data;
import lombok.ToString;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Data
#ToString(exclude = "password")
#Entity
public class Account {
public static final PasswordEncoder PASSWORD_ENCODER = new BCryptPasswordEncoder();
private #Id #GeneratedValue Long id;
private String name;
#JsonIgnore private String password;
private String[] roles;
public void setPassword(String password) {
this.password = PASSWORD_ENCODER.encode(password);
}
protected Account() {}
public Account(String name, String password, String... roles) {
this.name = name;
this.setPassword(password);
this.roles = roles;
}
}
Using Spring Data REST here, so everything else that is there is just repositories, there is no extra layer to do something smart.
There is two main ways to get the "white-list" properties effect in Jackson library
First Way:
Remove #Data annotation from your Account class and add getters only to fields you want to expose. To make sure that properties without getters will not be excludes add #JsonIgnoreProperties(ignoreUnknown=true) to your Account class
Second Way:
Wrap your Account class with AccountForJson class. for example :
public class AccountForJson {
private Account account;
public MyClassForJson(Account accountToWrapped) {
this.account = accountToWrapped;
}
/**
* Example of property that you want to expose
*/
public String getName() {
return this.account.getName();
}
}
p.s : there is an open issuse in Jackson github repository for that feature, here is the link for watching that issuse - Add #JsonIncludeProperties(propertyNames) (reverse of #JsonIgnoreProperties)

how to make two column as a primary key in hibernate annotation class

This is my annotation class and i want userId and groupId column both as primary key.
I have found more questions (Question) about this, but didn't found relevant answer.
I have less reputation, so I am not able to comment on posts, So I am putting my question here.
This is my code..
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.NaturalId;
#Entity
#Table(name="user_group")
public class user_group {
#Column(name="serviceProvider")
private String serviceProvider;
#Column(name="enterpriseId")
private String enterpriseId;
#Column(name="department")
private String department;
#Column(name="trunkGroupName")
private String trunkGroupName;
#Id
#Column(name="userId")
private String userId;
#Column(name="groupId")
private String group;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getServiceProvider() {
return serviceProvider;
}
public void setServiceProvider(String serviceProvider) {
this.serviceProvider = serviceProvider;
}
public String getEnterpriseId() {
return enterpriseId;
}
public void setEnterpriseId(String enterpriseId) {
this.enterpriseId = enterpriseId;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getTrunkGroupName() {
return trunkGroupName;
}
public void setTrunkGroupName(String trunkGroupName) {
this.trunkGroupName = trunkGroupName;
}
}
You should create a new #Embeddable class containing the PK fields:
#Embeddable
public class user_groupId implements Serializable {
#Column(name="userId")
private String userId;
#Column(name="groupId")
private String group;
}
And use it in the #Entity as an #EmbeddedId:
#Entity
public class user_group {
#EmbeddedId
user_groupId id;
...
}
You could also use the #IdClass annotation to that effect.
This excellent answer by Pascal Thivent elaborates on the details. You can also take a look at this other answer I posted to a almost identical question some time ago.
As a side note, if you've got control over the DB structure, you might also consider avoiding composite keys. There are some reasons to do so.
you can create a composite primary key in hibernate using #UniqueConstraint annotation.
#Table(name="user_group",uniqueConstraints=#UniqueConstraint(columnNames= {"userId","groupId"}))
public class user_group
{
#Column(name="userId")
private String userId;
#Column(name="groupId")
private String group;
}
above method is not feasible if we use spring because for creating composite primary key we have to create a class is not a good thing.
in hibernate and spring you only have to create POJO classes which are available as an entity on your system.

How to define index by several columns in hibernate entity?

Morning.
I need to add indexing in hibernate entity. As I know it is possible to do using #Index annotation to specify index for separate column but I need an index for several fields of entity.
I've googled and found jboss annotation #Table, that allows to do this (by specification). But (I don't know why) this functionality doesn't work. May be jboss version is lower than necessary, or maybe I don't understant how to use this annotation, but... complex index is not created.
Why index may not be created?
jboss version 4.2.3.GA
Entity example:
package somepackage;
import org.hibernate.annotations.Index;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
#Entity
#org.hibernate.annotations.Table(appliesTo = House.TABLE_NAME,
indexes = {
#Index(name = "IDX_XDN_DFN",
columnNames = {House.XDN, House.DFN}
)
}
)
public class House {
public final static String TABLE_NAME = "house";
public final static String XDN = "xdn";
public final static String DFN = "dfn";
#Id
#GeneratedValue
private long Id;
#Column(name = XDN)
private long xdn;
#Column(name = DFN)
private long dfn;
#Column
private String address;
public long getId() {
return Id;
}
public void setId(long id) {
this.Id = id;
}
public long getXdn() {
return xdn;
}
public void setXdn(long xdn) {
this.xdn = xdn;
}
public long getDfn() {
return dfn;
}
public void setDfn(long dfn) {
this.dfn = dfn;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
When jboss/hibernate tries to create table "house" it throws following exception:
Reason: org.hibernate.AnnotationException: #org.hibernate.annotations.Table references an unknown table: house
Please try the following:
#Entity
#org.hibernate.annotations.Table(appliesTo = House.TABLE_NAME,
indexes = {
#Index(name = "IDX_XDN_DFN",
columnNames = {House.XDN, House.DFN}
)
}
)
#Table(name="house")
public class House {
...
}
Note that this should also allow you to create a multi-column index (based on the index name):
#Index(name = "index1")
public String getFoo();
#Index(name = "index1")
public String getBar();
P.S.: What version of Hibernate are you using BTW? What database/dialect?
You have to have hibernate.hbm2ddl.auto set to create in persistence.xml. When set to update hibernate won't create indexes.
hibernate.hbm2ddl.auto = create
You'd better go with a composite primary key.
This article explains how to do it with JPA annotations. It uses #Embeddable and #EmbeddedId

Categories

Resources