Set Data in Bean Class - java

I am stuck in an operation. I have 2 POJO Bean Classes
class A{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
..................................................................
class B {
private String company;
private Object object;
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getObject() {
return object;
}
public void setObject(String object) {
this.object = object;
}
}
..........................................................
class SampleTest {
public static void main(String[] args) {
A a = new A();
a.setName("Some Data");
B b = new B();
b.setCompany("Stack Overflow");
b.setObject(a);
//...... Next Lines.....
}
}
Is there any way to set data in B pojo class by reading any Property file?
Example Property file:
#Property File<br>
B.company = Stack Overflow<br>
B.object.name = Some Data
Please help.
Thank you

One way can be :
Properties prop = new Properties();
try
{
// load a properties file
prop.load(new FileReader("config.properties"));
// get the property value
B b = new B();
b.setCompany(prop.getProperty("B.company"));
}
catch (IOException ex)
{
ex.printStackTrace();
}

Related

Changing object values only when save() method is called

I need help passing a test, but can't seem to find the solution anywhere. I have a code for determining the bonus points for customers. I get my info from a text file and I need to give customers bonus points based on vairables. The catch is that the bonus points should only be added when used the save() method, which overwrites the text file. I have a CustomerRepository class:
public class CustomerRepository {
private static final String FILE_PATH = "src/poly/customer/data.txt";
public List<AbstractCustomer> customers;
public CustomerRepository() {
try {
this.customers = readFiles();
} catch (IOException e) {
e.printStackTrace();
}
}
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public List<AbstractCustomer> readFiles() throws IOException{
List<AbstractCustomer> result = new ArrayList<>();
List<String> lines = Files.readAllLines(Path.of(FILE_PATH));
for (String line : lines) {
String[] parts = line.split(";");
int points = Integer.parseInt(parts[3]);
if (parts[0].equals("REGULAR")) {
LocalDate date = LocalDate.parse(parts[4], formatter);
RegularCustomer customer = new RegularCustomer(parts[1], parts[2], points, date);
result.add(customer);
} else if (parts[0].equals("GOLD")) {
GoldCustomer customer = new GoldCustomer(parts[1], parts[2], points);
result.add(customer);
} else {
throw new IOException();
}
}
return result;
}
public void save(AbstractCustomer customer) {
if (!(customers.contains(customer))) {
customers.add(customer);
}
StringBuilder result = new StringBuilder();
for (AbstractCustomer client : customers) {
result.append(client.toString());
result.append("\n");
}
try{
File file = new File(FILE_PATH);
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(result.toString());
bw.close();
}catch(IOException e){
e.printStackTrace();
}
}
This class is working, but I don't know how to give customer objects points only when they are saved. I also have RegularCustomer and GoldCustomer classes which extend the AbstractCustomer class:
public abstract sealed class AbstractCustomer permits GoldCustomer, RegularCustomer {
protected String id;
protected String name;
protected int bonusPoints;
public AbstractCustomer(String id, String name, int bonusPoints) {
this.id = id;
this.name = name;
this.bonusPoints = bonusPoints;
}
public abstract void collectBonusPointsFrom(Order order);
public String getId() {
return id;
}
public String getName() {
return name;
}
public Integer getBonusPoints() {
return bonusPoints;
}
The code itself is working fine and does the intended things, but my only problem is passing this test:
#Test
public void customerIsChangedOnlyWhenSaved() {
String randomId = UUID.randomUUID().toString();
repository.save(new RegularCustomer(
randomId, "David", 0, LocalDate.now()));
AbstractCustomer customer = repository.getCustomerById(randomId).get();
assertThat(customer.getBonusPoints(), is(0));
customer.collectBonusPointsFrom(new Order(200, LocalDate.now()));
assertThat(customer.getBonusPoints(), is(not(0)));
AbstractCustomer loaded = repository.getCustomerById(randomId).get();
assertThat(loaded.getBonusPoints(), is(0));
}
This test creates a new customer and adds a order, but the customer bonuspoints should not change, because it is not saved. My code still adds the points and overwrites the file.
There is also a BonusCollector class, which collects bonus points from order, but this class shouldn't be modified.
This is the implementation for collectBonusPoints(Order order):
#Override
public void collectBonusPointsFrom(Order order) {
if (order.getTotal() >= 100) {
double points = order.getTotal();
if (isWithinAMonth(order.getDate())) {
this.bonusPoints += Math.toIntExact(Math.round(points * 1.5));
this.lastOrderDate = order.getDate();
} else {
this.bonusPoints += Math.toIntExact(Math.round(points));
this.lastOrderDate = order.getDate();
}
}
}
The gold customer implementation is a bit different.
The problem is with persisting state.In abstractcustomer class you need to have get method and from this method to return the clone of the object to be able to pass the test.
public class Customer {
protected String id;
protected String name;
protected int bonusPoints;
public Customer(String id, String name, int bonusPoints) {
this.id = id;
this.name = name;
this.bonusPoints = bonusPoints;
}
public void collectBonusPointsFrom(Order order) {
....
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public Integer getBonusPoints() {
return bonusPoints;
}
public Customer get(){
//if you don`t return new object you will work directly with the one from repo
return new Customer(id,name,bonusPoints);
}
}
The full code you can find -> https://drive.google.com/file/d/1FOeF68RO-qI4CO9mJ92rKlQ8MNigWbof/view?usp=sharing

Thread safe Builder Pattern

I want to make my Builder pattern as Thread safe But facing issues in that, below is my code:
// Server Side Code
final class Student {
// final instance fields
private final int id;
private final String name;
private final String address;
public Student(Builder builder)
{
this.id = builder.id;
this.name = builder.name;
this.address = builder.address;
}
// Static class Builder
public static class Builder {
/// instance fields
private int id;
private String name;
private String address;
public static Builder newInstance()
{
return new Builder();
}
private Builder() {}
// Setter methods
public Builder setId(int id)
{
this.id = id;
return this;
}
public Builder setName(String name)
{
this.name = name;
return this;
}
public Builder setAddress(String address)
{
this.address = address;
return this;
}
// build method to deal with outer class
// to return outer instance
public Student build()
{
return new Student(this);
}
}
#Override
public String toString()
{
return "id = " + this.id + ", name = " + this.name +
", address = " + this.address;
}
}
----------
There is another class named StudentReceiver.java in which I am using multithreading:
class StudentReceiver {
// volatile student instance to ensure visibility
// of shared reference to immutable objects
private volatile Student student;
public StudentReceiver() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
public void run() {
student = Student.Builder.newInstance().setId(1).setName("Ram").setAddress("Noida").build();
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
student = Student.Builder.newInstance().setId(2).setName("Shyam").setAddress("Delhi").build();
}
});
t1.start();
t2.start();
//t1.join();
//t2.join();
}
public Student getStudent() {
return student;
}
}
----------
Main class is below from where I am calling these methods:
//Driver class
public class BuilderDemo {
public static void main(String args[]) throws InterruptedException
{
for(int i=0; i<10;i++)
{
StudentReceiver sr = new StudentReceiver();
System.out.println(sr.getStudent());
}
}
}
----------
The output I am getting is like below:
null
null
null
null
null
null
null
null
id = 1, name = Ram, address = Noida
null
Why I am getting null here??
May anyone explain and How to make Builder Pattern thread safe so that it can be used in multithreaaded environment.
Your Builder Pattern is not the problem here. The Constructor of StudentReceiver is.
Starting a Thread inside it without joing it there will lead to the object being assigned, possibly and probably before the Thread even started. So the student Field will not be set for quite some time. So much time in fact, that executing the System.out.println(sr.getStudent()); line right after the constructor will (very probably) receive null from getStundent().
The fix would be to either:
Not use a separate Thread in the Constructor.
Or join the thread inside the Constructor ( which somewhat defeates the Thread's purpose ).
And the Builder class should not be static.
Here is an example of what I'd do:
public interface IBuilder
{
IBuilder setId( int id );
// ...
Student build();
}
final class Student {
// final instance fields
private final int id;
// + other fields - left out for brevity
private Student(Builder builder)
{
this.id = builder.id;
// + other fields
}
private static Object builderLock = new Object();
public static IBuilder getBuilder()
{
synchronized(builderLock)
{
return new Builder();
}
}
// Static class Builder
public class Builder implements IBuilder {
// instance fields
private int id = -1;
// ...
private Builder() {}
// Setter methods
public IBuilder setId(int id) {
this.id = id;
return this;
}
public Student build() {
return new Student(this);
}
}
}
Disclaimer: untested!

Convert composite java object to CSV with Jackson

With Jackson, I need to convert an instance of my class Test in CSV but I'm getting problems with a class that contains one list (Inner)
Ex:
public class Test {
String testName;
#JsonUnwrapped
Simple simple;
#JsonUnwrapped
Inner inner;
public Test(String testName, Simple simple, Inner inner) {
this.testName = testName;
this.simple = simple;
this.inner = inner;
}
public String getTestName() {
return testName;
}
public void setTestName(String testName) {
this.testName = testName;
}
public Simple getSimple() {
return simple;
}
public void setSimple(Simple simple) {
this.simple = simple;
}
public Inner getInner() {
return inner;
}
public void setInner(Inner inner) {
this.inner = inner;
}
}
class Inner {
#JsonUnwrapped
List<Person> persons;
public Inner(List<Person> persons) {
this.persons = persons;
}
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Simple {
String simpleName;
public Simple(String simpleName) {
this.simpleName = simpleName;
}
public String getSimpleName() {
return simpleName;
}
public void setSimpleName(String simpleName) {
this.simpleName = simpleName;
}
}
class Main {
public static void main(String[] args) {
Simple simple = new Simple("simple");
Person person = new Person("jesus");
Inner inner = new Inner(Arrays.asList(person));
Test test = new Test("test", simple, inner);
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(Test.class);
try {
String csv = mapper.writer(schema).writeValueAsString(test);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
For objects properties, I used the annotation #JsonUnwrapped as recommended on this link ,
but I get one exception when jackson try to convert the list Inner.persons:
How can I fix that ?

Does BeanUtils.copyProperties make a deep clone?

To test this, I quickly whipped up the following :
public class Test {
public static void main(String[] args) {
try {
Employee e = new Employee();
e.setName("A");
Employee y = new Employee();
// y=e;
BeanUtils.copyProperties(y, e);
e.setName("B");
System.out.println(y.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Employee{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
This should have printed A instead it prints null. What went wrong here ?
How can I really copy properties from one object to another (and not have them point to the same values), and does BeanUtils.copyProperties create a deep copy in the first place ?
You need to make your Employee class public. This code worked for me (and compiles):
package com.sandbox;
import org.apache.commons.beanutils.BeanUtils;
public class Sandbox {
public static void main(String[] args) {
try {
Employee e = new Employee();
e.setName("A");
Employee y = new Employee();
// y=e;
BeanUtils.copyProperties(y, e);
e.setName("B");
System.out.println(y.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
public static class Employee {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
When I removed the public from Employee, it printed "null".

Using reflection to set an object property

I getting class by name and i need to update them with respective data and my question is how to do it with java
I want to add the method some dummy data .
I don't know the class type I just getting the class name and use reflection to get his data
I use this code to get the class instance and
Class<?> classHandle = Class.forName(className);
Object myObject = classHandle.newInstance();
// iterate through all the methods declared by the class
for (Method method : classHandle.getMethods()) {
// find all the set methods
if (method.getName().matches("set[A-Z].*")
And know that I find the list of the set method I want to update it with data
how can I do that .
assume that In class name I got person and the class have setSalary and setFirstName etc
how can I set them with reflection ?
public class Person {
public void setSalery(double salery) {
this.salery = salery;
}
public void setFirstName(String FirstName) {
this.FirstName = FirstName;
}
}
Instead of trying to call a setter, you could also just directly set the value to the property using reflection. For example:
public static boolean set(Object object, String fieldName, Object fieldValue) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, fieldValue);
return true;
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return false;
}
Call:
Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
set(instance, "salary", 15);
set(instance, "firstname", "John");
FYI, here is the equivalent generic getter:
#SuppressWarnings("unchecked")
public static <V> V get(Object object, String fieldName) {
Class<?> clazz = object.getClass();
while (clazz != null) {
try {
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
return (V) field.get(object);
} catch (NoSuchFieldException e) {
clazz = clazz.getSuperclass();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
return null;
}
Call:
Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
int salary = get(instance, "salary");
String firstname = get(instance, "firstname");
To update the first name
First find the field you want to update
Then find the mutator (which accepts an argument of the field's type)
Finally execute the mutator on the object with the new value:
Field field=classHandle.getDeclaredField("firstName");
Method setter=classHandle.getMethod("setFirstName", field.getType());
setter.invoke(myObject, "new value for first name");
if (method.getName().matches("set[A-Z].*") {
method.invoke(person,salary)
// and so on
}
to know the parameters you can issue method.getPagetParameterTypes()
based on the result construct your parameters and supply.
package apple;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Map.Entry;
import java.util.Set;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
/*
* Employe Details class
*/
class Employee {
private long id;
private String name;
private String userName;
private Address address;
private Contact contact;
private double salary;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Contact getContact() {
return contact;
}
public void setContact(Contact contact) {
this.contact = contact;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
/*
* Address class for employee
*/
class Address {
private String city;
private String state;
private String country;
private int pincode;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getPincode() {
return pincode;
}
public void setPincode(int pincode) {
this.pincode = pincode;
}
}
/*
* Contact class for Employee
*/
class Contact {
private String email;
private String contactNo;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getContactNo() {
return contactNo;
}
public void setContactNo(String contactNo) {
this.contactNo = contactNo;
}
}
public class Server {
public static void main(String args[]) throws JsonSyntaxException, Exception{
Gson gson = new Gson();
/*
* Old Employee Data
*/
Address address = new Address();
Contact contact = new Contact();
Employee employee = new Employee();
address.setCity("shohna-road");
address.setCountry("INDIA");
address.setPincode(12201);
address.setState("Hariyana");
contact.setContactNo("+918010327919");
contact.setEmail("shivritesh9984#gmail.com");
employee.setAddress(address);
employee.setContact(contact);
employee.setId(4389573);
employee.setName("RITESH SINGH");
employee.setSalary(43578349.345);
employee.setUserName("ritesh9984");
System.out.println("Employee : "+gson.toJson(employee));
/* New employee data */
Employee emp = employee;
address.setCity("OMAX");
emp.setAddress(address);
emp.setName("RAVAN");
/* Update employee with new employee Object*/
update(employee, gson.fromJson(gson.toJson(emp), JsonObject.class) );
System.out.println("Employee-Update : "+gson.toJson(employee));
}
/*
* This method update the #target with new given value of new object in json object form
*/
public static void update(Object target, JsonObject json) throws Exception {
Gson gson=new Gson();
Class<? > class1 = target.getClass();
Set<Entry<String, JsonElement>> entrySet = json.entrySet();
for (Entry<String, JsonElement> entry : entrySet) {
String key = entry.getKey();
Field field = class1.getDeclaredField(key);
field.setAccessible(true);
Type genType = field.getGenericType();
field.set(target,
gson.fromJson(entry.getValue(),genType));
}
}
}

Categories

Resources