Assume I have an User object:
public class User {
private Long id;
private String name;
private String surname;
// getters + setters
}
When creating a User through SOAP, I want the user to input only the name and surname but not the id. In this case, should I create something like UserDTO object? For example:
public class UserDTO {
private String name;
private String surname;
// getters + setters
}
In my service bean, I will have the following method:
public void updateUser (Long id, UserDTO dto) {
User user = new User(id, dto.getName(), dto.getSurname());
service.updateUser(user);
}
Will this be a correct approach to my question? Thank you
I'm not sure if I understand your question right but why don't you just provide second constructor for your User class?
It will be:
public class User {
private Long id;
private String name;
private String surname;
//in case of creating user manually
public User(Long id, String name, String surname) {
this.id = id;
this.name = name;
this.surname = surname;
}
//in case of creating user via soap:
public User(String name, String surname) {
this.id = generateId(); //or some other logic to specify users id
this.name = name;
this.surname = surname;
}
}
Related
I converted UUID to string (String id) and put the conversion inside a method.
I also declared other String variables such as FirstName etc and put in on an ArrayList:
Code
The code does work. But I'm confused why the string email was showing second on the list.
public class StudentController {
#Autowired
StudentService studentService = new StudentService();
#GetMapping
public List<Student> displayStudent(){
return studentService.getStudent();
}
}
public class StudentService {
Student student = new Student();
private List<Student> studentList = Arrays.asList(
new Student(student.genID(),"Elvis" , "Presley" ,"Elvis#gmail.com")
);
public List<Student> getStudent(){
return studentList;
}
}
public class Student {
UUID uuid = UUID.randomUUID();
private String id;
private String FirstName;
private String LastName;
private String email;
public Student() {}
//Method Converting UUID into string
public String genID(){
id = uuid.toString();
return id;
}
public Student(String id) {
this.id = id;
}
public Student(String id, String firstName, String lastName, String email) {
this.id = id;
FirstName = firstName;
LastName = lastName;
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return FirstName;
}
public void setFirstName(String firstName) {
FirstName = firstName;
}
public String getLastName() {
return LastName;
}
public void setLastName(String lastName) {
LastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Expected
I expected data to be in this order
ID , FirstName , LastName , email
Actual Output JSON
JSON is an unordered collection, as specified on https://www.json.org/json-en.html , so you don't have to worry about it. It might depend on library though.
Specify the serialized order of properties
The order of properties during serialization can be defined in Jackson.
Either at class-level specifically using annotation #JsonPropertyOrder.
Or globally for your ObjectMapper using a feature:
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
Example
In your case you can achieve expected order using the annotation on your class:
#JsonPropertyOrder({'id', 'firstName', 'lastName', 'email'})
public class Student {
// body of your class
}
Or separately with an index on your fields:
public class Student {
#JsonProperty(index=10)
private String id;
// not ordered specifically
private String firstName;
private String lastName;
#JsonProperty(index=20)
private String email;
// remainder of your class
}
See also
Jackson ObjectMapper - specify serialization order of object properties
Order of JSON objects using Jackson's ObjectMapper
Jackson JSON - Using #JsonPropertyOrder annotation to define serialized properties ordering
I have written three Java classes:
Company
Department
Employee
Each Company object contains an array of Department objects, which in turn contain arrays of Employee objects.
I want to write a method in the Employee class setQid() which will set a unique ID for that employee in the following format:
compName_deptName_deptNumber_empFirstName_empSurname
Example:
"Microsoft_Accounting_3_John_Smith"
My question is: how can I access the following variables from the context of my Employee class?
String name in Company
String name in Department
int number in Department
Please see my code below:
public class Company {
private String name;
private Department[] departments;
public Company(String name, Department[] departments) {
this.name = name;
this.departments = departments;
}
}
public class Department {
private String name;
private int number;
private Employee[] members;
public Department(String name, int number, Employee[] members) {
this.name = name;
this.number = number;
this.members = members;
}
}
public class Employee {
private String firstname;
private String surname;
private String qid; //A unique employee ID
public Employee(String firstname, String surname) {
this.firstname = firstname;
this.surname = surname;
setQid();
}
public void setQid() {
// How can I access the Company name, Department name, and Department number from here?
}
}
You need to have a reference for the Department in your Employee class and a reference for the Company in your Department, only then will your relationships amongst your entities will be complete.
public class Company {
private String name;
private Department[] departments;
public Company(String name, Department[] departments) {
this.name = name;
this.departments = departments;
}
//add getters and setters
}
public class Department {
private String name;
private int number;
private Employee[] members;
private Company company;
public Department(String name, int number, Employee[] members) {
this.name = name;
this.number = number;
this.members = members;
}
//add getters and setters
}
public class Employee {
private String firstname;
private String surname;
private String qid; //A unique employee ID
private Department department;
public Employee(String firstname, String surname) {
this.firstname = firstname;
this.surname = surname;
setQid();
}
public void setQid() {
qid = department.getCompany().getName + "_" + department.getName() ....
}
//add getters and setters
}
I have a User class which saves some extra data on the user. This data is stored in/coming from Firestore. I have a couple of fields which are working(name, surname, lastLogin) but a couple of them are not working(blocked).
When I make the field public they work, but when I try to use a setter, it doesn't. I tried cleaning the build and rebuilding it. I know it is not saving the field due to #Exclude, that is intended.
What am I doing wrong? The field type doesn't matter, I've added a new String field which gave the same warning, while name and surname work.
The database:
**userid**
{
"name" : "John",
"surname" : "Doe",
"lastLogin" : **timestamp**,
"blocked" : true
}
The class:
#Keep
public class User
{
private String name;
private String surname;
private Date lastLogin;
private boolean blocked = false;
public User()
{
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getSurname()
{
return surname;
}
public void setSurname(String surname)
{
this.surname = surname;
}
public Date getLastLogin()
{
return lastLogin;
}
public void setLastLogin(Date lastLogin)
{
this.lastLogin = lastLogin;
}
#Exclude
public boolean isBlocked()
{
return blocked;
}
public void setBlocked(boolean blocked)
{
this.blocked = blocked;
}
The problem in your code is that the constructor in the User class is private. That's not the correct way in which you should create a new instance of the class. JavaBeans require a no-argument constructor to be present.
When Cloud Firestore SDK deserializes objects that are coming from the database, it requires that any objects in use, to have this public no-argument constructor, so it can use it to instantiate the object. Fields in the objects are set by using public setter methods or direct access to public members, as you already tried.
Because your constructor is private, the SDK doesn't really know how to create an instance of it. So it is mandatory to change it as public. A correct way to create that class should be:
class User {
private String name;
private String surname;
private long lastLogin;
private boolean blocked = false;
public User() {} //Needed for Cloud Firestore
public User(String name, String surname, long lastLogin, boolean blocked) {
this.name = name;
this.surname = surname;
this.lastLogin = lastLogin;
this.blocked = blocked;
}
//Getters and setters are not mandatory
}
Also please note that the setters and the getters are not required. Setters are always optional because if there is no setter for a JSON property, the Firebase client will set the value directly onto the field.
Edit:
According to your comment:
but it does not explain why some fields are working and others aren't. It should not work at all, right?
Yes, that's right, all should work. The reason why some of them are not working is that the blocked property in your User class is of type boolean while in your database is of type String and this is not correct. Both types must match.
And the private constructor is due to the singleton instance, as far as I know, the constructor should be private to avoid creating new instances of the class.
No, the constructor must be public. I think there is a misunderstanding. Every time you use FirebaseDatabase.getInstance(), a single socket connection between your application and the Firebase servers is opened. From that moment on, all traffic between the application and the database goes over the same socket. So it doesn't matter how many times you create an instance, it will always be a single connection. Regarding your POJO class, there is no need for such a Singleton because Firebase always needs to know how to create an instance of that class, using the public no-argument constructor.
Try to create a constructor with parameters for all class attributes along with a non-parameter constructor and then in the java class where you store in firebase, create object from user and pass it.
for example:
package com.example.spacing.Model;
public class User {
private String username;
private String phone;
private String id;
private String imageURL;
private String email;
public User(String username, String email ,String phone, String id, String imageURL) {
this.username = username;
this.email=email;
this.phone = phone;
this.id = id;
this.imageURL = imageURL;
}
public String getImageURL() {
return imageURL;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public User() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
and
FirebaseDatabase.getInstance().getReference("Users")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.setValue(user);
You can try to add #field:JvmField to your boolean variable inside your User class.
So in the app I'm creating I have a user class defined as the following
public class User implements Serializable{
private int id;
private String username;
private String firstName;
private String lastName;
private String email;
private String password;
private String picture;
private ArrayList<String> tags;
private double rating;
private Category favorite;
private boolean star;
private Location homeLocation;
public User(int id, String username, String firstName,String lastName,String picture, ArrayList<String> tags,double rating, Category favorite, boolean star,Location homeLocation,String email,String password) {
this.id = id;
this.username = username;
this.firstName = firstName;
this.lastName = lastName;
this.picture = picture;
this.tags = tags;
this.rating = rating;
this.favorite = favorite;
this.star = star;
this.homeLocation = homeLocation;
this.email = email;
this.password = password;
}
public int getId() {
return id;
}
public String getUsername() {
return username;
}
public String getFirstName() {
return firstName;
}
public String getLastName(){ return lastName;}
public String getPicture(){ return picture;}
public ArrayList<String> getTags() {
return tags;
}
public double getRating(){ return rating;}
public Category getFavorite(){ return favorite;}
public Boolean getStar(){ return star;}
public Location getHomeLocation(){return homeLocation;}
public String getEmail(){return email;}
public String getPassword(){return password;}
public void setId(int id){
this.id = id;
}
Now, when I create a User object I pass an ArrayList<String> tags which, when logged, shows just as intended.
List<String> listTags = Arrays.asList(DummyTags.tagsNewUser);
ArrayList<String> tags = new ArrayList<>();
tags.addAll(listTags);
Log.d("Tags",tags.toString());
user = new User(0,userName,firstName,lastName,picturePlaceHolder,tags,4,category,true,loc,email,password);
However, when I use this user object in, say a profile page, and retrieve the users tags through the getter in the class it always returns null.
user = (User) getArguments().getSerializable("User");
tags = user.getTags();
Doing this always has tags be null, no matter what ArrayList I pass when creating the user object.
I also get a warning in android studio saying that invoking user.getTags() may produce a npe. Every other part of the user model works just fine. I have tried to solve this for a while now and have not been able to find anything relating to my problem so any help would be appreciated!
Try:
Bundle bundle=new Bundle();
bundle.putStringArrayList("tags",tags);
bundle.putSerializable("User",user);
and then retrieve as:
tags = getArguments().getStringArrayList("tags");
The reason that your solution does not work is that ArrayList is not implementing Serializable interface
So basically I want to get the store which a Person is in? Here is the Pojo code for the store ;
#Entity
public class Store{
#Id
Long StoreId;
String Name;
String Address;
#Index List<Key<Person>> Members;
private House() {
}
public Store(Long StoreId ,String Name, String Address) {
StoreId = StoreId;
this.Name = Name;
this.Address = Address;
Members = new ArrayList<Key<Person>>();
}
public Long getId() {
return StoreId;
}
public String getName() {
return Name;
}
public void setName(String name) {
this.Name = name;
}
public String getAddress() {
return Address;
}
public void setAddress(String postcode) {
this.Address = Address;
}
public void AddToStore(Key<Person> person) {
Members.add(person);
}
Here is the code that Creates a store and adds in the current signed in user (Google login)
/**
* Inserts a new {#code Store}.
*/
#ApiMethod(
name = "insert",
path = "Store",
httpMethod = ApiMethod.HttpMethod.POST)
public House insert(User user) throws UnauthorizedException {
if (user == null){
throw new UnauthorizedException("You need to authorisation");
}
String tempName = "cottages";
String tempAddress = "Gogoland";
String userId = user.getUserId();
Key<Person> personKey = Key.create(Person.class, userId);
final Key<Store> storeKey = OfyService.factory().allocateId(Store.class);
final Long StoreId = storeKey.getId();
Store h = new Store(StoreId , tempName,tempAddress);
h.AddToStore(personKey);
ofy().save().entity(h).now();
logger.info("Created Store.");
return ofy().load().entity(h).now();
}
So the relationship between Store to person is one to many as you can see. So i want to be able to get the Current house of the logged in user and in turn retrieve the other "person"/members entities also in the object. Furthermore i would wish to also retrieve the "children" of the "Person" entities on the same store as the current user.
Furthermore How would it be possible to invite other people to join the users store via email?
Any help is appreciated.
You should filter by key since you have an index:
return ofy().load().filter("Members", personKey).first().now();
However if you already saved the entity with the .save() method, you can simply do this:
return h;