Spring RestController ignoring #jsonProperty/JsonGetter/JsonSetter - jackson

I am using Springboot 2.1.2.RELEASE. I have a get request with an object as input parameter. Expecting the attributes in my class to be request parameters. My EmployeeBean has properties in java naming convention. But I need the custom names to request parameters. Tried to achieve that using #JsonProperty/ #Jsongetter/ #JsonSetter annotations but its not working. Am I missing something?
#RequestMapping(value="/api", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE )
public List<Map<String, Object>> getEmployeeData(EmployeeBean employeeBean
#Data
public class EmployeeBean implements Serializable {
private static final long serialVersionUID = -2757478480787308113L;
#JsonProperty(value="first_name")
private String firstName;
#JsonProperty(value="last_name")
private String lastName;

Try this,
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#JsonProperty(value="first_name")
public void setFirst_name(String firstName) {
this.firstName = firstName;
}
#JsonProperty(value="last_name")
public void setLast_name(String lastName) {
this.lastName = lastName;
}
controller
#RestController
public class JsonController {
#RequestMapping(value="/api", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE )
public List<Map<String, Object>> getEmployeeData(EmployeeBean employeeBean) {
System.out.println("employeeBean: "+employeeBean);
return null;
}
}
result:
employeeBean: EmployeeBean [firstName=firstName10, lastName=lastName20]
I've tested and it's worked
other options, using JsonCreator in constructor:
private String firstName;
private String lastName;
#JsonCreator
public EmployeeBean(#JsonProperty("first_name") String first_name, #JsonProperty("last_name") String last_name) {
this.firstName = first_name;
this.lastName = last_name;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}

Related

Resteasy - Multiple resource methods match request "POST /.../..."

I am doing a REST API with Java Resteasy framework (using Jackson as well).
I was trying to define 2 api endpoints almost equal:
#POST
#Path("/addbook")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
public BookAdvanced addBook (BookAdvanced book){...}
#POST
#Path("/addbook")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
public Book addBook (Book book){...}
Is this possible? What I want is, depending on the xml arriving execute one or the other method
Here book class:
package package1;
import javax.xml.bind.annotation.*;
import java.util.Date;
#XmlRootElement(name = "book")
public class Book {
private Long id;
private String name;
private String author;
#XmlAttribute
public void setId(Long id) {
this.id = id;
}
#XmlElement(name = "title")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "author")
public void setAuthor(String author) {
this.author = author;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
// constructor, getters and setters
}
Here BookAdvanced class:
package package1;
import javax.xml.bind.annotation.*;
import java.util.Date;
#XmlRootElement(name = "book")
public class BookAdvanced {
private Long id;
private String name;
private String author;
private int year;
#XmlAttribute
public void setId(Long id) {
this.id = id;
}
#XmlElement(name = "title")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "author")
public void setAuthor(String author) {
this.author = author;
}
#XmlElement(name = "year")
public void setYear(int year) {
this.year = year;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
public int getYear() {
return year;
}
// constructor, getters and setters
}
27-Jan-2023 12:33:18.238 WARN [http-nio-8080-exec-39] org.jboss.resteasy.core.registry.SegmentNode.match RESTEASY002142: Multiple resource methods match request "POST /hello/addbook". Selecting one. Matching methods: [public package1.BookAdvanced prova_gradle_war.HelloWorldResource.addBook(package1.BookAdvanced), public package1.Book prova_gradle_war.HelloWorldResource.addBook(package1.Book)]
Matching is based on the request URI and not the request body. There is no real way to match the path and decide the method to use based on the body.
You could do something manually where you inspect the data and determine which type to create.

JavaFX how i can set Image to my Student (model) from SQL database?

Student Model--
Which code I must write to set photo type in the Student?
package mh.st.model;
import java.sql.Date;
import java.time.LocalDate;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.image.Image;
public class Student {
private IntegerProperty id;
private StringProperty firstName;
private StringProperty lastName;
private StringProperty fatherName;
private IntegerProperty ID;
private StringProperty phone;
private StringProperty birthday;
private ObjectProperty<Image>photo;
public Student()
{
}
public Student(int id,String firstName,String lastName,String fatherName,int ID,String phone,String birthday,Object photo)
{
this.id=new SimpleIntegerProperty(id);
this.firstName=new SimpleStringProperty(firstName);
this.lastName=new SimpleStringProperty(lastName);
this.fatherName=new SimpleStringProperty(fatherName);
this.ID=new SimpleIntegerProperty(ID);
this.phone=new SimpleStringProperty(phone);
this.birthday=new SimpleStringProperty(birthday);
}
public IntegerProperty getId() {
return id;
}
public StringProperty getFatherName() {
return fatherName;
}
public void setFatherName(String fatherName) {
this.fatherName =new SimpleStringProperty(fatherName);
}
public StringProperty getFirstName() {
return firstName;
}
public StringProperty getLastName() {
return lastName;
}
public IntegerProperty getID() {
return ID;
}
public StringProperty getPhone() {
return phone;
}
public StringProperty getBirthday() {
return birthday;
}
public void setFirstName(String firstName) {
this.firstName =new SimpleStringProperty(firstName);
}
public void setLastName(String lastName) {
this.lastName =new SimpleStringProperty(lastName);
}
public void setID(Integer ID) {
this.ID =new SimpleIntegerProperty(ID);
}
public void setPhone(String phone) {
this.phone =new SimpleStringProperty(phone);
}
public void setBirthday(String birthday) {
this.birthday =new SimpleStringProperty(birthday);
}
}

Are custom classes in Java mutable by default?

I've been reading up on encapsulation and was wondering; if I make a new class, is it by default mutable?
If so, how would I go about making it an immutable class, if possible, without just doing defensive copying?
Thanks.
It depends on what you put in the class.
public class MutableClass {
private String firstName;
public MutableClass(String s) {
firstName = s;
}
public String getFirstName() {
return firstName;
}
// this allows mutation...
public void setFirstName(String s) {
firstName = s;
}
}
public class ImmutableClass {
private String firstName;
public MutableClass(String s) {
firstName = s;
}
public String getFirstName() {
return firstName;
}
}
That doesn't account of things like setAccessible with reflection, but I expect that is not what you are concerned about.
I hope that helps.

HQL query for the unary table

I have an user_info table as below
As you see the supervisor column refers the same table.
I am using the Netbean for my development. My POJO created the following class
package database.hibernate_pojo;
// Generated May 31, 2013 12:50:13 AM by Hibernate Tools 3.2.1.GA
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
/**
* UserInfo generated by hbm2java
*/
#Entity
#Table(name="user_info"
,catalog="bit_final_year_project"
, uniqueConstraints = #UniqueConstraint(columnNames="user_name")
)
public class UserInfo implements java.io.Serializable {
private Integer userId;
private UserInfo userInfo;
private String userName;
private String firstName;
private String secondName;
private char department;
private String password;
private char privilege;
private int invalidLogin;
private char status;
private String signaturePath;
private Set<Shipping> shippings = new HashSet<Shipping>(0);
private Set<Audit> audits = new HashSet<Audit>(0);
private Set<UserInfo> userInfos = new HashSet<UserInfo>(0);
public UserInfo() {
}
public UserInfo(String userName, String firstName, String secondName, char department, String password, char privilege, int invalidLogin, char status) {
this.userName = userName;
this.firstName = firstName;
this.secondName = secondName;
this.department = department;
this.password = password;
this.privilege = privilege;
this.invalidLogin = invalidLogin;
this.status = status;
}
public UserInfo(UserInfo userInfo, String userName, String firstName, String secondName, char department, String password, char privilege, int invalidLogin, char status, String signaturePath, Set<Shipping> shippings, Set<Audit> audits, Set<UserInfo> userInfos) {
this.userInfo = userInfo;
this.userName = userName;
this.firstName = firstName;
this.secondName = secondName;
this.department = department;
this.password = password;
this.privilege = privilege;
this.invalidLogin = invalidLogin;
this.status = status;
this.signaturePath = signaturePath;
this.shippings = shippings;
this.audits = audits;
this.userInfos = userInfos;
}
#Id #GeneratedValue(strategy=IDENTITY)
#Column(name="user_id", unique=true, nullable=false)
public Integer getUserId() {
return this.userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="supervisor")
public UserInfo getUserInfo() {
return this.userInfo;
}
public void setUserInfo(UserInfo userInfo) {
this.userInfo = userInfo;
}
#Column(name="user_name", unique=true, nullable=false, length=12)
public String getUserName() {
return this.userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
#Column(name="first_name", nullable=false, length=15)
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
#Column(name="second_name", nullable=false, length=15)
public String getSecondName() {
return this.secondName;
}
public void setSecondName(String secondName) {
this.secondName = secondName;
}
#Column(name="department", nullable=false, length=1)
public char getDepartment() {
return this.department;
}
public void setDepartment(char department) {
this.department = department;
}
#Column(name="password", nullable=false, length=45)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name="privilege", nullable=false, length=1)
public char getPrivilege() {
return this.privilege;
}
public void setPrivilege(char privilege) {
this.privilege = privilege;
}
#Column(name="invalid_login", nullable=false)
public int getInvalidLogin() {
return this.invalidLogin;
}
public void setInvalidLogin(int invalidLogin) {
this.invalidLogin = invalidLogin;
}
#Column(name="status", nullable=false, length=1)
public char getStatus() {
return this.status;
}
public void setStatus(char status) {
this.status = status;
}
#Column(name="signature_path", length=45)
public String getSignaturePath() {
return this.signaturePath;
}
public void setSignaturePath(String signaturePath) {
this.signaturePath = signaturePath;
}
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="userInfo")
public Set<Shipping> getShippings() {
return this.shippings;
}
public void setShippings(Set<Shipping> shippings) {
this.shippings = shippings;
}
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="userInfo")
public Set<Audit> getAudits() {
return this.audits;
}
public void setAudits(Set<Audit> audits) {
this.audits = audits;
}
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="userInfo")
public Set<UserInfo> getUserInfos() {
return this.userInfos;
}
public void setUserInfos(Set<UserInfo> userInfos) {
this.userInfos = userInfos;
}
}
I want to show the name of the supervisor in my application. I have written the SQL command it worked perfectly in the Workbench.
select e.user_name from user_info e, user_info s where e.user_id=s.supervisor
But the issue was when I tried to write it in HQL there is no respective methods were created by the Netbean in UserInfo class.
Can anyone help me out of this issue to find a solution?
I've found the solution for my issue by my own. It's simply object within another object. Thus I need to query the first object, then the second object can be accessed
public Iterator getCustomSupervisor(){
String hqlQuery = "FROM UserInfo";
Query query = session.createQuery(hqlQuery);
while(query.list().iterator().hasNext()){
//the first object
UserInfo ui = (UserInfo) query.list().iterator().next();
//access the second object
System.out.println(ui.getUserInfo().getUserName());
}
}

Filter nested objects using Jackson's BeanPropertyFilter

I have the following objects:
#JsonFilter("myFilter")
public class Person {
private Name name;
private int age;
public Name getName() {return name;}
public void setName(Name name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
#JsonFilter("myFilter")
public class Name {
private String firstName;
private String lastName;
public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}
}
I wrote a method to marshall a Person object like this:
#Test
public void test() throws Exception {
Person person = new Person();
person.setAge(10);
Name name = new Name();
name.setFirstName("fname");
name.setLastName("lastname");
person.setName(name);
ObjectMapper mapper = new ObjectMapper();
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name.firstName"));
System.out.println(mapper.filteredWriter(filters).writeValueAsString(person));
}
What I'd like to see is JSON like this:
{"name":{"firstName":"fname"}}
Is something like that possible?
Ok, figured it out. Varargs would have made this a bit prettier, but oh well. Just hope I don't have two inner beans which have properties with the same name. I wouldn't be able to make the distinction between the two
FilterProvider filters = new SimpleFilterProvider()
.addFilter("myFilter", SimpleBeanPropertyFilter
.filterOutAllExcept(new HashSet<String>(Arrays
.asList(new String[] { "name", "firstName" }))));
There's a better way that solves problem with property name conflicts. Just add another filter to class Name ("nameFilter"):
#JsonFilter("personFilter")
public class Person {
private Name name;
private int age;
public Name getName() {return name;}
public void setName(Name name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
#JsonFilter("nameFilter")
public class Name {
private String firstName;
private String lastName;
public String getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
public String getLastName() {return lastName;}
public void setLastName(String lastName) {this.lastName = lastName;}
}
And then add 2 filters, one for Person and one for Name:
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("personFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name"))
.addFilter("nameFilter", SimpleBeanPropertyFilter.filterOutAllExcept("firstName"));