Results 1 to 10 of 13

Thread: Service + Web architecture questions

Hybrid View

  1. #1
    Join Date
    Mar 2009
    Posts
    15

    Default Service + Web architecture questions

    Two Questions:

    (1) In desinging a the service layer, I find myself hesitant exposing my domain objects to the user
    - Why? Some domain objects, (ie. Lease) have an expiry date(or any other attrib, hashed password) set by the service (biz logic). When a user queries a Lease, he can now modify the domain object then persist with a different expiry date.
    - I am hesitatnt to put in checks to make sure the date's haven't been tampered with. And if there is a lot of stuff,
    - Should I
    [a]: Only pass in String,Date,int... values into the service and not the objects? Bascially the values that need to change + the id of the Object.
    [b]: Some new DTO type object, that has those biz logic determined fields declared as immutable.


    (2) Package structure:
    - Constv give me some good structure hints for the service Tier. But what about the Controller/View layers?
    - com.company.web.controller is OK, but what is the most elegant way of organizing a package for a web app (spring web app)

    thanks!

  2. #2
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    ramoq,

    1) It seems, the issue here is to achieve a proper degree of object granularity. You can have some domain classes whose instances will only be constructed within the service - using the objects passed from the client. So, for example, you may have to split your Lease object in two, with proper names, where one (only modified by the service in the middle-tier) would have additional fields and nest the other whose data can be safely set in the front-end and passed to the service.

    2) About the package structure of a web application... I usually separate all classes into web-specific (UI related, MVC, webflow, servlets, etc.) and not web-specific. Then, just do whatever seems the most convenient and appropriate. Since, after you have extracted all your business components into separate functional modules, you are left with the web application as a single module, you can either group the classes by functionality - again, or by the type of work they do, e.g. validators, services, etc. There is no longer a danger of coupling unrelated components by making them all joint at some "persistence" package - because they all are integral part of the same application, anyway. if any distinct functional domains exist that are specific only to my web application, I usually create a namespace for each of them under com.mycompany.myapp.

    Assuming you use the standard Maven structure, you may have something like this, under your Java folder...

    com.mycompany.myapp.common (app-common useful interfaces, classes, utils)
    com.mycompany.myapp.order (app-specific order processing, not web UI)
    ----------------------------------.domain
    ----------------------------------.service
    ----------------------------------.service.dao
    ----------------------------------.validation
    ...
    com.mycompany.myapp.web
    ---------------------------------.springmvc
    ---------------------------------------------.errorresolvers
    etc.
    ---------------------------------.webflow
    -------------------------------------------.actions
    -------------------------------------------.listeners
    etc.

    Under Resources, you may have some of your properties files, templates, etc.

    Under webapp, you may have your JS files, CSS files, image files (if your app does no use those from some other location on the server), some index.jsp that redirects to your dispatcher servlet, and WEB-INF. Your JSPs will be under WEB-INF, of course. You'll also have some config folder with your spring config XMLs. Group Spring configuration by functionality as well.
    Something like that...

    HTH,
    C

  3. #3
    Join Date
    Mar 2009
    Location
    Brazil
    Posts
    25

    Default

    You can also define this as a invariant of the object. If there is a rule to only set the expiration date once, you can do something like it:

    setExpirationDate(Date date) {
    if(expirationDate != null) throw new BlaBlaBlaException("Expiration Date cannot be set twice");
    this.expirationDate == date;
    }

    getExpirationDate() {
    // return a copy of expirationDate to make sure the object is not changed.
    }
    Last edited by juk; Mar 11th, 2009 at 05:29 PM.
    Regards
    Juliano

  4. #4
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    Quote Originally Posted by juk View Post
    You can also define this as a invariant of the object. If there is a rule to only set the expiration date once, you can do something like it:

    setExpirationDate(Date date) {
    if(expirationDate != null) throw new BlaBlaBlaException("Expiration Date cannot be set twice");
    this.expirationDate == date;
    }

    getExpirationDate() {
    // return a copy of expirationDate to make sure the object is not changed.
    }
    I think ramoq meant that setting/modifying some data should only be controlled by the middle-tier service based on its internal business logic, not the client. So, just disallowing a property to be reset on a "lease" probably is not a good idea - especially, because that would mean hardcoding some very specific requirement into the "lease" concept. It is reasonable - and logical - to assume that an expiration date may be set, and then re-set on a lease, in general. So, the question is: who and when should be able to do it? It is up to the use case that defines the context in which the "lease" is used. The service in this case implements the use case that governs that particular requirement. This is a good example of how the domain entity/service model can be a natural (easy and intuitive, and more logical) alternative to the DDD approach from the Evans book - per our conversation in another thread. Such specifics should never be part of the object that defines the entity. I hope this somewhat illustrates the reasoning behind the points I was making.

  5. #5
    Join Date
    Mar 2009
    Location
    Brazil
    Posts
    25

    Default

    Quote Originally Posted by constv View Post
    I think ramoq meant that setting/modifying some data should only be controlled by the middle-tier service based on its internal business logic, not the client. So, just disallowing a property to be reset on a "lease" probably is not a good idea - especially, because that would mean hardcoding some very specific requirement into the "lease" concept. It is reasonable - and logical - to assume that an expiration date may be set, and then re-set on a lease, in general. So, the question is: who and when should be able to do it? It is up to the use case that defines the context in which the "lease" is used. The service in this case implements the use case that governs that particular requirement. This is a good example of how the domain entity/service model can be a natural (easy and intuitive, and more logical) alternative to the DDD approach from the Evans book - per our conversation in another thread. Such specifics should never be part of the object that defines the entity. I hope this somewhat illustrates the reasoning behind the points I was making.
    If there is not a rule (like only one Expiration Date change), it is not a business logic, is an infrastructure concern and you can take other solution to resolve it even in DDD (you are not forced to put everything into the objects).
    Regards
    Juliano

  6. #6
    Join Date
    Mar 2009
    Posts
    15

    Default

    So, for example, you may have to split your Lease object in two, with proper names, where one (only modified by the service in the middle-tier) would have additional fields and nest the other whose data can be safely set in the front-end and passed to the service.
    Constv, could you provide a basic example of this?

  7. #7
    Join Date
    Jan 2008
    Posts
    182

    Default

    Quote Originally Posted by ramoq View Post
    Two Questions:
    Two ideas:
    1) If you want some fields to not be updateable, but ok to be viewed then annotate the field with @Column(updateable=false)
    2) If you want different fields or some subset to be displayed then you need to have a different object as the forrm backing bean and map to the domain object. You can create a reflective utility to automate the mappings.

  8. #8
    Join Date
    Mar 2009
    Posts
    15

    Default

    I often see recomendations along these lines for directory/package structurues. Is this a good idea???? see below:

    core
    ---- src
    ---- ---- main
    ---- ---- test

    web <-- i'm assuming all controller releated items go in here?
    ---- src
    ---- ---- main
    ---- ---- test

    webapp
    ---- src
    ---- ---- resources
    ---- ---- ---- images
    ---- ---- ---- css
    ---- ---- ---- js
    ---- ---- war
    ---- ---- ---- WEB-INF
    ---- ---- ---- ---- jsp
    ---- ---- ---- META-INF

  9. #9
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    Quote Originally Posted by ramoq View Post
    I often see recomendations along these lines for directory/package structurues. Is this a good idea???? see below:

    core
    ---- src
    ---- ---- main
    ---- ---- test

    web <-- i'm assuming all controller releated items go in here?
    ---- src
    ---- ---- main
    ---- ---- test

    webapp
    ---- src
    ---- ---- resources
    ---- ---- ---- images
    ---- ---- ---- css
    ---- ---- ---- js
    ---- ---- war
    ---- ---- ---- WEB-INF
    ---- ---- ---- ---- jsp
    ---- ---- ---- META-INF
    Yes, this ("main/test", "src/resources/webapp" approach) is actually the de facto standard for the directory structure for modules - originally introduced by the Maven project. Except , instead of your "core" and "web" modules you should have any reusable modules with the functionality that should not be built into your [web] application but rather externalized. In other words, each module - in addition to your web application module - should represent a distinct functional domain, not just some core, UI, or persistence. Each such module should define its own model. service, and persistence classes, which would allow it to be fully independent and distributable with various applications, if necessary. Among these "external" modules there normally would be some kind of "commons" or "core" module that contains common interfaces, classes and utilities that may be used by any other modules. Each specific application is just another separate module in the project, and it will use other modules as dependencies (e.g. packaged as jars in the web app's war file.) This also allows you to have different project configurations, e.g. loading sources for some modules and using the others as jar dependencies, while other developers are working on updates to those modules. You will avoid the necessity of having a huge monolithic project with thousands of classes where nothing can be taken out and worked on independently. (That happens all the time!) I have tried to explain all that in some of my earlier posts.

    Your controllers and other web-app related java classes must live under the web application's modu;e's java/src/main tree. Also, you got it wrong with the contents of the resources folder of your webapp.

    The structure for a web application module should look like this:

    yourappname
    -----src
    --------main
    -------------java
    ------------------com.yourcompany.yourappname
    -------------------------------------------------your java packages here (including controllers, form classes, etc.)
    -------------resources (properties files, templates, etc)
    -------------webapp
    ---------------------css
    ---------------------js
    ---------------------images
    ---------------------WEB_INF
    --------------------------config
    --------------------------jsp
    --------------------------tags
    --------------------------tld
    ------------------------web.xml
    ---------------------index.jsp
    --------test
    -----pom.xml

    -----target (build artifacts such as .war file will be placed here...)

    I would highly recommend to follow these guidelines, and, most importantly, to use Maven for your project/build configuration and management. It is a very powerful and flexible tool. It is 100% IDE agnostic, and all major IDEs fully support Maven. This means, you will be able to install a Maven-configured project in any such IDE in minutes by pointing the IDE to the Maven configuration files (POMs) instead of using the IDE-specific project settings. Take a look at the Maven site, it is worth spending some time getting familiar with Maven.

    http://maven.apache.org/guides/getti...ted/index.html
    Last edited by constv; Mar 18th, 2009 at 09:39 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •