Given the following class:
package com.example.model;
import java.util.Collection;
import java.util.Set;
import org.neo4j.graphdb.Direction;
import org.neo4j.helpers.collection.IteratorUtil;
import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelatedTo;
import org.springframework.data.neo4j.annotation.RelatedToVia;
import org.springframework.security.core.GrantedAuthority;
#NodeEntity
public class User {
private static final String SALT = "cewuiqwzie";
public static final String FRIEND = "FRIEND";
public static final String RATED = "RATED";
#Indexed
String login;
String name;
String password;
String info;
private Roles[] roles;
public User() {
}
public User(String login, String name, String password, Roles... roles) {
this.login = login;
this.name = name;
this.password = encode(password);
this.roles = roles;
}
private String encode(String password) {
return "";
// return new Md5PasswordEncoder().encodePassword(password, SALT);
}
#RelatedToVia(elementClass = Rating.class, type = RATED)
Iterable<Rating> ratings;
#RelatedTo(elementClass = Movie.class, type = RATED)
Set<Movie> favorites;
#RelatedTo(elementClass = User.class, type = FRIEND, direction = Direction.BOTH)
Set<User> friends;
public void addFriend(User friend) {
this.friends.add(friend);
}
public Rating rate(Movie movie, int stars, String comment) {
return relateTo(movie, Rating.class, RATED).rate(stars, comment);
}
public Collection<Rating> getRatings() {
return IteratorUtil.asCollection(ratings);
}
#Override
public String toString() {
return String.format("%s (%s)", name, login);
}
public String getName() {
return name;
}
public Set<User> getFriends() {
return friends;
}
public Roles[] getRole() {
return roles;
}
public String getLogin() {
return login;
}
public String getPassword() {
return password;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public void updatePassword(String old, String newPass1, String newPass2) {
if (!password.equals(encode(old)))
throw new IllegalArgumentException("Existing Password invalid");
if (!newPass1.equals(newPass2))
throw new IllegalArgumentException("New Passwords don't match");
this.password = encode(newPass1);
}
public void setName(String name) {
this.name = name;
}
public boolean isFriend(User other) {
return other != null && getFriends().contains(other);
}
public enum Roles implements GrantedAuthority {
ROLE_USER, ROLE_ADMIN;
#Override
public String getAuthority() {
return name();
}
}
}
I get a compilation exception here:
public Rating rate(Movie movie, int stars, String comment) {
return relateTo(movie, Rating.class, RATED).rate(stars, comment);
}
Following the tutorial here. Any insight as to where this function resides is appreciated.
You're trying to use the advanced mapping mode. See the reference manual for more information. You'll need to set up AspectJ support in your IDE. Methods are woven into your entity classes at compile time.
Related
I have a User class and a Json file containing an array of Users. When trying to deserialize those users and get a List I'm getting a JsonMappingException, I don't understand what's wrong.
This is my User class:
public class User {
private StringProperty username;
private StringProperty password;
private StringProperty name;
private StringProperty surname;
private StringProperty email;
private StringProperty company;
private StringProperty phone;
private BooleanProperty canMonitorize;
private BooleanProperty canCreateProject;
private BooleanProperty canOpenProject;
private BooleanProperty admin;
public User() {}
public User(String user, String pass, String name, String surname, String email, String company, String phone,
boolean monitorize, boolean createP, boolean openP, boolean admin) {
this.username = new SimpleStringProperty(user);
this.password = new SimpleStringProperty(pass);
this.name = new SimpleStringProperty(name);
this.surname = new SimpleStringProperty(surname);
this.email = new SimpleStringProperty(email);
this.company = new SimpleStringProperty(company);
this.phone = new SimpleStringProperty(phone);
this.canMonitorize = new SimpleBooleanProperty(monitorize);
this.canCreateProject = new SimpleBooleanProperty(createP);
this.canOpenProject = new SimpleBooleanProperty(openP);
this.admin = new SimpleBooleanProperty(admin);
}
public String getUsername() {
return username.get();
}
public void setUsername(String username) {
this.username.set(username);
}
public String getPassword() {
return password.get();
}
public void setPassword(String password) {
this.password.set(password);
}
public String getName() {
return name.get();
}
public void setName(String name) {
this.name.set(name);
}
public String getSurname() {
return surname.get();
}
public void setSurname(String surname) {
this.surname.set(surname);
}
public String getEmail() {
return email.get();
}
public void setEmail(String email) {
this.email.set(email);
}
public String getCompany() {
return company.get();
}
public void setCompany(String company) {
this.company.set(company);
}
public String getPhone() {
return phone.get();
}
public void setPhone(String phone) {
this.phone.set(phone);
}
public boolean canMonitorize() {
return canMonitorize.get();
}
public void setCanMonitorize(boolean canMonitorize) {
this.canMonitorize.set(canMonitorize);
}
public boolean canCreateProject() {
return canCreateProject.get();
}
public void setCanCreateProject(boolean canCreateProject) {
this.canCreateProject.set(canCreateProject);
}
public boolean canOpenProject() {
return canOpenProject.get();
}
public void setCanOpenProject(boolean canOpenProject) {
this.canOpenProject.set(canOpenProject);
}
public boolean isAdmin() {
return admin.get();
}
public void setAdmin(boolean isAdmin) {
this.admin.set(isAdmin);
}
}
And this is an example of the Json file:
[{"username":"admin","password":"blablabla","name":"admin","surname":"admin","email":"admin#admin.com","company":"admin","phone":"admin","admin":true}]
This is the method that should obtain the list of users:
public static List<User> getUsers(String jsonArrayStr) {
ObjectMapper mapper = new ObjectMapper();
List<User> ret;
try {
User[] userArray = mapper.readValue(jsonArrayStr, User[].class);
ret = new ArrayList<>(Arrays.asList(userArray));
} catch (IOException e) {
return new ArrayList<User>();
}
return ret;
}
The error I get when executing the code:
com.fasterxml.jackson.databind.JsonMappingException: N/A (through reference chain: object.User["username"])
When you have a public 0-args constructor it is used by default to create new POJO instance. But in your case you should not allow to create instance with default constructor because all internal fields are null and when Jackson tries to set first property, username, NullPointerException is thrown. Try to declare your constructor as below and remove default one:
#JsonCreator
public User(#JsonProperty("username") String user,
#JsonProperty("password") String pass,
#JsonProperty("name") String name,
#JsonProperty("surname") String surname,
#JsonProperty("email") String email,
#JsonProperty("company") String company,
#JsonProperty("phone") String phone,
#JsonProperty("monitorize") boolean monitorize,
#JsonProperty("createP") boolean createP,
#JsonProperty("openP") boolean openP,
#JsonProperty("admin") boolean admin) {
//your code;
}
Also, your getUsers method could look like this:
public static List<User> getUsers(String json) {
final ObjectMapper mapper = new ObjectMapper();
try {
final JavaType collectionType = mapper.getTypeFactory().constructCollectionType(List.class, User.class);
return mapper.readValue(json, collectionType);
} catch (IOException e) {
//You should not hide exceptions. Try to log it at least.
//But probably application should not start when app configuration is missing or wrong.
e.printStackTrace();
return Collections.emptyList();
}
}
This will be quite a bit of code as I don't know what will be important. I was trying to recreated the basic UI Alejandro made in my tutorial session with him a few months ago, substituting a table in my database for the one he used. The errors I'm getting all seem related to overriding Vaadin Flow functions. I know that replaces the behavior of the Super method. IntelliJ opens the relevant Super method when I click on the errors, which I'm assuming it wants me to edit to solve the problem, but I have no idea how to do that.
I was going to paste a link to the code but the forum told me to just place it here.
Customer.java
package com.dbproject.storeui;
import java.time.LocalDate;
public class Customer {
private Long id;
private String lastname;
private String firstname;
private String email;
private String password;
private String phone;
private String street;
private String city;
private String st;
private int zip;
private LocalDate dob;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getSt() {
return st;
}
public void setSt(String st) {
this.st = st;
}
public int getZip() {
return zip;
}
public void setZip(int zip) {
this.zip = zip;
}
public LocalDate getDob() {
return dob;
}
public void setDob(LocalDate dob) {
this.dob = dob;
}
}
CustomerRepository.java
package com.dbproject.storeui;
import org.apache.ibatis.annotations.*;
import java.util.List;
#Mapper
public interface CustomerMapper {
#Select("SELECT * FROM customer ORDER BY id")
List<Customer> findAll();
#Update("UPDATE customer" +
"SET lastname=#{lastname}, firstname=#{firstname}, email=#{email}, password=#{password}, phone=#{phone}, street=#{street}, city=#{city}, st=${st}, zip=#{zip}, dob=#{dob}" +
"WHERE id=#{id}")
void update(Customer customer);
#Insert("INSERT INTO customer(lastname, firstname, email, password, phone, street, city, st, zip, dob) VALUES(#{lastname}, #{firstname}, #{email}, #{password}, #{phone}, #{street}, #{city}, #{st}, #{zip}, #{dob})")
#Options(useGeneratedKeys = true, keyProperty = "id")
void create(Customer customer);
}
CustomerView.java (the UI class)
package com.dbproject.storeui;
import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.router.Route;
#Route("")
public class CustomerView extends Composite<VerticalLayout> {
private final CustomerMapper customerMapper;
private Grid<Customer> grid = new Grid<>();
private TextField lastname = new TextField("Last Name");
private TextField firstname = new TextField("First Name");
private Button save = new Button("Save", VaadinIcon.CHECK.create());
private Button create = new Button("New", VaadinIcon.PLUS.create());
private VerticalLayout form = new VerticalLayout(lastname, firstname, save);
private Binder<Customer> binder = new Binder<>(Customer.class);
private Customer customer;
public CustomerView(CustomerMapper customerMapper) {
this.customerMapper = customerMapper;
grid.addColumn(Customer::getLastname).setHeader("Last Name");
grid.addColumn(Customer::getFirstname).setHeader("First Name");
grid.addSelectionListener(event -> setCustomer(grid.asSingleSelect().getValue()));
updateGrid();
save.addClickListener(event -> saveClicked());
create.addClickListener(event -> createClicked());
getContent().add(grid, create, form);
binder.bindInstanceFields(this);
binder.setBean(null);
}
private void createClicked() {
grid.asSingleSelect().clear();
setCustomer(new Customer());
}
private void saveClicked() {
binder.readBean(customer);
if (customer.getId() == null) {
customerMapper.create(customer);
} else {
customerMapper.update(customer);
}
updateGrid();
Notification.show("Saved!");
}
private void setCustomer(Customer customer) {
this.customer = customer;
form.setEnabled(customer != null);
binder.setBean(customer);
}
private void updateGrid() {
grid.setItems(customerMapper.findAll());
}
}
I'm trying to implement authentication with Spring Security and my problem is that I'm using a MongoDB base where the username and the associated password are in two distinct collections. So when I implement UserDetails, I can't return the password properly. Here is what I've tried:
package com.example.springmongo.user;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
#Document(collection = "users")
public class User implements UserDetails {
/**
*
*/
private static final long serialVersionUID = -2217225560457250699L;
#Autowired
private UserPassService userPassService;
#Id
private String id;
#Field(value = "iduser")
private Long iduser;
#Field(value = "name_complete")
private String name_complete;
#Field(value = "mail")
private String mail;
#Field(value = "active")
private Double active;
#Field(value = "creationDate")
private String creationDate;
#Field(value = "last_login")
private String last_login;
public User() {
super();
}
public User(String id, Long iduser, String name_complete, String mail, Double active, String creationDate, String last_login) {
super();
this.id = id;
this.iduser = iduser;
this.name_complete = name_complete;
this.mail = mail;
this.active = active;
this.creationDate = creationDate;
this.last_login = last_login;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Long getIduser() {
return iduser;
}
public void setIduser(Long iduser) {
this.iduser = iduser;
}
public String getName_complete() {
return name_complete;
}
public void setName_complete(String name_complete) {
this.name_complete = name_complete;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public Double getActive() {
return active;
}
public void setActive(Double active) {
this.active = active;
}
public String getCreationDate() {
return creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
public String getLast_login() {
return last_login;
}
public void setLast_login(String last_login) {
this.last_login = last_login;
}
#Override
public String toString() {
return "name: " + this.name_complete + ", mail: " + this.mail + ", id: " + this.id;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
#Override
public String getPassword() {
return this.userPassService.getUserPassword(this.iduser);
}
#Override
public String getUsername() {
return this.getMail();
}
#Override
public boolean isAccountNonExpired() {
if (this.getActive() != null && this.getActive().equals(1.0)) {
return true;
}
return false;
}
#Override
public boolean isAccountNonLocked() {
if (this.getActive() != null && this.getActive().equals(1.0)) {
return true;
}
return false;
}
#Override
public boolean isCredentialsNonExpired() {
if (this.getActive() != null && this.getActive().equals(1.0)) {
return true;
}
return false;
}
#Override
public boolean isEnabled() {
if (this.getActive() != null && this.getActive().equals(1.0)) {
return true;
}
return false;
}
}
Unfortunately, I can't access my UserPassService from an entity like this. So how can I access the password ?
Thanks in advance !
You cant use #Autowired on spring components in entity class as a field. Use like this ;
private transient UserPassService userPassService;
and add setter method of this ;
#Autowired
public void setUserPassService(UserPassService userPassService) {
this.userPassService = userPassService;
}
Beaware of creatation of Entity class with new is making this service is null. If you create with new , call setUserPassService method with autowired object of UserPassService.
I am trying to convert the response from server which is a JSON string,I want to convert that JSONstring to java object.I am trying Gson.Please someone explain and tell me the steps how to do it using Gson.
#Override
public void onClick(View v) {
if (v == mLoginButton) {
LoginUser();
}
if (v==mSignUpBtn){
Intent intent=new Intent(LoginActivity.this,RegistrationActivity.class);
startActivity(intent);
}
}
private void LoginUser() {
// final String username = editTextUsername.getText().toString().trim();
final String password = editTextPassword.getText().toString().trim();
final String email = editTextEmail.getText().toString().trim();
StringRequest postStringRequest = new StringRequest(Request.Method.POST,LOGIN_API,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(LoginActivity.this, response, Toast.LENGTH_LONG).show();
Log.d(TAG,"Reponse Check :"+response);
// Gson gson = new Gson();
// String jsonInString = "{}";
//LoginActivity staff = gson.fromJson(jsonInString, LoginActivity.class);
//Log.d(TAG,"Reponse Check staff :"+staff);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(LoginActivity.this, error.toString(), Toast.LENGTH_LONG).show();
Log.e(TAG,"Error Response Check :"+error);
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
Log.d(TAG,"For email :"+email);
Log.d(TAG,"For password :"+password);
//try {
Log.d(TAG,"My Credentials email URL Encoder: "+( mEncryption.AESEncode(email)));
Log.d(TAG,"My Credentials email URL DECODED: "+( mEncryption.AESDecode(mEncryption.AESEncode(email))));
params.put("data[User][email]",(mEncryption.AESEncode(email)));
Log.d(TAG,"My Credentials pass URL Encoder: "+( mEncryption.AESEncode(password)));
paa
}
logcat
03-16 16:36:08.346 2618-3428/com.example.user.myapplication D/Null: For email :abc#gmail.com
03-16 16:36:08.346 2618-3428/com.example.user.myapplication D/Null: For password :12345678
03-16 16:36:08.354 2618-3428/com.example.user.myapplication D/Null: My Credentials email URL Encoder: RyUMRBg7UyeIlFBBtNemZFuG46PJtAIdiZWXnlJ4zNI=
03-16 16:36:08.358 2618-3428/com.example.user.myapplication D/Null: My Credentials email URL DECODED: abc#gmail.com
03-16 16:36:08.360 2618-3428/com.example.user.myapplication D/Null: My Credentials pass URL Encoder: pfrt1fKLkoZhAT6hoMJFiA==
03-16 16:36:08.361 2618-3428/com.example.user.myapplication D/Null: Params :{data[User][password]=pfrt1fKLkoZhAT6hoMJFiA==
, data[User][email]=RyUMRBg7UyeIlFBBtNemZFuG46PJtAIdiZWXnlJ4zNI=
}
03-16 16:36:08.505 2618-2618/com.example.user.myapplication D/Null: Reponse Check :{"code":200,"user":{"User":{"id":"ui1bJkK19jxbaquTboA2oQ==","email":"RyUMRBg7UyeIlFBBtNemZFuG46PJtAIdiZWXnlJ4zNI=","status":"1","verified":"1","created":"2016-03-07 11:41:59","modified":"2016-04-07 15:43:43","token":"6b987332b77d7c69d76bf7be80a85177fb7fa08d"},"Profile":{"id":"1","first_name":"abc","last_name":"fgh","bio":"sfafaf","address":"82, Debinibash Road\r\nDum Dum, P.O. - Motijheel","phone":"+913325505055","profile_pic":"\/img\/356a192b7913b04c54574d18c28d46e6395428ab\/license.jpg","user_id":"1","Contributor":{"id":"31","profile_id":"1","status":"1","vs_cdn_id":"261961777","secret_token":"s-7Va5z","uploaded_on":null,"statement":"AOK KJDHKJDH bkgkg kkhkjh kjhkj kjh kjhkjh","time":"7 hours per month","created":"2016-05-02 18:40:11","modified":"2016-05-02 18:41:29"},"Moderator":[]},"redirect":"\/"}}
You can use in a generic way like:
private final static Gson GSON = new GsonBuilder().create();
public static <T> T fromJSON(String json, Class<T> clazz) {
try {
return GSON.fromJson(json, clazz);
} catch (JsonSyntaxException e) {
LOGGER.warn("Could not deserialize object", e);
}
return null;
}
You can't make activity/fragment from json.
In your onResponse() method:
ModelObject obj = new Gson().fromJson(jsonString, ModelObject.class);
And make ModelObject class something like this:
public class ModelObject {
int field1;
int field2;
//here you should make getters and setters;
}
After it you can do anything you need with this object (pass it to any activity or fragment).
Gson will map the values to the corresponding model class object if the fields are given correctly. Have a look at the below model classes. After that, if you call Example data = GSON.fromJson(yourJson, Example.class); , this data object will have all that you need.
-----------------------------------com.example.Contributor.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Contributor {
#SerializedName("id")
#Expose
private String id;
#SerializedName("profile_id")
#Expose
private String profileId;
#SerializedName("status")
#Expose
private String status;
#SerializedName("vs_cdn_id")
#Expose
private String vsCdnId;
#SerializedName("secret_token")
#Expose
private String secretToken;
#SerializedName("uploaded_on")
#Expose
private Object uploadedOn;
#SerializedName("statement")
#Expose
private String statement;
#SerializedName("time")
#Expose
private String time;
#SerializedName("created")
#Expose
private String created;
#SerializedName("modified")
#Expose
private String modified;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getProfileId() {
return profileId;
}
public void setProfileId(String profileId) {
this.profileId = profileId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getVsCdnId() {
return vsCdnId;
}
public void setVsCdnId(String vsCdnId) {
this.vsCdnId = vsCdnId;
}
public String getSecretToken() {
return secretToken;
}
public void setSecretToken(String secretToken) {
this.secretToken = secretToken;
}
public Object getUploadedOn() {
return uploadedOn;
}
public void setUploadedOn(Object uploadedOn) {
this.uploadedOn = uploadedOn;
}
public String getStatement() {
return statement;
}
public void setStatement(String statement) {
this.statement = statement;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public String getModified() {
return modified;
}
public void setModified(String modified) {
this.modified = modified;
}
}
-----------------------------------com.example.Example.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Example {
#SerializedName("code")
#Expose
private Integer code;
#SerializedName("user")
#Expose
private User user;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
-----------------------------------com.example.Profile.java-----------------------------------
package com.example;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Profile {
#SerializedName("id")
#Expose
private String id;
#SerializedName("first_name")
#Expose
private String firstName;
#SerializedName("last_name")
#Expose
private String lastName;
#SerializedName("bio")
#Expose
private String bio;
#SerializedName("address")
#Expose
private String address;
#SerializedName("phone")
#Expose
private String phone;
#SerializedName("profile_pic")
#Expose
private String profilePic;
#SerializedName("user_id")
#Expose
private String userId;
#SerializedName("Contributor")
#Expose
private Contributor contributor;
#SerializedName("Moderator")
#Expose
private List<Object> moderator = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
public String getBio() {
return bio;
}
public void setBio(String bio) {
this.bio = bio;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getProfilePic() {
return profilePic;
}
public void setProfilePic(String profilePic) {
this.profilePic = profilePic;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Contributor getContributor() {
return contributor;
}
public void setContributor(Contributor contributor) {
this.contributor = contributor;
}
public List<Object> getModerator() {
return moderator;
}
public void setModerator(List<Object> moderator) {
this.moderator = moderator;
}
}
-----------------------------------com.example.User.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class User {
#SerializedName("User")
#Expose
private User_ user;
#SerializedName("Profile")
#Expose
private Profile profile;
#SerializedName("redirect")
#Expose
private String redirect;
public User_ getUser() {
return user;
}
public void setUser(User_ user) {
this.user = user;
}
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
public String getRedirect() {
return redirect;
}
public void setRedirect(String redirect) {
this.redirect = redirect;
}
}
-----------------------------------com.example.User_.java-----------------------------------
package com.example;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class User_ {
#SerializedName("id")
#Expose
private String id;
#SerializedName("email")
#Expose
private String email;
#SerializedName("status")
#Expose
private String status;
#SerializedName("verified")
#Expose
private String verified;
#SerializedName("created")
#Expose
private String created;
#SerializedName("modified")
#Expose
private String modified;
#SerializedName("token")
#Expose
private String token;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getVerified() {
return verified;
}
public void setVerified(String verified) {
this.verified = verified;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
public String getModified() {
return modified;
}
public void setModified(String modified) {
this.modified = modified;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
I am playing with the Jackson examples and am having some trouble getting deserialization to work with immutable classes and interfaces.
Below is my code:
package com.art.starter.jackson_starter;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
/** * Hello world! * */ public class App {
public static void main( String[] args ) throws JsonGenerationException, JsonMappingException, IOException
{
System.out.println( "Hello World!" );
AddressImpl.AddressBuilder builder = new AddressImpl.AddressBuilder();
NameImpl.Builder nameBuilder = new NameImpl.Builder();
UserImpl.Builder userBuilder = new UserImpl.Builder();
Name name = nameBuilder.first("FirstName")
.last("LastName")
.build();
Address address = builder.setCity("TestCity")
.setCountry("TestCountry")
.setState("PA")
.setStreet("TestAddress")
.setZip(123)
.build();
User user = userBuilder.address(address)
.gender(User.Gender.MALE)
.isVerified(true)
.userImage(new byte[5])
.build();
System.out.println(address);
System.out.println(name);
System.out.println(user);
StringWriter sw = new StringWriter();
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(sw, user);
System.out.println(sw);
StringReader sr = new StringReader("{\"address\":{\"state\":\"PA\",\"country\":\"TestCountry\",\"street\":\"TestAddress\",\"city\":\"TestCity\",\"zip\":123},\"verified\":true,\"gender\":\"MALE\",\"userImage\":\"AAAAAAA=\"}");
/*
This line throws the Exception
*/
User user2 = mapper.readValue(sr, UserImpl.class);
System.out.println(user2);
} }
package com.art.starter.jackson_starter;
import java.util.Arrays;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
public final class UserImpl implements User
{
private final Address address;
private final Gender gender;
private final byte[] userImage;
private final boolean isVerified;
public static class Builder
{
private Address address;
private Gender gender;
// private Name name;
private byte[] userImage;
private boolean isVerified;
public Builder address(Address address)
{
this.address = address;
return this;
}
public Builder gender(Gender gender)
{
this.gender = gender;
return this;
}
// public Builder name(Name name)
// {
// this.name = name;
// return this;
// }
public Builder userImage(byte[] userImage)
{
this.userImage = userImage;
return this;
}
public Builder isVerified(boolean isVerified)
{
this.isVerified = isVerified;
return this;
}
public UserImpl build()
{
return new UserImpl(address, gender, userImage, isVerified);
}
}
#JsonCreator
public UserImpl(#JsonProperty("address") Address address, #JsonProperty("gender") Gender gender, #JsonProperty("userImage") byte[] userImage,
#JsonProperty("verified") boolean isVerified)
{
super();
this.address = address;
this.gender = gender;
this.userImage = userImage;
this.isVerified = isVerified;
}
public Address getAddress()
{
return address;
}
public Gender getGender()
{
return gender;
}
public byte[] getUserImage()
{
return userImage;
}
public boolean isVerified()
{
return isVerified;
}
#Override
public String toString()
{
StringBuilder builder2 = new StringBuilder();
builder2.append("UserImpl [address=");
builder2.append(address);
builder2.append(", gender=");
builder2.append(gender);
builder2.append(", isVerified=");
builder2.append(isVerified);
builder2.append(", name=");
builder2.append(", userImage=");
builder2.append(Arrays.toString(userImage));
builder2.append("]");
return builder2.toString();
}
}
package com.art.starter.jackson_starter;
import org.codehaus.jackson.annotate.JsonCreator;
import org.codehaus.jackson.annotate.JsonProperty;
public final class AddressImpl implements Address
{
private final String city;
private final String country;
private final String street;
private final String state;
private final int zip;
public static class AddressBuilder
{
private String city;
private String country;
private String street;
private String state;
private int zip;
public AddressBuilder setCity(String city)
{
this.city = city;
return this;
}
public AddressBuilder setCountry(String country)
{
this.country = country;
return this;
}
public AddressBuilder setStreet(String street)
{
this.street = street;
return this;
}
public AddressBuilder setState(String state)
{
this.state = state;
return this;
}
public AddressBuilder setZip(int zip)
{
this.zip = zip;
return this;
}
public AddressImpl build()
{
return new AddressImpl(city, country, street, state, zip);
}
}
#JsonCreator
public AddressImpl(#JsonProperty("city") String city, #JsonProperty("country") String country, #JsonProperty("street") String street,
#JsonProperty("state") String state, #JsonProperty("zip") int zip)
{
this.city = city;
this.country = country;
this.street = street;
this.state = state;
this.zip = zip;
}
public String getCity()
{
return city;
}
public String getCountry()
{
return country;
}
public String getStreet()
{
return street;
}
public String getState()
{
return state;
}
public int getZip()
{
return zip;
}
#Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("AddressImpl [city=");
builder.append(city);
builder.append(", country=");
builder.append(country);
builder.append(", state=");
builder.append(state);
builder.append(", street=");
builder.append(street);
builder.append(", zip=");
builder.append(zip);
builder.append("]");
return builder.toString();
}
}
The issue appears to be with Address. I get this exception:
Exception in thread "main" org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.art.starter.jackson_starter.Address, problem: abstract types can only be instantiated with additional type information
at [Source: java.io.StringReader#785f8172; line: 1, column: 2]
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.StdDeserializationContext.instantiationException(StdDeserializationContext.java:212)
at org.codehaus.jackson.map.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:97)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:230)
at org.codehaus.jackson.map.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:595)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:472)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:350)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2391)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1614)
at com.art.starter.jackson_starter.App.main(App.java:56)
I am sure this is because there is no way for Jackson to resolve Address which is an interface to AddressImpl which is a concrete implementation. I have been poking through the docs and have looked at a few articles regarding the #JsonDeserialize(as=AddressImpl.class),but it didn't work. So I am stumped. Has anyone ever gotten this to work, is it even supported?
It works like a champ if I replace Address with AddressImpl in the UserImpl class.
Just in case you hadn't seen it, here's a blog entry that discusses working with immutable objects and Jackson.
But you should definitely be able to use #JsonDeserialize(as=AddressImpl.class); either by adding it to Address.java interface (either directly or by using mix-ins), or by adding it to field or property. One thing to note is that for deserialization, it MUST be next to accessor you use; setter if you have one, if not, next to field. Annotations are not (yet) shared between accessors; so for example adding it to 'getter' would not work.
Jackson 1.8 also finally allows registration of abstract-to-concrete types (see http://jira.codehaus.org/browse/JACKSON-464 for more details) which might be the best option to indicate that 'AddressImpl' is to be used for 'Address'.