Given a generic tree based (Java) data model. Let's say
abstract class XModel {
long id;
XModel parent;
}
class ProjectModel extends XModel {
String customer;
}
class FileModel extends XModel {
String name;
}
class FolderModel extends XModel {
String name;
String attributes;
}
My challenge is to make sure that FileModels are only used in FolderModels (or PrjectModels) and FolderModels are only used in ProjectModels.
Since the model should be extensible - is there any generic way to do this constraint validation (like XML Schema does) without hardcoding the parent-child-realtions in a validation method?
I'm not sure how useful it would be - depends on how you create the tree, but this might work:
abstract class XModel<T extends XModel> {
long id;
T parent;
}
class ProjectModel extends XModel { ... }
class FolderModel extends XModel<ProjectModel> { ... }
class FileModel extends XModel<FolderModel> { ... }
UPDATE
To separate validation logic from model itself you could use some runtime validators like Hibernate or Spring validators.
I would use generics and interfaces that describe the restrictions
interface Model {
}
abstract class AbstractModel<P extends Model> implements Model {
Long id;
P parent;
}
class ProjectModel extends AbstractModel implements HasFileModel,
HasFolderModel {
}
interface HasFileModel extends Model {
}
static class FileModel extends AbstractModel<HasFileModel> {
}
interface HasFolderModel extends Model {
}
class FolderModel extends AbstractModel<HasFolderModel> implements
HasFileModel {
}
This way the child only restricts the parent to an interface not a concrete type
If you don't want to put those constraints into code, you'd have to write a validation method that is fed by some external data yourself. AFAIK there's no such built in option (in the compiler) besides using Generics, which would require you to express the constraints in code.
Related
Since an abstract class can contain both complete and incomplete methods, when is it necessary to implement an interface? When should it implement an interface in an abstract class?
It is a standard way of how OOP works. Imagine a class Human. It is of course abstract as there can not be a concrete instance of a human. A concrete implementation could for example be a class Person that requires a name and some other information.
public class Person extends Human {
String name;
int age;
}
A common usage of interfaces is to describe abilities. In our example we could have interfaces like CanWalk, CanBreath, CanJump, NeedsWater, HasGender and so on. In such a case a Human could implement all of these interfaces, it would be perfectly fine.
public abstract class Human implements CanWalk,
CanBreath, CanJump, NeedsWater, HasGender {
...
}
Those interfaces now have methods, like
public interface HasGender {
String getGender();
}
and Human may implement them, but as an abstract human has no concrete gender, it may delegate the implementation to its implementing class Person:
public class Person extends Human {
String name;
int age;
String gender;
#Override
public String getGender() {
return gender;
}
}
On the other hand there might be interfaces where Human can offer an implementation, like
public interface NeedsWater {
int amountOfWaterNeeded();
void drink(int amount);
}
public abstract class Human implements CanWalk,
CanBreath, CanJump, NeedsWater, HasGender {
#Override
public int amountOfWaterNeeded() {
return 10;
}
}
Finally we may have classes that work with interfaces. Like
public class WaterDistributor {
public void distributeWaterTo(Iterable<NeedsWater> consumers) {
for (NeedsWater c : consumers) {
c.drink(c.amountOfWaterNeeded());
}
}
}
And you want to be able to pass your humans to that method, so you need to implement the interface.
I have the following class structure (it actually is a VO layer with Hibernate mappings):
public abstract class abstractClassVO {
private int id;
private String name;
}
public class concreteClassAVO extends abstractClassVO {
private String aAttribute;
}
public class concreteClassBVO extends abstractClassVO {
private Long bAttribute;
}
And the equivalent DTO objects:
public abstract class abstractClassDTO {
private int id;
private String name;
}
public class concreteClassADTO extends abstractClassDTO {
private String aAttribute;
}
public class concreteClassBDTO extends abstractClassDTO {
private Long bAttribute;
}
Then I have another object like this:
public class compositeObject {
private int anAttribute;
private abstractClassVO myInstance;
}
and its equivalent:
public class compositeObjectDTO{
private int anAttribute;
private abstractClassDTO myInstance;
}
How can I tell dozer to automatically map myInstance to the specific DTO that corresponds to the concrete class implementation in the VO layer?
Currently, out of the box, Dozer isn't even putting anything in the myInstance field of the compositeObjectDTO class. My guess is that it's due to the fact that abstractClassDTO it is an abstact class, and since it cannot determine the implementation, it does nothing. I am not getting any exceptions.
Dozer can't do it out of the box but you could write a helper that would determine destination class by source class. You can get this information from DozerBeanMapper.getMappingMetadata().getClassMappings* methods. These methods return list of ClassMappingMetadata that contains destination class. You just only need to chech whether destination class is inherited from abstractClassDTO. This check can be omitted if you only have one mapping for one VO.
For bi-directional mapping you should additionally check ClassMappingMetadata.MappingDirection field.
At this moment I start work on small web application based on MVC.
Now I try implement main classes for Model layout using DAO pattern.
So, first of all I create two entity classes (for example): Author and Book:
package myProject.model.entity;
import java.io.Serializable;
public class Author implements Serializable {
private static final long serialVersionUID = 7177014660621405534L;
private long id;
private String firstName;
private String lastName;
public Author() {
}
// getter and setter methods here
}
and Book class:
package myProject.model.entity;
import java.io.Serializable;
public class Book implements Serializable {
private static final long serialVersionUID = 7177014660621405534L;
private long id;
private String title;
private String description;
public Book() {
}
// getter and setter methods here
}
On next step, I see, that classes Book and Author both have getId() and setId().
so, I create interface Persistent for my Entity classes:
package myProject.model.entity;
public interface Persistent {
public long getId();
public void setId(long id);
}
So, first my question:
It is correct implementation for model package?
On the next step, I start implement classes for package dao.
package myProject.model.dao;
import java.util.List;
import myProject.model.entity.Persistent;
public interface Dao {
Persistent get(long id);
void save(Persistent persistent);
void delete(long id);
}
Next step: create interfaces AuthorDao and BookDao, that extend base dao interface Dao
But both interfaces: AuthorDao and BookDao - at this moment empty.
What do you think - it in normal, that interfaces empty? It is my second question.
And on the last step I create package model.dao.hibernate and add to the package to class AuthorDaoHibernate and BookDaoHibernate - both class implements AuthorDao and BookDao interfaces.
And My main question now:
my interface Dao work with objects type Persistent and I dont use Generics. And all ok and nice.
What do you thinks - what benefits I have, if I re-work Dao interface wit Generics:
package myProject.model.dao;
import java.util.List;
import myProject.model.entity.Persistent;
public interface Dao<Persistent> {
T get(long id);
List<T> getAll();
void save(T persistent);
void delete(long id);
}
My Dao classes work only with persistent entities - no any other object type...
Do you really any reasons in me case use Generics?
Generics can greatly improve code readability and reduce errors that could come from wrong casting.
We're using something similar to what you described (note that there are interfaces and implementations needed).
Here's a basic example (I'll leave the getters and setters out for brevitiy):
#MappedSuperClass
class BaseEntity {
#Id
private int id;
}
#Entity
class UserEnity extends BaseEntity {
//user stuff like name
}
class BaseDAO<T extends BaseEntity> {
public T findById(int id) {
...
}
//other generic CRUD methods
}
#Stateless
class UserDAO extends BaseDAO<UserEntity> {
//additional user specific methods
}
Using UserDAO would then be like this:
UserDAO userDao; //some injection or lookup
//no explicit cast needed here, thanks to generics
UserEntity user = userDao.findById(userId);
//compiler error due to the generic parameter being UserEntity and AnotherEntity doesn't extend that
AnotherEntity a = userDao.findById(someId);
If you want to use generics you should define Dao as following:
public interface Dao<T extends Persistent> {
.....................
void save(T persistent);
...................
}
Now when you extend it you will have to create save that accepts Book only:
public class Book extends Dao<Book> {
.....................
void save(Book persistent);
...................
}
The benefit here is that you cannot pass Author to BookDao. This will not pass compilation.
BTW if you are using Hibernate, JPA or other ORM solution you do not really have to create DAO per entity. One generic dao can solve all your needs.
There is no reason here. If it's unique, it's not generic, by definition !
List getAll() will do the Job.
The ArrayList is Generic because it will sometimes return Persistent, sometime President.
currently I'm trying to implement a typed generic DAO.
I do not even get to compile anything, since NetBeans complains about UserDAOHibernate
interface expected here
type argument User is not within bounds of type-variable ENTITY
I'm afraid there is some obvious mistake in how I use inheritance/interfaces, since I'm rather new to Java.
Here's some stripped down code
public interface GenericEntity<ID extends Serializable> {
public abstract ID getId();
public abstract void setId(final ID id);
}
public abstract class LongEntity implements GenericEntity<Long> {
protected Long id;
public Long getId();
public void setId(final Long id);
}
public class User extends LongEntity implements Serializable {
private String name;
private String password;
private Customer customer;
}
public interface GenericDAO<ENTITY extends GenericEntity<ID>, ID extends Serializable> {
public abstract ENTITY findById(ID id);
public abstract List<ENTITY> findAll();
public abstract ENTITY makePersistent(ENTITY entity);
public abstract void makeTransient(ENTITY entity);
}
public abstract class GenericHibernateDAO<ENTITY extends GenericEntity<ID>, ID extends Serializable>
implements GenericDAO<ENTITY, ID> {
}
public class UserDAOHibernate implements GenericHibernateDAO<User, LongEntity> {
}
Is it that LongEntity should extend GenericEntity<Long>? If so, how would I do this with Java's single level or inheritance?
Is this layered approach a bad example to follow? All my entities need an id and this implementation could easily be reused lateron with different id types, so I thought I might use it.
The error comes from here:
public class UserDAOHibernate implements GenericHibernateDAO<User, LongEntity> {
}
You've specified that GenericHibernateDAO's ID parameterized type is bounded by <ID extends Serializable>.
LongEntity extends GenericEntity, and hence, why you have a type mismatch.
Also, GenericHibernateDAO is an abstract class (and not an interface), so you'll need to extends instead of implements.
The correct solution should be:
public class UserDAOHibernate extends GenericHibernateDAO<User, Long> {
}
Dynamic Inheritance
I have a situation where I want a class (which is a JPA entity) to be able to extend either class A or class B dynamically. My thought was to use Generics, but it looks like generics doesn’t support this. For example:
#Entity
public abstract class Resource() {
...
}
#Entity
public abstract class Snapshot() {
...
}
public abstract class CommonRS<R extends Resource, S extends Snapshot> {
/* This is the class that I want to dynamically assign Inheritance to. */
...
}
#Entity
public class FeedResource extends CommonRS<Resource> {
...
}
#Entity
public class FeedSnapshot extends CommonRS<Snapshot> {
...
}
The reason I want to do this is that FeedResource must Inherit from Resource and FeedSnapshot must inherit from Snapshot because both classes are using the JPA join strategy InheritanceType.JOINED and are persisted to different tables, however they both share common attributes and I would like them to be able to inherit those common attributes.
I understand that I can I could use #Embeddable on CommonRS and the Embed it in both FeedResource and FeedSnapshot.
Since Java doesn’t support multiple inheritance, I can’t see any other way to do this other than using Embeddable.
Thanks in advance.
Here is how you do it
#MappedSuperClass
public abstract class Base() {
...
// put your common attributes here
}
#Entity
public abstract class Resource() extends Base{
...
}
#Entity
public abstract class Snapshot() extends Base {
...
}
public abstract class CommonRS<R extends Base> {
...
}
#Entity
public class FeedResource extends CommonRS<Resource> {
...
}
#Entity
public class FeedSnapshot extends CommonRS<Snapshot> {
...
}
UPDATE
Another solution can be implementing same interface (if common inheritance cannot be achieved). In that case #MappedSuperClass annotation should be used on actual base classes.
#Entity
public abstract class Resource() extends BaseIntf {
...
}
#Entity
public abstract class Snapshot() extends BaseIntf {
...
}
public abstract class CommonRS<R extends BaseIntf> {
...
}
#Entity
public class FeedResource extends CommonRS<Resource> {
...
}
#Entity
public class FeedSnapshot extends CommonRS<Snapshot> {
...
}