Java beans binding in GUI - java

I created a User bean class and bind it to a JTextField. I'd like to update the textfield when a method setName of the bean is call. Here is the code:
package newpackage;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class User {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
propertyChangeSupport.firePropertyChange(null, null, null);
}
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.removePropertyChangeListener(listener);
}
}
I use NetBeans to design a GUI. It works. But I was wondering whether it is a correct way to implement bean binding with a Swing component.

Almost. Try something like this (untested):
public void setName(String name) {
String oldName = this.name;
this.name = name;
propertyChangeSupport.firePropertyChange("name", oldName, name);
}
See the Javadoc.

Related

Validating model classes in setter methods

I would like to ask your ideas about designing best validation approach for below requirements:
We have a User model class and depending on it is status we can update some specific fields. As you can see, changeability of the model class depends on its status field.
If the status of user is ACTIVE then all fields (name, surname,
password ....) can be updated.
If the status of user is INACTIVE only password can be updated.
If the status of user is BLOCKED then name and surname can be
updated.
If the status of user is DELETED then update operation is not
allowed for any field.
Obviously, it can be done simply by adding a UserValidator class and before setting values in setter methods I can call my UserValidator to check if the operation is allowed or not. However, it has a drawback (?): what will happen if there will be new field (let's say maritalStatus) and dev who adds that field forgets to call UserValidator before setting maritalStatus?
Other ways of solving this problem that I can think of:
Using custom annotations by extending CustomValidator. However, it
won't work as annotation cannot know the previous values of object.
I mean, the isValid() method of CustomValidator won't know if the name
field has changed or not (it was "John" and now dev wants to change it
to "Jack")
Proxy pattern could be useful but not sure if it is good idea to use
proxy for model objects.
I've seen that the decorator pattern can be used for this problem but I don't understand how. I think validating model class is beyond the responsibility of a decorator design.
public class User {
private Integer id;
private String name;
private String surname;
private String password;
private Status status;
// setters
}
public enum Status {
ACTIVE, DELETED, INACTIVE, BLOCKED
}
I suggest you to use intention-revealing interfaces instead of setter/getter
E.g.
public class User {
private Integer id;
private String name;
private String surname;
private String password;
private Status status;
void rename(String newName, String newSurname){
if(Status.INACTIVE.equals(status) || Status.DELETED.equals(status))
throws new Exception("You cannot rename a inactive or deleted user");
this.name = newName;
this.surname = newSurname;
}
.....
}
Here is the approach I will use. Would be very nice if you guys can also vote for that.
Basicly I will use Decorator pattern.
public interface User {
Integer getId();
void setId(Integer id);
String getName();
void setName(String name);
String getSurname();
void setSurname(String surname);
String getPassword();
void setPassword(String password);
Status getStatus();
void setStatus(Status status);
}
public class UserImpl implements User {
private Integer id;
private String name;
private String surname;
private String password;
private Status status;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
}
public abstract class UserDecorator implements User{
private final User user;
public UserDecorator(User user) {
this.user = user;
}
public Integer getId() {
return user.getId();
}
public void setId(Integer id) {
user.setId(id);
}
public String getName() {
return user.getName();
}
public void setName(String name) {
user.setName(name);
}
public String getSurname() {
return user.getSurname();
}
public void setSurname(String surname) {
user.setSurname(surname);
}
public String getPassword() {
return user.getPassword();
}
public void setPassword(String password) {
user.setPassword(password);
}
public Status getStatus() {
return user.getStatus();
}
public void setStatus(Status status) {
user.setStatus(status);
}
}
InActive User:
public class InactiveUserImpl extends UserDecorator {
public InactiveUserImpl(User user) {
super(user);
}
// didn't override setPassword therefore that field can be updated when the status of user is Inactive
#Override
public void setId(Integer id) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
#Override
public void setName(String name) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
#Override
public void setSurname(String surname) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
#Override
public void setStatus(Status status) {
throw new IllegalArgumentException("Field can not be update when user is InActive");
}
}
Active User:
public class ActiveUserImpl extends UserDecorator {
public ActiveUserImpl(User user) {
super(user);
}
// not overriding any method hence everything can be updated
}
Basically, whoever will ask for UserImpl I will return him wrapped version of UserImpl, For example,
class UserRepository{
public User getById(String id){
User user=db.getUserById(id);
// this can be done with Enum but it is out of our scope
if (user.getStatus().equals(INACTIVE))
return new InactiveUserImpl(user);
// ....
return null;
}
}
If you do :
User user= userRepository.getById(1)
then you will get user with the sets of allowed setters.

Overrride global jackson config

Im my app null values will not be serialized to json, and its ok. But in one specific case, I'd like to have null values send to client. How could I achieve that ?
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
for this class I tried with JsonInclude.Always but its defualt value that gets overriden in config later on.
Use JsonInclude annotation. Example:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
System.out.println(mapper.writeValueAsString(new User()));
}
}
#JsonInclude
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Above code prints:
{"name":null}
Default value in JsonInclude is ALWAYS:
/**
* Inclusion rule to use for instances (values) of types (Classes) or
* properties annotated.
*/
public Include value() default Include.ALWAYS;
Other option is to use JsonSerialize annotation:
#JsonSerialize(include = Inclusion.ALWAYS)
class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Result is the same as for JsonInclude.
Try
#JsonInclude(JsonInclude.Include.ALWAYS)

[JAVA]How to get generic class typed name

I would like to get E class name in String value with java reflection.
For example, if i create Node typed in Person, getClassName() has to return "Person"
Someone can help me?
public class Node<E extends AbstractNode> {
String getClassName() {
String name = ??
}
private String alias;
public Node() {
}
}
public abstract class AbstractNode {
}
public class Person extends AbstractNode {
private String name;
private String surname;
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;
}
}
Add a field to your Node class
private static final Class<T> type;
And add this to your constructor signature
public Node(Class type) {
this.type = type;
}
Lastly, create the getClassName method in your Node class:
public String getClassName(){
return this.type.getName();
}
Edit:
As a sidenote, your AbstractNode class is not really necessary (it doesn't do anything) and therefore neither is the extend in Person.

Are annotations must to Serailaize the java object via JaxB?

Sometimes it serializes without annotations in xml and the other times it doesnt?Someone please enlighten me regarding the necessity of Annotations.
#XmlRootElement
public class Test {
public void setAge(int age) {
this.age = age;
}
private int age;
private String name;
private Cat cat;
public Test()
{
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
}
class Cat
{
private String name="catttttttttttttttt";
public Cat()
{
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
In the above code,it works fine,but sometimes if dont add #XMLElement above the getCat(),it doesnt serialize.
I googled through some sites and got the best explanation here:
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
Its not required to put annotations and it depends completely on #XmlAccessorType.
Thanq
public class MainClass {
public static void main(String[] args) throws Exception {
JAXBContext contextObj = JAXBContext.newInstance(Test.class);
Marshaller marshallerObj = contextObj.createMarshaller();
marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Test test = new Test();test.setAge(25);test.setName("Sriharsha");test.setCat(new Cat());
marshallerObj.marshal(test, new FileOutputStream("/home/pankaj/Downloads/Emp.xml"));
System.out.println();
}
}

Java casting enum to a class

I have a class which is identical to enum. The only difference is that I create the class so that I can dynamically create the enums. What I want is to override the cast operation of enum so that I can give the enum instance to a method where it gets the class instance.
Example:
public enum SpecialEnum {
FIRST("First"), SECOND("Second");
private String name;
SpecialEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class SpecialClass {
private String name;
public SpecialClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public void displayName(SpecialClass specialClass) {
System.out.println(specialClass.getName());
}
Lets say that the SpecialClass instances are coming from a server where I display them. But I also want to use my pre-defined Special enum classes as well. I know that I could create static instances of SpecialClass and use them but not that it looks messy, also using enums are beneficial to my occasion as well. Is there a way to override casting operation of the enum class of a work around maybe?
Extract an interface:
public interface Named {
public String getName();
}
public class SpecialClass implements Named {
private String name;
public SpecialClass(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
public enum SpecialEnum implements Named {
FIRST("First"), SECOND("Second");
private String name;
SpecialEnum(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
public void displayName(Named specialClass) {
System.out.println(specialClass.getName());
}

Categories