Suppose I have some data in a file or maybe database. It could be JSON, XML, YAML, CSV, String[], etc.
I'd like to create a model object with this data. For example:
Data:
{
"name": "John Doe",
"age": "30"
}
Model (Pseudocode):
class Person {
Person(name, age) {
this.name = name;
this.age = age;
}
// business logic
}
Some code that creates Person objects from JSON data (Pseudocode):
peopleArray = [];
recordSet = aJSONReader.read('file');
for (recordSet as r) {
peopleArray.add(new Person(r[0], r[1]));
}
What would you use to build model objects from given data? In my example I'd start supporting JSON. What if I'd like to change it or support new data formats?
How do I decouple this code? Which design pattern fit here?
Use the strategy pattern (see here). You want to provide different methods to parse data. A method would parse JSON, another method would parse XML and another method would read a database. Each method can be seen as a strategy to parse data and generate data objects.
Create a common interface, let's say IDataObjectParser with a single method like public List<DataObject> parse(). Each parser would implement this interface. Then you can exchange the parser whenever you want, e.g. during runtime or according to a configuration file.
I like this technique. Create an abstract object who's responsibility will be to provide attributes. In this case name and age.
interface PersonInput {
public String getName();
public int getAge();
}
Have Person class use that object in the constructor
class Person {
public Person(PersonInput input) {
name = input.getName();
age = input.getAge();
}
}
Now you can have many implementations of PersonInput each dealing with different data format (CSV, XML, etc.)
JSON example:
class JsonPersonInput implements PersonInput {
private String name;
private int age;
public JsonPersonInput(String json) throws JSONException {
JSONObject data = new JSONObject(json);
name = data.getString("name");
age = data.getInt("age");
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
You use it like this
new Person(new JsonPersonInput(jsonString))
If by 'data' you are referring to a persistence mechanism then this is the perfect situation for Data Access Objects (or DAOs).
This is most commonly associated with Java web applications and implementations for RDBMSs but it has applications in all Java applications requiring persistence.
You only need define a DAO interface for your person, say PersonDAO with two methods on it getPerson() and savePerson().
interface PersonDAO {
public Person readPerson(String path);
public void addPerson(Person personToBeSaved);
}
Then create another class, say one for your JSON implementation, that implements your DAO, let's call ours JsonPersonDAO.
If you are using a factory to generate your Person objects you then only need to change the DAO implementation that you are using in a single place when the need arises. If you are generating your Person objects from inside your class you only need to change what DAO implementation it uses.
Further reading on this here:
http://www.oracle.com/technetwork/java/dataaccessobject-138824.html
http://best-practice-software-engineering.ifs.tuwien.ac.at/patterns/dao.html
Related
I am sure this question might have been asked couple of times here but I am not understanding what query I should use.
What I want to do is, Passing POJO to another POJO where parameter could be dynamic
like example below
Class DataPOJO{
private String name;
public String getName(){
return this.name;
}
public void setName(String name){
return this.name;
}
}
I want to make another POJO where I can pass value like
RequestmakerPOJO request = new RequestmakerPOJO(authorisationObject, dataPOJO, DataPOJO);
Where dataPOJO would be object I created and DataPOJO.class it's structure, later I can pass any kind of pojo to this new Requestmaker class with it's structure definition and object just like. HashMap<ObjectType, ObjectType2>
But I want only 1 Object type to be passed and then it's object. I am new at java so I don't know what to call these scenarios. Please help me out with the query or solution.
:) thanks
You should declare RequestmakerPOJO as a generic class:
class RequestmakerPOJO<T> {
...
}
Now you can use T as a type wherever you want. For example, the constructor can be
RequestmakerPOJO(AuthPOJO auth, T data) {
...
}
To declare a variable
RequestmakerPOJO<DataPOJO> request = new RequestmakerPOJO<>(auth, data);
For more details, research generics in Java.
//Interface DAO
public abstract class BaseDAO<T extends BaseDTO> {
public void update(T t) throws DBException {
Field[] fieldsToInsert = t.getClass().getDeclaredFields();
//code to update database object academic or event
}
public Integer create(T t) throws DBException {
Field[] fieldsToInsert = t.getClass().getDeclaredFields();
//code to create academic or event in database
}
}
//Concrete DAOs
public class AcademicDAO extends BaseDAO<AcademicDTO> {
//provide implementation
}
public class EventDAO extends BaseDAO<EventDTO> {
//provide implementation
}
//Transfer object
public class AcademicDTO extends BaseDTO {
String title;
String surname;
//getters and setters
}
public class BaseDTO {
protected Integer ID;
public Integer getID() {
return ID;
}
public void setID(Integer ID) {
this.ID = ID;
}
}
Hello Guys, I have a sample code on me that follows the above structure to create a small java application to manage academics and events. It is leniently following this pattern
1- You experts are familiar with this pattern more than me. I would like to understand why generics are used in this case so DAOs can extend and implement a generic base class. It would be great if one can show how generics here may be advantageous using an example.
2 - I have also witnessed the use of java Fields. Is there a link between generics and Fields?
I would like to document DAO pattern in an academic report, but I am finding difficult to understand how Generics and Reflect Field play a part here. Do they support flexibility and loose coupling?
The code you've provided is reusable set of logic to load and persist entities. Many times, in an application of non-trivial size, you'll wind up persisting many different types of objects. In this example, you can define as many objects as necessary, but only define the logic to actually save and load once. By asking the DTO what Field objects are there, it can get at the data to help construct queries for loading and saving.
Generics allow you to use this pattern while maintaining type safety. AcademicDAO can only handle AcadmeicDTO. You can't use AcademicDAO to store EventDTO. Generics allow the instance of the class to rely on a more specific type when dealing with the Field objects. If you didn't have generics, the BaseDAO would take Object, and you wouldn't be able to access any methods except those that Object provides because the JVM wouldn't know what class is provided, so it has to limit it's knowledge to that of Object. Using getClass().getDeclaredFields() bypasses that limitation because getClass() returns the actual class of the Object parameter.
Field is just a way to use reflection to access the values of the properties in each DTO. If you had to access the fields directly, with getTitle(), you couldn't reuse a generic base class to do your persistence. What would happen when you needed to access EventDTO? You would have to provide logic for that. Field allows you to skip that logic.
Edit:
To explain what I mean by accessing getID, you could do the following within BaseDAO because T is known to be a BaseDTO with a getID() method defined:
public abstract class BaseDAO<T extends BaseDTO> {
public boolean update(T t) throws DBException {
Integer id = t.getID();
Field[] fields = t.getClass().getDeclaredFields();
// Assuming you have a db object to execute queries using bind variables:
boolean success = db.execute("UPDATE table SET ... WHERE id = ?", id.intValue());
return success;
}
}
If you had this instead (in a non-generic class):
public boolean update(Object o) throws DBException {
// This line doesn't work, since Object doesn't have a getID() method.
Integer id = t.getID();
Field[] fields = o.getClass().getDeclaredFields();
boolean success = db.execute("UPDATE table SET ... WHERE id = ?", id.intValue());
return success;
}
You'd have to look through those Field objects, or ask for the ID field and assume it existed.
For question 1. The use of generics allows the same implementations of update and create to be used regardless of the type of the DTO. Consider if you didn't use generics. Then the best you could do for the parameter type of update would be BaseDTO, but then you could call
academicDAO.update( eventDTO )
which doesn't make sense. With the code as you have it, this would be a type error. So the main advantage is: better type checking.
For question 2. The use of Fields allows a single implementation of update and create to work on DTO object of various concrete types.
I have in my application three classes User, Group, Company which do not belong to the same inheritance tree, as their names reveal. Each class has a constructor which receives a number of (different) parameters i.e: User(String name, String password, int type), Group(String name, String name), Company(String name, int employees, boolean isValid). The number of the paraameters that each constructors requires is not the same for all the classes. I have created a class ReadDataFromFile to read some data from txt files and to create new Objects passing the data as paaraameters to the above constructors. The code of this class is apparently the same for every type, except for one method which creates the objects. Consequently it is not appropriate to create three distinct classes, but I had better to aim at a better design approach.
My question is whether the opportune design on this occasion is a Generic class, or an abstract class and implementing in its subclass the one method which differs createObject(), assuming that the necessary data coming from the txt file are put into a String array with differnt length for each type. I would like to follow the approach of Generic class: class ReadDataFromFile<T>{} , but I cannot find how I should handle the different types, since each one requires a call of a different constructor. Should I check for the type with instanceof? Should I pass to the method the class of each object? Or is there a better way?
Do not understand why you have posed the question as "abstract or generic" it looks like the common solution would be both.
public abstract class ReadFromFile<T> {
public T readFile(File file) {
String[] rawInput = doSomeStuffCommonToAll();
return constructObject(rawInput);
}
abstract T constructObject(String[] rawInput);
}
public class UserFileReader extends ReadFromFile<User> {
#Override
User constructObject(String[] rawInput) {
return new User(rawInput[0], rawInput[1], Integer.parseInt(rawInput[2]);
}
}
Create your objects based on conditions, for example the "instanceof" validation:
if (objectData instanceof User){
User = new User();
user.setName(objectData.getString(1));
} //...
I think I would choose an abstract design and for instance make use of the abstract factory pattern.
The answer in short, is neither :) Yes you do need abstraction, but it does not have to be of the subclassing form you seem to be leaning towards. Prefer composition over inheritance?
Long answer :) I do not know your domain exactly, but from what you have written I'm assuming you have three files, users.txt, groups.txt and companies.txt, with a shared format but with different data - something like CSV. So you can achieve abstraction through composition by doing something like this, which should illustrate the point even if my assumptions are wrong.
public class FileReader {
public static void read(File f, RowHandler rowHandler) {
//read each line, convert its contents to a map, and pass it to rowHandler
}
}
where
public interface RowHandler {
void handle(Map<String,String> row);
}
This means you separate the reading and parsing of each line from what do to with each parsed line.
To create User objects you could do:
public class UserConstructor implements RowHandler {
private List<User> users = new ArrayList<User);
public void handle(Map<String,String> row) {
users.add(new User(row.get("name"), row.get("password"), Integer.parseInt(row.get("type)));
}
public List<User> getUsers() {
return users;
}
}
And then you connect it all by doing
UserConstructor uc = new UserConstructor();
FileReader.readFile(new File("users.txt), uc);
List<User> users = uc.users();
You use the class name ReadDataFromFile. This name suggests a single purpose, but your question suggests you're mixing another concern into it - so it reads files and creates objects. ReadDataFromFile should just read data from file, and pass the data to another class to implement a strategy to do something with it.
Thats what the above design attempts to do - keep concerns separate.
I can't find a simple way to add a custom field during serialization in Gson and I was hoping someone else may be able to help.
Here is a sample class to show my issue:
public class A {
String id;
String name;
...
}
When I serialize class A I would like to return something like:
{ "id":"123", "name":"John Doe", "url_to_user":"http://www.example.com/123" }
where url_to_user is not stored in my instance of class A, but can be generated with data in the instance of class A.
Is there a simple way of doing this? I would prefer to avoid writing an entire serializer just to add one field.
Use Gson.toJsonTree to get a JsonElement, with which you can interact dynamically.
A a = getYourAInstanceHere();
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(a);
jsonElement.getAsJsonObject().addProperty("url_to_user", url);
return gson.toJson(jsonElement);
Well, the top rated answer is quite a quick one and not essentially bad when you are lacking much time but here is the problem: There is no proper separation of concern
You are modifying the serialized JSON at the same place where you are writing your business logic. You should be doing all the serialization inside of a TypeAdapter or a JsonSerializer.
How can we maintain a proper separation of concern?
The answer wraps around a bit of additional complexity but the architecture demands it. Here we go(taken from my other answer):
First, we would be using a custom serializer for the type. Second, we would have to create a copy constructor inside the base class and a wrapper subclass as follows:
Note: The custom serializer might seem like an overkill but trust me, it pays off in long run for maintainability.
.
// Lets say the base class is named Cat
public class Cat {
public String name;
public Cat(String name) {
super();
this.name = name;
}
// COPY CONSTRUCTOR
public Cat(Cat cat) {
this.name = cat.name;
}
#Override
public String sound() {
return name + " : \"meaow\"";
};
}
// The wrapper subclass for serialization
public class CatWrapper extends Cat{
public CatWrapper(String name) {
super(name);
}
public CatWrapper(Cat cat) {
super(cat);
}
}
And the serializer for the type Cat:
public class CatSerializer implements JsonSerializer<Cat> {
#Override
public JsonElement serialize(Cat src, Type typeOfSrc, JsonSerializationContext context) {
// Essentially the same as the type Cat
JsonElement catWrapped = context.serialize(new CatWrapper(src));
// Here, we can customize the generated JSON from the wrapper as we want.
// We can add a field, remove a field, etc.
// The main logic from the top rated answer now here instead of *spilling* around(Kindly ignore the cat having a url for the sake of example)
return catWrapped.getAsJsonObject().addProperty("url_to_user", url);
}
}
So, why a copy constructor?
Well, once you define the copy constructor, no matter how much the base class changes, your wrapper will continue with the same role. Secondly, if we don't define a copy constructor and simply subclass the base class then we would have to "talk" in terms of the extended class, i.e, CatWrapper. It is quite possible that your components talk in terms of the base class and not the wrapper type.
I've noticed BlazeDS has certain things it does not support and it is often difficult to find this out. Ex: polymorphism is not. One must create methods with different names as methods with the same name with different parameters create a conflict.
I'm trying to find out if BlazeDS does not support Java static and non-static inner classes.
Details of an example pointing out the issue:
public class UserDTO {
private String name;
private AddressDTO adddress;
private PhoneDTO phone;
....
public static class PhoneDTO {
private String phoneNumber;
.....
}
public class AddressDTO {
private String address;
.....
}
This code appears to work fine for passing data to Flex via BlazeDS but results in errors when passing the data from Flex via BlazeDS back to Java.
#Service
#RemotingDestination(channels = { "my-amf" }, value = "UserService")
public class UserService {
....
public UserDTO getUser(Long userID) {
.....
return userDTO;
}
public void updateUser(UserDTO userDTO) {
....
}
public void updatePhone(PhoneDTO phoneDTO) {
.....
}
The example code above will compile and the getUser method will work. A call to the updateUser or updatePhone methods on the other hand results in a BlazeDS error. Is there a special way to use inner classes in Flex or are inner classes not supported?
Here is an example of the error messages produced:
[BlazeDS]Cannot create class of type 'com.test.dto.UserDTO.PhoneDTO'.
flex.messaging.MessageException: Cannot create class of type 'com.test.dto.UserDTO.PhoneDTO'. Type 'com.test.dto.UserDTO.PhoneDTO' not found.
Example Flex code:
var thisPhone:PhoneDTO = new PhoneDTO();
thisPhone.phoneNumber = "8885551212";
updateTagsResult.token = userService.updatePhone(thisPhone);
As for the static classes, I'm also very skeptical that they can be used as well. Static classes are possible in Actionscript, but only in the same file (private static) and I don't believe AMF3 supports it.
The purpose of AMF3 is just to have simple property to property serialization between classes. Anything more complex than that is hard to transfer over and frankly, shouldn't be done in the first place because the complexity will, in all probability, affect your development. This is why Java has DTOs. Abstract data objects that can be transferred to any languages using your choice of data protocol.
Inner Classes
No, sending an Actionscript object aliased to a Java inner class (static or otherwise) is not supported out-of-the-box.
As you've seen, when the AMF packet is deserialized, the class name is interpreted as an outer class, rather than as an inner class.
However, you could implement this yourself by having your classes implement IExternalizable. (See here for further information)
An alternative to IExternalizable is to use an approach similar to this one, which provides support for Java Enum's to be sent across to Flex. They use a custom deserializer endpoint.
In the interests of completeness, I should point out that serializing Actionscript inner classes is supported, however the [RemoteClass] metatag is not. Instead, inner classes must be explicitly registered using registerClassAlias, normally within a static method of the outer class.
Polymorphism
To correct a point in the original post:
.... Ex: polymorphism is not. One must create methods with different names as methods with the same name with different parameters create a conflict.
Given that BlazeDS is a server-side product, I'm assuming that you're referring to the way BlazeDS handles Polymorphism & overloading in Java. In which case, your statement is incorrect.
For example, the following code is valid:
#RemotingDestination
public class EchoService {
public String echo(String source)
{
return "Received String";
}
public Object echo(Object source)
{
return "Recieved object of type " + source.getClass().getName();
}
Executed as follows:
remoteObject.echo("Hello") // result from service is "Received String"
remoteObject.echo(new Date()) // result from service is "Received object of type java.util.Date"
However, this is not an example of polymoprhism, as your question states. This is method overloading, which is different.
Polymorphism is supported, as shown here:
// Java
// This method on EchoService
public String echo(Employee employee)
{
return employee.sayHello();
}
public class Employee {
public String sayHello() {
return "Hello, I'm an employee";
}
}
public class Manager extends Employee {
#Override
public String sayHello() {
return "Hello, I'm a Manager";
}
}
Executed as follows:
// In flex...
remoteObject.echo(new Employee()) // Recieves "Hello, I'm an employee"
remoteObject.echo(new Manager()) // Recieves "Hello, I'm a Manager"
If we remove the echo(Employee employee) method, then the result is:
// In flex...
remoteObject.echo(new Employee()) // Recieves "Recieved object of type Employee"
remoteObject.echo(new Manager()) // Recieves "Recieved object of type Manager"