Consider the following class.
public class UserDTO {
private String email;
private String password;
private String country;
private String fName;
private String lName;
private String type;
private String profPicPath;
public UserDTO(String fNme, String lNme, String profPic) {
this.setfName(fNme);
this.setlName(lNme);
this.setProfPicPath(profPic);
}
public String getEmail() {
return email;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getfName() {
return fName;
}
public void setfName(String fName) {
this.fName = fName;
}
public String getlName() {
return lName;
}
public void setlName(String lName) {
this.lName = lName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getProfPicPath() {
return profPicPath;
}
public void setProfPicPath(String profPicPath) {
this.profPicPath = profPicPath;
}
I want to create an object only contains the fName, Lname and profPicPath. I have created a constructor to initialize only these three fields. But when I create an object using this constructor it contains the other properties as well with null values. Is there any approach in Java to create an object only with a selected properties ?
I think you are confused between the domain/model object and DTO object. The domain/model class represents the full set of attributes while you specific DTOs representing subsets of attributes in the domain/model class e.g. the User class is your domain/model class representing the full set of attributes (email, password, country, fName, lName, type, gender, country, profPicPath etc.) and then you can have DTOs like, UserLoginCredentialDTO (with email and password attributes), UserDemographyDTO (with attributes like gender, country etc.).
You can also check https://softwareengineering.stackexchange.com/questions/155768/what-oo-design-to-use-is-there-a-design-pattern for another example.
Apart from this, the comments of JB Nizet and Abra are quite valid and will help you understand this concept better in terms of Java.
yes. the approach is called inheritance. You need to create a BaseUserDTO that contains the subset of properties that is shared between the two entities. (they need to be declared as protected to be accessible to the subclass) UserDTO will extend the base class so it contains all its properties plus its own. the constructor with three properties must call the matching super constructor in order to initialize the shared properties
Related
This question already has answers here:
Why use getters and setters/accessors?
(37 answers)
Closed 1 year ago.
Recently I was going through the concept of Encapsulation in Java. I was wondering if making data variables private along with public setter methods really make sense in simple POJO class? Please refer below POJO:
public class Employee{
private String id;
private String name;
private String department;
private int age;
public Employee(){
}
public Employee(String id, String name, String department, int age){
this.id = id;
this.name = name;
this.department = department;
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
I mean why am I making the name variable private when I can anyway change it using the setter method?
In the general case, it'll be the very basic
public void setName(String name) {
this.name = name;
}
Where it's identical to just doing employee.name = "william hammond". But imagine a case where you'd like to do implement something like a private String normalize(string username) method where you maybe make it all lower case, check for a valid name or prevent unicode entries. If you make name public initially you'll have users doing employee.name = "whatever they want :) 123" and you'll lose the ability to enforce that constraint.
Also see Why use getters and setters/accessors?
Using getters/setters is just considered good practice, but it can often be overkill - like in your example.
If you have methods that mutate the variable before setting, then it's nice to have getters/setters for the basic fields as well to maintain consistent code style.
Here's a good article on it:
https://dzone.com/articles/getter-setter-use-or-not-use-0
Let's have an example:
public class Example {
private String firstName;
private String lastName;
public Example(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getFullName() {
return firstName + " " + lastName;
}
}
This class has 3 properties (firstName, lastName, fullName), but only two fields (firstName, lastName). It makes sense, because a full name can be retrieved by combining first and last name.
However, I've noticed that I call getFullName() a lot of times in my program, but I almost never call getFirstName() and getLastName(). This slows down my program, because I need to create a new string each time getFullName() is called. So, I've refactored my code to have a better performance:
public class Example {
private String fullName;
public Example(String firstName, String lastName) {
this.fullName = firstName + " " + lastName;
}
public String getFirstName() {
return fullName.split(" ")[0];
}
public String getLastName() {
return fullName.split(" ")[1];
}
public String getFullName() {
return fullName;
}
}
Now my code works faster when calling getFullName(), but slower when calling getFirstName() and getLastName(), however It's exactly what I needed. From outside the class, nothing really've changed.
As you can see by the given example, fields describe how your class uses the computer's memory, but not necessarily which properties your class has. This is why fields should be considered an implementation detail and therefore be private to a class.
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.
Suppose I have two classes.
public class User {
private String userName;
private String age;
private Address address;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
public class Address {
private String city;
private String country;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
I want to set city and country of user using java reflection.
parameter map looks like
address.city=COLOMBO
address.country=SRI LANKA.
what is the best way to access address properties inside user object using java reflection.
Since I am going to create object through CSV.
So when user send attribute with dot (.) its means its object inside another object.
I want to write global reflection method to use through out the application.
One method to create object using CSV
The best way would be to create a new Address object, and then call the setters for this object and finally call the setAddress for the user.
The best pattern of use doesn't change because you are using reflection. I suggest you do the same thing but using reflection.
I think using reflection for that is not the best way. Anyway, as Peter tell you in the first answer, you should create a new object and assign it using the setter.
I defined an object "User" in server and client end. The "User" in server end only has a constructor and getter and setter, but the one in client end has some other method.
My project structure is following:
Project structure
The code is following:
The server:
class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String password;
private String role;
User(String name, String password, String role) {
this.setName(name);
this.setPassword(password);
this.setRole(role);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String toString() {
return this.name + this.password + this.role;
}
}
The client:
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String password;
private String role;
User(String name, String password, String role) {
this.name = name;
this.password = password;
this.role = role;
}
/*=====================getter and setter========================*/
public void set(String name, String password, String role) {
this.name = name;
this.password = password;
this.role = role;
}
public String get() {
return this.name + " " + this.password + " " + this.role;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword() {
return this.password;
}
public void setRole(String role) {
this.role = role;
}
public String getRole() {
return this.role;
}
/*==================Method===================*/
public void showMenu(String title) {
}
}
And I want to send a User object from client to server. But an ClassNotFoundException is thrown.
java.lang.ClassNotFoundException: pers.yangxujie.RecordMangerServer.main.User
Why? Do I have to user the same "User" object?(But I have to define them in both ends, because it is c/s model)
Based on what you have shown us, I think that the problem is that there is no class called pers.yangxujie.RecordMangerServer.main.User on the classpath on the server side.
If the problem was due to differences in the versions of the class on the client and server side, then I would expect to see different exceptions. It is (IMO) generally a bad idea to use different versions of a class when serializing and deserializing, because the differences can cause all sorts of problems (if you are not careful). However, sometimes this is unavoidable.
The class should be the same on both ends. Not different classes with the same name. Here 'same' means same name, same package, same serialVersionUID.
If you really know what you're doing, the classes can have minor disagreements about their fields, subject to the provisions of the Versioning chapter of the Object Serialization Specification: this can be handy as a solution to a deployment problem where you can't update server and client at the same time.
However it doesn't make sense to set out from the beginning to have two different classes called User in the same system. In this case it strongly appears that they are in different packages, which makes them different classes. This will not work for Serialization purposes.
Is the server class in its own separate file? Make sure neither one of them is an inner class
This question already has answers here:
How to serialize object to CSV file?
(8 answers)
Closed 9 years ago.
what would be the best way to have information in a JavaBean be put into a CSV file? I am making a registration page and have set all the parameters of my User JavaBean through a JSP page using I need to store this information into a csv from a servlet everytime someone registers so I can retrieve this information when they use the login JSP page.
Here is my JavaBean
package bean.user;
public class User_profile {
private String First_Name;
private String Last_Name;
private String ssn;
private String birthday;
private String home_phone;
private String password;
private String gender;
private String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFirst_Name() {
return First_Name;
}
public void setFirst_Name(String first_Name) {
First_Name = first_Name;
}
public String getLast_Name() {
return Last_Name;
}
public void setLast_Name(String last_Name) {
Last_Name = last_Name;
}
public String getSsn() {
return ssn;
}
public void setSsn(String ssn) {
this.ssn = ssn;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getHome_phone() {
return home_phone;
}
public void setHome_phone(String home_phone) {
this.home_phone = home_phone;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
You can use introspection to retrieve all the properties of your bean with their corresponding read/write method then call them by reflection.
Here is an example with this simple class:
public class User {
private String login;
private String name;
private String surname;
private Integer age;
//Getters and setters
}
Now, I create a user and dump its properties in a String with comma separated values :
User u = new User();
u.setAge(18);
u.setLogin("myLogin");
u.setName("myName");
u.setSurname("mySurname");
for(PropertyDescriptor pd : Introspector.getBeanInfo(User.class).getPropertyDescriptors()){
//I don't want to get the "class" property
if(!pd.getName().equals("class")){
Method readMethod = pd.getReadMethod();
System.out.print(readMethod.invoke(u)+",");
}
}
Output :
18,myLogin,myName,mySurname,
Note: For the simplicity of this example, I did not suppress the ',' at the end of the output and did not handle case when properties contain character ','.
Use jsefa if you really really want CSV but this is better suited to store the details in some sort or repository/DB.
You can use this library http://jexcelapi.sourceforge.net/ or any such library which can help you convert your java objects in CSV form. One more for you http://kasparov.skife.org/csv/