Domain to Model classes - java

I am writing some code that will serve a website and I have some questions about my "architecture".
Domain I have a database and and at the lowest level I have the **Domain* *package that contains the classes that represent the tables of the database. I use Hibernate and lazy fetch for relationships.
Access This package has all the classes that perform database actions on the domains. I guess this is the equivalent of DAO. I get entries using the primary key, return all the entries in a table, perform a query on it. Everything is returns as a domain class or a collection of it.
Service This packages has the class (again related to a domain class each) that has more complex logic. It uses the Access package to get domain objects and transform them to model objects where model is what I call classes that represent an equivalent domain class but without the members that have relationships on them like *ToMany which would possibly have hibernate proxies that cannot be serialised and also make the object "heavier". In the future I might write custom methods/transformation to turn those collections of domain object to something descriptive for presentation but for now I disregarde them.
Model This package has the exact same number of classes as the Domain and like I mentioned is the a representation of the domain objects to something I can use for presentations, transmit, etc. (This is like parallel to the other hierarchy not part of the order.)
Servlet This packages contains all the Servlets for the websites and each servlet contains the code for something the website wants to do. It uses the service classes to get the data it wants to manipulate. The service classes will get the relevant domain objects and transform them to model objects which will be returned to the servlet classes that will perform the operations needed by the website request and then return to the website the data in JSON format.
So obviously I would like some feedback to this approach and my following thoughts.
1) I think the service classes should have only code having to do with transforming the domain object to a model object. I am thinking of using Dozer and just add code that might be needed for something more complex that Dozer can't do (basically the in the future bit). From what I saw since my model classes are basically domain classes without the heavy stuff and the members have the same name I don't even need annotations or xml.
2)In the Access I use as a parameter the base class of all domain classes so I can have an abstract class and implement all the common methods in there like so
public abstract class DomainAccess<T extends Domain> {
protected abstract Logger getLogger();
protected DatabaseFacade db;
protected Class<T> domainClass;
#Inject
public DomainAccess(DatabaseFacade databaseFacade, Class<T> domainClass) {
this.db = databaseFacade;
this.domainClass = domainClass;
}
#SuppressWarnings("unchecked")
public T fetchByPrimaryKey(Object primaryKey) {
return (T) db.find(domainClass, primaryKey);
}
// TODO This might be better to be used for complete comparison if expanded
public boolean exists(T object) {
return fetchByPrimaryKey(object.getPrimaryKey()) == null ? false : true;
}
public void save(T object) {
db.save(object);
}
public void merge(T object) {
db.merge(object);
}
public void delete(T object) {
db.remove(object);
}
public void saveOrUpdate(T object) {
if (exists(object)) {
merge(object);
} else {
save(object);
}
}
public void deleteByPrimaryKey(T object) throws EntityNotFoundException {
Object primaryKey = object.getPrimaryKey();
T objectToDelete = fetchByPrimaryKey(primaryKey);
if (objectToDelete == null) {
getLogger().debug("There was no entry found with primary key: " + primaryKey);
throw new EntityNotFoundException("No entry was found with specified primary key [" + primaryKey + "]");
} else {
getLogger().debug("Deleting entry with id: " + primaryKey);
delete(objectToDelete);
}
}
#SuppressWarnings("unchecked")
public List<T> getResultList(String hql, String... parameters) {
TypedQuery<T> query = db.createTypedQuery(hql, domainClass);
for (int i = 0; i < parameters.length; i++) {
query.setParameter(i + 1, parameters[i]);
}
return query.getResultList();
}
#SuppressWarnings("unchecked")
public T getSingleResult(String hql, String... parameters) {
TypedQuery<T> query = db.createTypedQuery(hql, domainClass);
for (int i = 1; i <= parameters.length; i++) {
query.setParameter(i, parameters[i - 1]);
}
return query.getSingleResult();
}
}
3) Similarly I think in the Service I think i shoud use the Model as a parameter like
public abstract class DomainService {
protected abstract Logger getLogger();
protected final Validator validator;
protected DomainService() {
// TODO this might be needed only for insertion so instead of a class member, maybe it's better to have it as
// a method variable?
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
this.validator = factory.getValidator();
}
/**
* Inserts an entry in the database for the object passes an an argument.
*
* #param object The object representing the entry to be inserted
* #throws ValidationException When the object doesn't pass the validation. i.e. a member value is not valid based
*/
//TODO handle validation exception with message
abstract public void insert(T object) throws ValidationException;
/**
* Deletes an entry from the database. A whole object of the appropriate type is passed as an argument which
* will be used as a storage/collection of the attributes of the entry by which the deletion can occur. Different
* implementations can use these attributes to performs filtering and collection of entries to be deleted.
*
* #param object An object representing the entry to be deleted.
*
* #throws EntityNotFoundException when no entry to be deleted is found
*/
// TODO remove TransactionRequiredException, IllegalArgumentException
abstract public void delete(T object) throws EntityNotFoundException;
/**
* Returns all the entries of the table.
*
* #return a list containing objects representing all the entries in the table.
*/
abstract public List<T> fetchAll();
}
So, in the servlet where I will have all the values for an object I will construct a member instance and then pass that down to the service which will transform it to a domain or use it to update an existing domain object (it was retrieved form the database for instance) and so on

Related

Strategy pattern, pass function into parent method

I would like to implement something like Strategy Pattern. I have generalized logic in Parent method, I need to pass specific logic (with casting etc..) into parent.
I have following classes:
class A{
public Object generateData(Function fetchData, AbstractForm form)
{
List<DataBean> dataBeans = (List<DataBean>) fetchData.apply(form);
//...
}
}
class B extends A{
void someMethod(AbstractForm form){
Function<AbstractForm, List<DataBean>> fetchFunction = new Function<AbstractForm, List<DataBean>>() {
//here goes form specific casting and other data fetch specific logic
return dataBeans;
}
super.generateData(fetchFunction, form);
}
}
Did I get the Idea of function correctly here?
Correct use of the Strategy pattern implies aggregation between a Context (in your case class A) and a Strategy (in your case an implementation of Function).
You can see the relationship in the image below (taken from the Gang of Four book, Design patterns: elements of reusable object-oriented software).
Below I've applied a traditional Strategy pattern approach to your problem. In this case I've made it so that Function.apply(AbstractForm) returns List<DataBean> to remove the need for casting. You could of course use generics to make Function more flexible.
Strategy
public interface Function {
List<DataBean> apply(AbstractForm form);
}
Context
public class A {
private Function fetchData; // strategy
public void setStrategy(Function fetchData) { // method for setting the strategy
this.fetchData = fetchData;
}
// precondition: fetchData != null
public Object generateData(AbstractForm form) {
List<DataBean> dataBeans = fetchData.apply(form); // using the strategy
return null; // whatever you want to return
}
}
In this case, extending class A is not neccessary as we can inject our Strategy (Function) using setStrategy(Function). However, we could always extend A to great an object with a predefined Strategy.
For example:
public class B extends A {
public B() {
setStrategy((form) -> null); // implement your concrete strategy here
}
}
Using a Factory Method
Since a Strategy for fetching the data is likely required and there may be no 'default' to use and may not ever change, the Factory method pattern could be used instead to enforce the creation of a Product (Function). Note class A is now abstract and includes a Factory method createFunction() which is then implemented in the subclasses (e.g. B) to create the Function.
The design for the factory method pattern can be seen in the UML below. In this case our Product is now what was previously our Strategy (Function) and the Creator is class A, with the ConcreteCreator being class B.
Creator
public abstract class A {
private Function fetchData; // product to be used
public class A() {
fetchData = createFunction(); // call factory method
}
protected abstract Function createFunction(); // factory method
// precondition: fetchData != null
public Object generateData(AbstractForm form) {
List<DataBean> dataBeans = fetchData.apply(form); // using the product
return null; // whatever you want to return
}
}
ConcreteCreator
public class B extends A {
#Override
protected Function createFunction() {
return (form) -> null; // return product
}
}
In this case the Product is fixed and not changable, but this could be overcome by mixing the two patterns together and including setStrategy(Function) again from class A in the first example.

From a generic manager class, how to access in a static way information about it's instances?

I am trying to create a online arena game where players can create custom arenas to play on. I wish to save the arena settings in a MySQL database so that it saves the arena for further playing.
The catch is, there are different variations of Arenas. So there can be jungle arenas, desert ones, etc. All of these different variations (subclasses of the abstract class Arena) must be stored in different tables since the variables (and thus the columns) are different for each type of arenas.
My question is : from the Manager class described below containing an array of a generic type, how can I get the required columns from the child (T) class and it's parent. I am using a generic type because I also want to use this class for managing player's informations (which also need to be stored in a database) later.
Here is the Manager class:
public class Manager<T extends Savable> {
private Connection connection;
private List<Column<?>> columns;
private List<T> instances;
public Manager() {
fillColumnArray()
try {
connection = getSQLConnection();
Statement s = connection.createStatement();
s.executeUpdate(getCreateQuery())
s.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public void fillColumnArray() {
// Somehow, manages to get the needed columns from
// the parent class and the child class
}
public Connection getSQLConnection() {
// Creates a mysql connection to a database
// from parameters on a local file and returns it
}
public String getCreateQuery() {
// Creates the query from the previously found columns
}
/* */
}
Here is the Column class used in the Manager:
public class Column<U> {
private String name;
private U defaultValue;
/* */
}
And here are possible variables for the Arena class and one possible children
public abstract class Arena implements Savable {
private Vector centerPosition;
private int radius;
private int gameLenght;
/* */
}
public class JungleArena extends Arena {
private int treeHeight;
private boolean daytime;
/* */
}
I thought of many different possibilities. One of them was to add a requestColumns() method in the Savable interface but this option doesn't work because upon creation of the Manager, I can only access the T class in a static way.
So then I thought of adding a static method requestColumns() inside both the child and the parent but since I am using a generic type, the compiler would not understand where the method comes from.
Then I thought of casting the T type to it's specefic Arena type but then it would not work further in my project when using the same class for storing players.
Hope this is clear enough.
Is anyone having an idea to make things work or just another way of doing things from your understanding?
Thanks
I'm not sure why you would need to do this statically considering you have the instance already and you can use the instance to get this information for you in a generic way. I'm also not clear how you intend to get the values for the columns from the class, this answer handles that if you haven't yet.
Personally, absent any worthy framework capable of this already, I'd define an annotation to put on the public getters of the column fields. Like so:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Column {
String name() default "";
}
You could then use reflection to get those getters and then invoke the methods on the instance thereby getting the values as well. For example, given this class:
class Entity {
...
#Column(name = "Name")
public getName() { return name; }
#Column(name = "Height")
public getHeight() { return height; }
}
I could get the column names and values like so:
Entity e = new Entity("First", 42);
Method[] methods = e.getClass().getMethods();
Map<String, Method> colums = new HashMap<>();
for (Method m : methods) {
Column c = m.getAnnotation(Column.class);
if (c != null) {
colums.put(c.name(), m);
}
}
colums.entrySet().forEach(entry -> {
try {
System.out.println(entry.getKey() + ": " + entry.getValue().invoke(e));
} catch (IllegalAccessException | InvocationTargetException e1) {
e1.printStackTrace();
}
});
Output >
Height: 42
Name: First

Creating multiple aliases for the same QueryDSL path in Spring Data

I have a generic Spring Data repository interface that extends QuerydslBinderCustomizer, allowing me to customize the query execution. I am trying to extend the basic equality testing built into the default repository implementation, so that I can perform other query operations using Spring Data REST. For example:
GET /api/persons?name=Joe%20Smith // This works by default
GET /api/persons?nameEndsWith=Smith // This requires custom parameter binding.
The problem I am having is that every alias of an entity path I create seems to override the preceding alias bindings.
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable>
extends PagingAndSortingRepository<T, ID>, QueryDslPredicateExecutor<T>, QuerydslBinderCustomizer {
#Override
#SuppressWarnings("unchecked")
default void customize(QuerydslBindings bindings, EntityPath entityPath){
Class<T> model = entityPath.getType();
Path<T> root = entityPath.getRoot();
for (Field field: model.getDeclaredFields()){
if (field.isSynthetic()) continue;
Class<?> fieldType = field.getType();
if (fieldType.isAssignableFrom(String.class)){
// This binding works by itself, but not after the next one is added
bindings.bind(Expressions.stringPath(root, field.getName()))
.as(field.getName() + "EndsWith")
.first((path, value) -> {
return path.endsWith(value);
});
// This binding overrides the previous one
bindings.bind(Expressions.stringPath(root, field.getName()))
.as(field.getName() + "StartsWith")
.first((path, value) -> {
return path.startsWith(value);
});
}
}
}
}
Is it possible to create more than one alias for the same field? Can this be accomplished in a generic way?
You can create a transient property bound to QueryDSL this way:
#Transient
#QueryType(PropertyType.SIMPLE)
public String getNameEndsWith() {
// Whatever code, even return null
}
If you are using the QueryDSL annotation processor, you will see the "nameEndsWith" in the metadata Qxxx class, so you can bind it like any persisted property, but without persisting it.

Hibernate check deletion constraints

I am using Spring - Hibernate to control models in my application. The models are linked to each other (one-to-many, many-to-many, almost kinds of relationships), and now I have a problem when deleting one entity which is being used by other entities. The problem is I want to show the detail message that informs exactly what other objects (type, name) are using the entity that I am going to delete. It's not the common message about Constraint violation that Hibernate throws me.
For example: Car --> Person, House --> Person; then when I delete one Person who has a car and house, the message will show "There are Car (named Ford Mustang) and House (named MyHouse) linked to this Person".
1. So is there any method from Hibernate support this requirement? I guess there's no implementation for this specific requirement.
2. If not any utility available for this problem, I am thinking about below solutions:
- in each entity class (i.e Person), I will define all checking method that detect linking from the this entity to other entities, for example:
class Person {
// Properties
// Checking methods, return type and name of linked objects
public Map<String, String> getLinkedCars() {
// Query to DB to get linked cars
// return a Map contain Class name along with object name <Car, Ford Mustang>
}
public Map<String, String> getLinkedHouses() {
// Query to DB to get linked houses
// return a Map contain Class name along with object name <House, MyHouse>
}
}
-and then, in service before deleting Person entity, I will use reflection mechanism to collect results from checking methods (whose name is started with "getLinkedXXX"), and build the detail error messages.
So is this solution good? About the performance, and the convention of MVC (because I have to query data inside model class)?
Thank you for your help.
One (not so simple) approach is to scan your entity class for #OneToMany or #ManyToMany annotated fields and perform checking so neat error message can be provided to user. Following sample code assumes you only annotate the field, not the getters method, eg:
public class Person {
#OneToMany(..)
private List<House> houses;
//...
}
First get the list of all fields using reflection:
Fields[] fields = Person.class.getDeclaredFields();
Then iterate and check for #OneToMany or #ManyToMany annotations
for(Field f : fields) {
if( f.getAnnotation(OneToMany.class) != null ||
f.getAnnotation(ManyToMany.class) != null) {
// Here you know f has to be checked before the person is deleted ...
}
}
The value of a field of a particular person object can be obtained using:
Person p = // fetch a person ..
Field f = // assume f is the "List<House> houses" field
List<House> houses = (List<House>) f.get(p);
I had a similar problem, I had to check if an entity could be safely deleted to avoid foreign key constraint violations. This is how I solved:
First, I created an annotation to mark the entity that needs to be checked before deletion:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Constraint(validatedBy = SafeDeleteValidator.class)
public #interface SafeDelete {
String message() default "{lima.jefferson.SafeDelete.message}";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Then I created another annotation to be applied to any method that will be used to check if the entity can be deleted:
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
#Documented
public #interface CheckForDelete {
}
In the entity class I used these annotations like this:
#SafeDelete(message = "Couldn't delete this entity due to...")
public class MyEntity {
#CheckForDelete
public Boolean checkForDelete() {
// Insert your business logic here
return true;
}
}
And finally, the validator for the SafeDelete annotation:
public class SafeDeleteValidator implements ConstraintValidator<SafeDelete, Object> {
#Override
public void initialize(SafeDelete constraintAnnotation) {
}
#Override
public boolean isValid(Object object, ConstraintValidatorContext context) {
Method[] methods = object.getClass().getMethods();
return Arrays.stream(methods)
.filter(m -> m.getAnnotation(CheckForDelete.class) != null)
// Deal with the exception here
.map(m -> (Boolean) m.invoke(object))
.reduce(true, (a, b) -> a && b);
}
}
Then you can follow the answer of this question to apply the validation to deletion only.

How do Generics and Fields assist DAO Pattern in Standalone Java applications

//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.

Categories