Posts Mentioning RSS Toggle Comment Threads | Keyboard Shortcuts

  • Mike 9:40 pm on May 29, 2008 Permalink | Reply
    Tags:   

    Exceptional Metadata 

    Exceptions are an important part of any programming language, especially Java. Java has two types of Exceptions. No, not checked and unchecked, but rather useful and useless. The utility of the Exception is up to you, the developer. What am I talking about? Bear with me, read on, and please share your comments at the end.

    Core data

    Exceptions are comprised of some sort of primary data, for example, the name or type of Exception, and maybe the exception’s message. Take, for example, a ConnectionTimeoutException.

    You, as a developer, have a pretty good idea as to what is going on when you see this at the top of the stack trace. You may be able to read the message, if the developer provided one, and get a little more information about the exception.

    /**
    * Signals that a timeout occurred while opening the socket.
    */
    public class ConnectionTimeoutException extends IOException {
    
    /** Create an instance */
    public ConnectionTimeoutException(String message) {
    super(message);
    }
    
    }
    

    Default Metadata

    If you read a stack trace or hack the exception’s API, you can even get some more information about the it. Such as the Class that threw the Exception, or the line number where the Exception occurred. You might be able to review the hierarchy of the class to garner some information. For example, this ConnectionTimeoutException extends from IOException. That tells you something.

    The Problem

    The problem with this type of Exception is that someone, like a developer, needs to review this information in order to track down the cause of the issue. That means locating the stack trace, and determining the parameters and other configurations that were present at the time of the Exception.

    Java, however, and most any other language, provide a means for supplying pertinent metadata when an Exception occurs. They are called properties, getters and setters, or mutators. You, as the designer, just need to include those properties when you design the class.

    Example

    Consider the ConnectionTimeoutException. Wouldn’t it be nice to know the source and destination URIs of the connection? And what the timeout value was?

    /**
    * Signals that a timeout occurred while opening the socket.
    */
    public class ConnectionTimeoutException extends IOException {
    
    private long timeout;
    private String source;
    private String destination;
    
    /** Create an instance */
    public ConnectionTimeoutException(long timeout, String source, String destination) {
    
    super("failed to connect to " + destination + " within alloted " + timeout + "ms");
    
    this.timeout = timeout;
    this.source = source;
    this.destination = destination;
    }
    
    public long getTimeout();
    public String getSource();
    public String getDestination();
    }
    

    Would you agree that the Exception that knows the timeout value and destination URI is more valuable to you, the developer, than some Exception with an arbitrary message that the designer may or may not have populated with relevant information?

    Benefits

    The resulting Exception implementation provides a constructor requiring specific values. The developer who consumes this Exception no longer needs to come up with some arbitrary message. He or she just needs to provide the requested parameters, which is known or can be read from some HttpClient implementation.

    The developer who is catching and dealing with this ConnectionTimeoutException now has a few more options. Perhaps an error message will be displayed. The developer can write a custom message and use the timeout property to notify the end user what the timeout was. The developer doesn’t need to parse it from a String message property.

    If the code throwing the ConnectionTimeoutException is a framework to be used by other developers, the developer has a lot more options to handle this Exception. Perhaps they are writing a GUI for your tool and can now provide their end users with more information.

    Metadata in the Real World

    I decided to write about this topic after a user of our Architecture Rules (Assert your Architecture!) open source software asked us to enhance our Exception APIs.

    Our CyclicRedundancyException simply contained a message that described a package by its name, and then listed all of the packages involved in a cyclic dependency with said package.

    ...architecturerules.exceptions.CyclicRedundancyException:
    cyclic dependencies found:
    
    -- test.com.seventytwomiles.services
    |  |
    |  |-- test.com.seventytwomiles.model
    |  |
    |  |-- test.com.seventytwomiles.dao.hibernate
    |
    |
    -- test.com.seventytwomiles.model
    |  |
    |  |-- test.com.seventytwomiles.services
    |
    |
    -- test.com.seventytwomiles.dao.hibernate
    |
    |-- test.com.seventytwomiles.services
    

    steven.devijver asked that we provide an API to retrieve a List of the packages involved in the cycle. This way Steven can construct his own message, or wrap the data in his own domain Exception, or whatever else he had in mind. We accommodated him by providing a Map containing a key (package name) and value (List of package names involved in a cyclic dependency) pair. This should be useful when we go to write the Maven 2 plugin report for this tool.

    As another example, we inherited a DataFinderException in another project we’re working on. The only constructor for this Exception was a String named message. We introduced a new constructor and two properties — name and value — and getters for each. Now, the code that constructs DataFinderExceptions no longer needs to build some complex message with a StringBuffer before throwing the Exception.

    StringBuffer message = new StringBuffer();
    message.append("Could not find entity with");
    message.append("userId");
    message.append(" = ");
    message.append(userId);
    
    throw new DataFinderException(message.toString());
    

    became

    throw new DataFinderException("userId", userId);
    

    A cleaner execution, fewer lines of code, and useful metadata that can be passed on to the end user, logged, or handled eloquently.

    How do you design your Exceptions to provide useful metadata? Can you think of any Exception in the JDK that provide such metadata?

     
    • Jamo 2:19 pm on May 30, 2008 Permalink

      Brilliant explanations!

      No, I can not think of an existing exception that provides useful information in it (was there a right answer?).

  • Mike 5:49 pm on May 24, 2008 Permalink | Reply  

    Spring: Many applicationContext.xml > One applicationContext.xml 

    This is a short introduction to splitting up your bean definitions from one single Spring application context, to many application contexts. That is, from one XML file to many XML files.

    The general idea is to have one single primary application context, usually titled
    applicationContext.xml, and then many other application contexts with are named what they contain.

    Example

    • applicationContext.xml
    • applicationContext-dao.xml
    • applicationContext-dao-datasource.xml
    • applicationContext-ldap.xml
    • applicationContext-aspects.xml
    • applicationContext-web.xml

    Breakdown

    In this example, your DAO definitions, transaction managers, and DAO or integration interceptors are defined in applicationContext-dao.xml. We have further broken the DAO application context to a dao-datasource which contains our data sources. LDAP configuration, beans, and DAOs are in their own applicationContext-ldap.xml.

    Benefits

    Why so many? There have been a few benefits so far.

    • Clearly, working with a smaller XML file is easier than working with one enormous file. It is easier to maintain and easier to read.
    • Testing. When I wrote my tests for LDAP, I had my LDAP configuration in applicationContext.xml, but then every time I ran an LDAP test, I would get the WebApplicationContext, which would import applicationContext-hibernate, which would connect to the database, tests took forever, needless resources used… Anyway, now I just get applicationContext-ldap.xml which only contains LDAP configurations, so no needless resources are loaded.
    • Including. Finally, its really easy to comment out a line like
      <import resource="applicationContext-aspects.xml"/>

      and quickly have all my aspects, which for me only write logs, disabled.

    Does anyone else use multiple application context files? See any other benefits? Or problems?

     
    • Jamo Smith 5:52 pm on May 24, 2008 Permalink

      I’ve used a folder called springbeans to hold all my context files. They are module or entity centric:

      - user.xml
      - project.xml
      - hibernate.xml
      - security.xml

      Tests are able to isolate only 1 or 2 contexts that are required to do the given test.

    • cherouvim 5:53 pm on May 24, 2008 Permalink

      Yep. Many files and imports is how I prefer it as well. Especially those which are deployment related (datasource, mail session details etc).

      And I see no problems with that.

    • Ashkan 5:53 pm on May 24, 2008 Permalink


      Clearly, working with a smaller xml file is easier than working with one enormous file.

      And working with as little as possible XML stuff is the utopia so take a look at Guice Mike.

    • Peter Warhol 2:23 pm on May 25, 2008 Permalink

      I think that was covered recently in the 90th percentile:
      http://icoloma.blogspot.com/2008/01/mock-your-spring-config-for-fun-and.html

    • Mike 9:19 am on May 26, 2008 Permalink

      Thank you Peter. the 90th percentile states

      This is an old habit of mine, a “main index file” that imports everything else. It is a bit cleaner than specifying every file in the web.xml descriptor

      and follows up that with an example of how to import many application contexts into a main one.

    • Matt 9:55 am on May 27, 2008 Permalink

      Another issue we ran into is having several applicationContext.xml on the classpath leads to some very hard to track errors. By giving the file a unique name, you can help avoid these conflicts.

    • Adrian Neagomir 10:14 am on May 27, 2008 Permalink

      I use two definition files when doing web applications with Spring: one containing the database access and the service layer while the web related stuff in the configuration file that’s used to configure the DispatcherServlet.

      The advantage of having this setup is that I can instantiate a console application that has access to the entire service layer for batch jobs, tests etc. using only the first file without having any dependency to a servlet container.

      Using more files one can assemble different application using the same codebase.

    • Max Power 6:15 pm on May 28, 2008 Permalink

      Splitting your bean definitions into multiple files is definitely a good practice. However, regarding how your old way of not splitting it up caused the app context to connect to the database reminds me of something I read where I believe the preferred way of coding unit tests is to create the beans programmaticly in the setup methods. This way the tests aren’t tied to configuration files that may be changed, causing the tests to become invalid since they aren’t being run in the same configuration against which they were coded.

    • Mike 7:45 am on May 29, 2008 Permalink

      Max, good points on test datasouces. With a Spring context, you could create a datasource bean with the same name, and then load that test context AFTER the production context, the test context would be used. That way you can keep all the configuration in the application contexts and have them injected.

    • Andrew Sazonov 1:44 am on June 7, 2008 Permalink

      Just my 2 cents – suggestion from Mike regarding testing via bean overriding (i.e registering bean in text context using the same name as one in production) will work, but only if context is configured to allows bean definition overriding (there is appropriate setting for that)

  • Mike 2:48 pm on May 24, 2008 Permalink | Reply  

    Spring: OpenSessionInViewInterceptor & OpenSessionInViewFilter Examples 

    This post on OpenSessionInViewInterceptor vs. OpenSessionInViewFilter gets a lot of views from developers who are searching “OpenSessionInViewFilter” and “OpenSessionInViewFilter”. I’d guess, a lot of them are looking for examples. I don’t want to disappoint anyone so here are example setups of both the filter and the interceptor.

    OpenSessionInViewInterceptor

    This goes into your action-servlet.xml.

    <beans>
    
    <bean id="urlMapping"
    class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    
    <property name="interceptors">
    <list>
    <ref bean="openSessionInViewInterceptor"/>
    </list>
    </property>
    
    <property name="mappings">
    
    </bean>
    
    <bean name="openSessionInViewInterceptor"
    class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
    
    <property name="sessionFactory">
    <ref bean="sessionFactory"/>
    </property>
    </bean>
    
    </beans>
    

    OpenSessionInViewFilter

    This goes into your web.xml.

    <web-app>
    
    <filter>
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>
    
    <filter-mapping>
    <filter-name>openSessionInViewFilter</filter-name>
    <url-pattern>*.html</url-pattern>
    </filter-mapping>
    
    </web-app>
    

    If you are not sure if you need to use the filter or the interceptor, check our post that explains the “>difference between the OpenSessionInViewFilter and the OpenSessionInViewInteceptor. The comments on that page offer some good insight too.

     
    • Anonymous 2:49 pm on May 24, 2008 Permalink

      Thanks.

    • Anonymous 2:49 pm on May 24, 2008 Permalink

      thanks a lot! code is better than 1000 blog post! :D

    • Mike 2:50 pm on May 24, 2008 Permalink

      Too true. I hate going to software blogs and seeing nothing but paragraph after paragraph. I want to see code that I can copy and paste, that has comments in it so that I can follow it.

      Glad I could help. Cheers.

    • cookie 2:51 pm on May 24, 2008 Permalink

      Hi Mike,
      Kudos on the great explanations and examples.

      I am a newbie to Spring (as well as Java :P ). I have a question regarding OpenSessionInViewInterceptor/ Filter.

      I have a Spring app that only selective controllers requires open sessions. Can I selectively “hook-up” the interceptor to those controllers?

      Thanks a lot.

      YS

    • Anonymous 2:51 pm on May 24, 2008 Permalink

      For those of you using the Persistence API, there is also an EntityManager version:

      org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor

      Thanks for your example, Chris

      PS I would put an example – but seems the comments box does not allow it :(

    • weggyboy 2:52 pm on May 24, 2008 Permalink

      Nice Post, but it only works for views, doesn´t it?

      I was trying to change some entries after the proposed changes and found out, that the write operations are not allowed with the default session setting for the openViewInSession filter.
      After searching for a solution I´ve found that:

      import org.springframework.orm.hibernate3.support.OpenSessionInViewFilter;
      import org.hibernate.*;
      import org.springframework.dao.*;

      public class SessionFilter extends OpenSessionInViewFilter {
      /*
      * The default mode is FlushMode.NEVER
      *
      * @see org.springframework.orm.hibernate.support.OpenSessionInViewFilter#getSession(net.sf.hibernate.SessionFactory)
      */
      protected Session getSession(SessionFactory sessionFactory)
      throws DataAccessResourceFailureException {
      Session session = super.getSession(sessionFactory);
      session.setFlushMode(FlushMode.COMMIT);
      return session;
      }

      /**
      * we do an explicit flush here just in case we do not have an automated flush
      */
      protected void closeSession(Session session, SessionFactory factory) {
      session.flush();
      super.closeSession(session, factory);
      }
      }

      Now it works as wished!

    • delta one 2:53 pm on May 24, 2008 Permalink

      Excellent example!

    • Dan Allen 3:21 pm on May 24, 2008 Permalink

      You should read Spring in Seam, Part 3 (http://www.javaworld.com/javaworld/jw-05-2008/jw-05-spring-seam3.html) and chapters 8 and 9 of Seam in Action to discover why this Spring filter/interceptor is essential a huge *hack*. The persistence manager (Hibernate Session/JPA EntityManager) was designed to be extended across a series of requests, not be relegated to a single request or worse service layer call. LazyInitializationExceptions happen because the persistence manager is scoped incorrectly.

    • David Newcomb 12:28 pm on October 12, 2009 Permalink

      Your xml for urlMapping is incomplete! No value is set for:

      and the property is closed. What is it supposed to be?

    • David Newcomb 12:29 pm on October 12, 2009 Permalink

      Your xml for urlMapping is incomplete! No value is set for:
      property name=”mappings”
      and the “property” is not closed. What is it supposed to be?

    • David Newcomb 1:51 pm on October 12, 2009 Permalink

      Also urlMapping doesn’t work if you are using annotations.
      If you are using annotations you should probably go for the OpenSessionInViewFilter otherwise there is a rats nest of other support classes you need. Just spent the day reading all about it and I have lost the will to live :(

    • Mike 9:25 am on October 13, 2009 Permalink

      @David Newcomb – The post isn’t really about how to set mappings. But you’ll want something like

      installController

      which maps a request URI to a controller. Here are some examples…

      http://www.google.com/search?q=SimpleUrlHandlerMapping+example

    • Pieno 7:52 am on July 11, 2010 Permalink

      In Spring 3 you can use the tag to use the OpenSessionInViewInterceptor. There is an example on my blog: http://www.pieno.be/content/2010/opensessioninviewinterceptor-example-spring-3-web-mvc

  • Mike 2:38 pm on May 24, 2008 Permalink | Reply  

    Spring: OpenSessionInViewInterceptor vs. OpenSessionInViewFilter 

    Problem: Assuming you’re using an ORM, such as Hibernate, rendering the view with business objects that have many-to-one or one-to-one relationships might try to access a detached object with a lazy property and throw a LazyInitializationException. For this reason, we’re provided with the Open Session In View pattern.


    Solution: The Open Session In View pattern binds a Hibernate session to the thread to be used throughout the life of the request and closes any transactions when the response is sent. This is what allows your view to access model objects with lazily loaded properties after a transaction has been closed. This is nothing new and this is not what this post is about.

    To setup the Open Session In View in your Spring application, you have two options. The OpenSessionInViewInterceptor and the OpenSessionInViewFilter. You can use either solution because the two classes serve the very same function and implement the same pattern. Well if this is the case, then why do they both exist? Why is there a filter option and an interceptor option? This is what I set to find out.

    I’ve been searching Google all night. I’ve read through forums, I’ve read docs, and I’ve read blogs. Why? Because I want to use the better of the two options on my application. I want to ensure I am getting the best performance and the most reliability for my clients as I can. Anyway, the only thing that I could dig up was that they are equal in almost every way. The only consideration that you really need to make is what servlet spec you are using. If your servlet container support version 2.3 or later, you can use either one. If it’s 2.2 or earlier, you’ll need to go with the OpenSessionInViewInterceptor.

    Surely there are other considerations. Maybe you want to keep your filters down to a bare minimum, or you think interceptors are confusing or messy. Or perhaps you like to keep your configuration files as small as possible. If you use annotations, you might want to go with the OpenSessionInViewInterceptor.

    I hope I answered any questions you had about why there were two classes for implementing this pattern.

     
    • jazzy 2:40 pm on May 24, 2008 Permalink

      Hi, thanks for your post, it’s good to see that at least someone is writing about this stuff because I always feel a little worried if I’m using functionality that it appears no one else is using.

      There is an argument for OpenSessionInViewInterceptor that you have left out. If you want to keep a hard line separation between your model and your view, ie, data objects should never be passed to JSPs, and web forms should never be passed to the model, so you’re doing conversions in the controller, then you don’t want the session to be open to the JSPs, you want to intercept calls to the Actions, so that when the JSP is being rendered, the session is closed, and any LazyInitializationException is an indication that you are breaking your design pattern.

      Another reason for the existence of an OpenSessionInViewInterceptor is that web containers are not the only views to business objects, for example, you might have an MDP that receives a message, makes a call on your business object, gets some hibernate data objects back as results, and encodes them and sends a reply message. In this case the only option is OpenSessionInViewInterceptor.

    • Robert Reiz 4:26 am on August 20, 2008 Permalink

      Another example: If you are using a quartz-job in your service-layer with hibernateDAO access you got an Exception

      “No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here”

      with the openSessionInViewFilter. Because the openSessionInViewFilter is not active for actions startet on your service-layer. Here you need the openSessionInViewInterceptor.

    • Ryan Stewart 8:50 am on August 25, 2008 Permalink

      Actually, neither the Open Session In View Filter nor interceptor is the correct solution to your quartz problem. That exception is telling you that that your configuration won’t let you arbitrarily create a session. This is good, and is likely the result of configuring your HibernateTemplate with allowCreate=false. Using the Open Session In View pattern here would be a Bad Idea, as it simply ensures that a *non-transactional* session is available, which might allow your quartz job to complete successfully, but outside of a transaction, which could mean that nothing gets committed to the database, or it might just fail with a different exception. Worst case, it might mean that things are written to the database in auto-commit mode, meaning that other threads reading from the database could get corrupt data back. Operations performed by the service layer should be done within a transaction. This probably means that your services should be proxied with a TransactionInterceptor to handle your transactions. The TransactionInterceptor does *not* need an Open Session In View Filter or Interceptor, as it opens its own session if one is not available.

      A good example of when to use the Open Session In View Interceptor is one that jazzy gave: when processing messages or requests from something other than a person using a web page. You can actually consider the Open Session In View Filter as a specialized application of the Open Session In View Interceptor. It is useful only when a request comes to your application via a servlet container. If the request/message comes via other channels–say a message from a JMS queue–then the Open Session In View Filter is useless because it isn’t going through the Filter mechanism. That’s where you need the Open Session In View Interceptor (assuming that some response message is needed). Both filter and interceptor allow you to render a response outside of a transaction–that’s what the Open Session In View pattern is really about. The only distinction is that one is specific to a servlet environment, and one isn’t.

    • Robert Reiz 3:54 am on September 4, 2008 Permalink

      Hallo Ryan Stewart,

      sorry for my late response. I don’t use the HibernateTemplates, I am working with the genericDaos from Christian Bauer and annotation driven transaction management. The openSessionInViewInterceptor you can use with the property “singleSession=false”. It will not use a single session per request then, but rather let each data access operation or transaction use its own session (like without Open Session in View).
      But you are right and I was wrong. The TransactionInterceptor does not need an OpenSessionInViewFilter or Interceptor, as it opens its own session if one is not available. If I comment out the OpenSessionInViewInterceptor the quartz job works still fine, because I am using the @Transactional annotation in the service layer.

    • Ryan Stewart 8:36 am on September 4, 2008 Permalink

      If you’re using Spring and Hibernate, then you’re most likely using the org.springframework.orm.hibernate3.support.HibernateDaoSupport. If this is true and you don’t know that you’re using a HibernateTemplate, then you’re likely injecting this with a SessionFactory. The HibernateDaoSupport always uses a HibernateTemplate internally, though, whether you configure it explicitly or not. However, if this is how it’s being used, then it will default to allowCreate=true, so your “No Hibernate Session” exception is coming from something else that is not allowed to create a session. Normally using the Open Session In View pattern, in whatever incarnation, would prevent this, but, as you mentioned, setting singleSession=false removes this benefit, and it will go back to breaking because a session is not eagerly created when singleSession=false. Instead, everything is allowed/required to create its own session as needed, as if the pattern weren’t in use at all.

    • Robert Reiz 2:52 pm on September 4, 2008 Permalink

      I am not using the HibernateDaoSupport. I am using the org.springframework.orm.hibernate3.LocalSessionFactoryBean and inject it via “autowire=byName” in the my DAOs. My DAOs all extend the GenericDaoHibernate class from Christian Bauer. For the transactions I am using the org.springframework.orm.hibernate3.HibernateTransactionManager. My “No Hibernate Session” exception occurred because the @Transactional method was not listed in the Interface to my Service class. Since I added the method signature to the interface it works fine with and without OpenSessionInViewInterceptor/Filter.

    • Ryan Stewart 3:35 pm on September 5, 2008 Permalink

      The most prominent GenericDaoHibernate class I see is org.appfuse.dao.hibernate.GenericDaoHibernate. Is that what you’re using? It’s a direct subclass of HibernateDaoSupport. If not, then you’re probably doing stuff manually that this class automates for you.

    • Robert Reiz 8:52 am on September 6, 2008 Permalink

      Actually I’m using my own GenericDao class. I have take a look to org.appfuse.dao.hibernate.GenericDaoHibernate. It’s similar to my class. Perhaps in the next project I will use it. Thank you for the hint.

    • Charles Gutjahr 1:26 am on November 11, 2008 Permalink

      I have found it necessary to choose OpenSessionInViewInterceptor over OpenSessionInViewFilter when using Spring Web Flow (SWF).

      If you use the filter (OpenSessionInViewFilter) then all requests will have the Hibernate session applied to them, regardless of whether Spring MVC, Spring Web Flow or something else handles the request. This is a problem if you use Spring Web Flow’s flow managed persistance (ie the tag) because it creates its own Hibernate session… this results in two sessions being created and a pile of IllegalStateExceptions because only one session is allowed.

      OpenSessionInViewInterceptor solves this problem because you can choose to apply it only to some handlers – ie apply it to Spring MVC but don’t apply it to Spring Web Flow. That way you can use OpenSessionInViewInterceptor for Spring MVC where it is very useful — and let Spring Web Flow use its (probably superior) flow managed persistance for Spring Web Flow handlers.

    • Mike 9:20 pm on November 11, 2008 Permalink

      @Charles Gutjahr – Charles, thanks for sharing that use case. I use and love Spring MVC, but have not had the opportunity to get into web flow yet. Thanks for describing the situation that you encountered and why the interceptor was the solution. I’m sure that comment will be very helpful to someone soon.

  • Mike 9:18 pm on May 15, 2008 Permalink | Reply
    Tags:   

    Squash those Cyles 

    Two packages are said to be involved in a cyclic dependency when package A depends on package B and package B depends on package A. This is called a direct cyclic dependency. Cyclic dependencies are created in various ways at different layers within a software system. It’s also possible for a cyclic relationship in one layer to cause cycles in another.

    cycles

    Cyclic dependencies hurt a software system’s goals:

    • Understandability Understandable software is critical in managing complex systems. Software that is easily understood acts like a bridge between the problem and its solution.
    • Flexibility
    • Modularity An approach to developing software that breaks projects into smaller units designed so that they can work with other sections of the program. Modifying the way that modules work will have no adverse affects on the other components of a program
    • Modifiability Modifiability is controlled change to the system in which some parts are altered without increasing the complexity or obscuring the logic of the original structure.
    • Reliability Reliability is the extent to which a software yields consistent, stable, and uniform without any human intervention and is crucial for any software system that must operate for long periods.
    • Maintainability The ease with which a software system can be modified to change or add capabilities, improve performance, or correct defects.
    • Testability The degree to which a system or component facilitates the establishment of test criteria and the performance of tests to determine whether those criteria have been met.
    • Reusability
    • Clarity

    By using Architecture Rules to Assert your Architecture, you are taking the first step in developing a strong architecture by actively managing package relationships.

    Aside from the adverse affects on the software development goals, cyclic dependencies create these negative consequences for the system:

    • Diminish the ability to determine a package’s purpose.
    • Changes impact seemingly unrelated components of the architecture.
    • Separation of layers.
    • Packages cooperating in a cycle must be released as an atomic unit.

    Determine a Package’s Purpose

    When future developers come along to maintain the software the presence of cycles can diminish the ability for that developer to determine a package’s purpose. This hurts the software’s clarity and understandability. The end result will be the introduction of bugs, or an increase in the amount of time required to modify the software.

    Changes Impact Unrelated Components

    When a class involved in a cycle is modified, it could change the bahavior of the other class involved in the cycle. This makes it difficult to accurately assess and manage the impact of changes to the system. This directly hinders the modifiability of your software. Reliability is also attacked since changing the behavior of an unrelated class could introduce a bug.

    Affecting other components also introduces a maintenance and testing issue, since you can’t do anything to either class without possibly affecting the other. A situation exists where class A needs to compile against class B, but class B needs to compile against class A.

    Separation of Layers

    Most architectural approaches recognize the advantages of layered architectures. For example, if you develop a presentation layer, a business or logic layer, and a database access layer, you are able to swap out one implementation of a layer for another. Such as replacing a JDBC data access layer with one that utilizes Hibernate, or a JSP presentation layer for a Flash or PHP presentation layer.

    Cyclic dependencies across layers couple the layers, defeating the purpose of layering. If a cycle exists between the service layer and the data access layer, then those two layers are no longer interchangeable. Thus, modifiability of the software is lowered. The layers are no longer encapsulated.

    Packages Must be Released as an Atomic Unit

    The Spring Framework is inspiring when it comes to its modular design. The Spring Framework can be considered as a collection of smaller frameworks. Most of these frameworks are designed to work independently of each other yet provide better functionalities when used together.

    This modularity by design, allows the Spring Framework to released as a full framework (spring.jar) or modularly, so that the users can use the features that they are interested, and nothing more (spring-core, spring-ldap, spring-orm, spring-aop, spring-beans, spring-mock, and on and on…). See all of the modules here.

    When cyclic dependencies exist, your ability to make and release independent modules is removed. Packages that may not be related must be released as a single jar, or module.

    ArchitectureRules wraps JDepend, a java library which is able to identify these cyclic dependencies. Upon detecting a cyclic dependency, a CyclicDependencyException is thrown, a RuntimeException whose message notifies you of which packages are involved in a cyclic dependency:

    ...architecturerules.exceptions.CyclicRedundancyException:
    
    cyclic dependencies found:
    -- test.com.seventytwomiles.services
    | |
    | |-- test.com.seventytwomiles.dao.hibernate
    |
    -- test.com.seventytwomiles.dao.hibernate
    |
    |-- test.com.seventytwomiles.services
    

    When are Cycles Acceptable

    Generally speaking, cycles are most always accepted when in the same package. For example two domain objects in the same package, such as User and Account. A User has Accounts, and an Account has a User. Since these two classes are in the same package, the package remains encapsulated.

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
esc
cancel