Results 1 to 10 of 33

Thread: Need advice on exception handling approach

Hybrid View

  1. #1
    Join Date
    Jul 2005
    Posts
    5

    Default Need advice on exception handling approach

    Hi all,

    Suppose we are implementing the code for "register a new user to Spring forum". And you need to guarantee that username is unique...

    (There is a service layer, a dao layer, and a view layer. Using declarative transaction management.)

    Here is what i thought:

    hmm, i can put a constraint check in database, let Spring throw DataIntegrityViolationException and catch it in the service layer and
    wrap it within a more specific and meaningful exception and throw the new exception.

    Here is the service layer code:
    Code:
        @Transactional
        public void save(User User) {
            try {
                dao.save(user);
            } catch (DataIntegrityViolationException ex) {
                throw new BusinessException("Duplicate username.");
            }
        }
    You might guess what actually happens in this situation; i can't catch the exception, because dao.save(user) would not really save to the database
    (hence the constraint viloation does not manifest) until transaction commits (when the save method exits).

    Any suggestion? What do you think i should do?

  2. #2
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    Have you tried to flush to db manually thus forcing immediate insertion to db? Something like this:
    Code:
    @Transactional
        public void save(User User) {
            try {
                dao.save(user);
            // or EntityManager  in EJB3  
                Session.flush();    
        } catch (DataIntegrityViolationException ex) {
                throw new BusinessException("Duplicate username.");
            }
        }
    Spring, it's a wonderful thing...

  3. #3
    Join Date
    Jul 2005
    Posts
    5

    Default

    Hi,

    It solves the problem, but I wonder if it is the right way of handling this kind of situations?

    I don't recall seeing manual flush in common sample codes. And in the API, it says that "Only invoke flush for selective eager flushing, for example when JDBC code needs to see certain changes within the same transaction. Else, it's preferable to rely on auto-flushing at transaction completion"

    Hence, I thought maybe the way I am handling the situation is wrong by design.

    (Besides, if I will have to flush, wouldn't dao layer be a more appropriate place?)

    Actually, I am trying to find the most preferable approach...

  4. #4
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    Quote Originally Posted by sk
    I don't recall seeing manual flush in common sample codes.
    (Besides, if I will have to flush, wouldn't dao layer be a more appropriate place?)
    Well, It's not the Spring you are dealing with in this scenario. You are dealing with Hibernate.
    Here is some example from Chapter 8 of the Hibernate in Action by Christian Bauer and Gavin King (the father of Hibernate)
    Code:
    Triggers and ORM are often a problematic combination. It's difficult to synchronize the effect of a trigger with the in-memory representation of the data.
    
    Item item = new Item();
    ...
    HibernateUtil.beginTransaction();
    Session session = HibernateUtil.getSession();
    session.save(item);
    session.flush(); // Force the INSERT to occur
    session.refresh(item); // Reload the object with a SELECT
    System.out.println( item.getCreated() );
    HibernateUtil.commitTransaction();
    HibernateUtil.closeSession();
    Most problems involving triggers may be solved this way, using an explicit flush() to force immediate execution of the trigger, perhaps followed by a call to refresh() to retrieve the result of the trigger.
    Triggers and ORM are often a problematic combination. SIC!!! SIC!!!
    Quote Originally Posted by sk
    (Besides, if I will have to flush, wouldn't dao layer be a more appropriate place?)
    I guess, this is a perfectly valid argument. I gave just an illustration. right? This manual flushing stuff is not application business logic but rather persistence logic, i.e. the way ORM deals with triggers. Therefore it should belong to DAO implementation layer.
    Quote Originally Posted by sk
    Actually, I am trying to find the most preferable approach...
    When you will, please, keep me posted
    Spring, it's a wonderful thing...

  5. #5
    Join Date
    Jul 2005
    Posts
    5

    Default

    Thx Arno. %100 agree with you

    I was just curious, why i never saw flush in sample codes. So, I thought maybe i needed a radical design change(like catching exception in view layer)

    Ok, i made a deeper check and saw some trustable sample codes, handling the same situation with flush and I am reliefed

  6. #6
    Join Date
    Dec 2005
    Location
    Argentina
    Posts
    73

    Default

    Maybe you can add an aspect to the service that runs outside the transactional aspect/proxy. This way you can catch the exception and convert it.
    However, I don't think that will work well for more complex cases where many things can fail, also there is the complexity cost of setting up an aspect for every conversion. Documentation for such method (the service method) should state that there's a conversion mechanism in the middle, otherwise the exception appears to be generated out of nowhere.

    Anyway, this is just a brain dump. I'm not convinced that this option is actually better.

    Federico.

  7. #7
    Join Date
    Dec 2005
    Location
    U-241
    Posts
    237

    Default

    @Arthur

    Quote Originally Posted by sk
    Hi all,

    Suppose we are implementing the code for "register a new user to Spring forum". And you need to guarantee that username is unique...

    (There is a service layer, a dao layer, and a view layer. Using declarative transaction management.)

    Here is what i thought:

    hmm, i can put a constraint check in database, let Spring throw DataIntegrityViolationException and catch it in the service layer and
    wrap it within a more specific and meaningful exception and throw the new exception.

    Here is the service layer code:
    Code:
        @Transactional
        public void save(User User) {
            try {
                dao.save(user);
            } catch (DataIntegrityViolationException ex) {
                throw new BusinessException("Duplicate username.");
            }
        }
    You might guess what actually happens in this situation; i can't catch the exception, because dao.save(user) would not really save to the database
    (hence the constraint viloation does not manifest) until transaction commits (when the save method exits).

    Any suggestion? What do you think i should do?
    Well, if it is enough for Sammy, it is enough for Arno.
    Spring, it's a wonderful thing...

Posting Permissions

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