
Originally Posted by
constv
So, your command object is passed to the controller upon the submission of the view. The task of the controller now is to convert the data from the received command object into a domain-specific object (not presentation-tier-specific) and pass it on to the middle-tier service (again, a non-presentation-tier-specific POJO) that performs the business operation on that data (i.e implements a specific use case.) ... Never pass Command objects to a business service! Command objects themselves, however, may nest generic business domain objects, but not the other way around.
I've had a look at the JPetStore example and I see how your comment reflects with the example.
I was wondering, isn't this a bit of an overkill? The way I look at it now is that one would have a Command object, a Data Transfer Object and an Entity object. The web form data is mapped to a Command object. Then you map the Command object to a Data Transfer object that is then fed through to the Service layer. If it is a Rich Domain design, the DTO would then be fed to the Entity object where the business rules are kept and use the data from the DTO.
I see from your comment and the JPetStore example that you can encapsulate Business objects within a Command object. To me, I would never refer to a Business object from within the Presentation layer, full stop.
Wouldn't it be more efficient to, say, have a DTO that the Service layer and the Domain objects/entities can understand and work with. This way, the Domain objects/entities are never visible to the Presentation layer?
For my next question I'll be open to opinion on this. If the Presentation layer can only talk to the Services using DTO with the example I've provided, is it safe to use the same DTO as a Command object?
So, as a (high level) example I would implement it as:
The DTO...
Code:
package org.mydomain.example.domain.blog;
public class BlogForm {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
The Domain entity...
Code:
package org.mydomain.example.domain.Blog
import java.util.Date;
import org.mydomain.example.dao.blog.BlogDao;
public class Blog {
private BlogDao blogDao;
..
// Other properties can be provided.
private String name;
private Date datePosted;
..
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getDatePosted() {
return this.datePosted;
}
public void setDatePosted(Date datePosted) {
this.datePosted = datePosted;
}
..
public void post(BlogForm blogForm) {
// A very basic business rule.
..
this.setName(blogForm.getName());
this.setDatePosted(new Date());
..
this.blogDao.save(this);
}
..
}
The Service interface...
Code:
package org.mydomain.example.service;
public interface BlogService {
abstract void postBlog(BlogForm blogForm);
}
The Service implementation...
Code:
package org.mydomain.example.service.standard;
import org.mydomain.example.domain.DomainFactory;
import org.mydomain.example.domain.blog.Blog;
import org.mydomain.example.domain.blog.BlogForm;
import org.mydomain.example.service.BlogService;
public class StandardBlogService implements BlogService {
private DomainFactory domainFactory;
..
public void postBlog(BlogForm blogForm) {
// A very basic business workflow.
Blog blog = DomainFactory.newBlog();
..
blog.post(blogForm);
..
}
}
The controller...
Code:
package org.mydomain.example.application;
import org.mydomain.example.domain.blog.BlogForm;
import org.mydomain.example.service.BlogService;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
public class PostBlogController extends SimpleFormController {
private BlogService blogService;
..
public ModelAndView onSubmit(Object command) {
..
this.blogService.postBlog((BlogForm) command);
..
return new ModelAndView(this.getSuccessView());
}
}
Shah.