This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

Spring debugging question : IoC

Mar 30th, 2005, 06:01 AM

Hi,

I am new to Spring, I have use Spring last month for a small JDBC project to test its features and Spring helped me well when retreiving JDBC connection (JDBCTemplate), etc. It seems to be well done, even if sometime I can be afraid to let the Spring Black Box manage all jdbc issues.

My next project will have to use Hibernate (3.0) in a greater scale (50 tables, 2 DB. for 8 webApps). I am open to use Spring if the project can be improved: faster coding, better unit testing, encapsulating Hibernate Implemetation and session management, giving a single Facade for all 8 WebApps, better maintenance. Spring seems great, but I know I could do this project without Spring without any pitfall.

Because my choice is not made yet, I would like to have some developpers feedback about pro/con using Spring for the software entire lifecycle (design, developement, testing, debugging, maintenance). Knowing the cons right now are more important for me than knowing the pros, since it could help me to avoid some pitfall if I choose this option.

Per example, I am not convince yet that Injection of Control (IoC) could be a good practice for everything (yes, I will read the article on ServerSide about this topic soon). I would like to know what is the impact of IoC when simply debugging the code. How can you debug a code when most of the links between objects are made in a xml file? Is there a "best practice" when using IoC?

How can you debug a code when most of the links between objects are made in a xml file? Is there a "best practice" when using IoC?

I would say, that the point you are questioning is not really an issue. At the time when you are debugging your application, all your objects are already wired up. So you will not even detect, that this has been done by spring.
What you might detect is a wrong or missing configuration of a property. But again, this is no spring-specific issue :wink:

If you are however concerned about the wiring itself:
If your application is well-designed, you should have classes collaborating with other types, declared as interfaces. If sufficiently documented, the contract of the collaborating types (i.e. interfaces) should be sufficient to get an overview over your architecture. The concrete implementation types (which are "hidden" in the spring configuration) should not matter much in that case.

You might want to use mocks (I prefere jMock) to test your modules in isolation and to do this in a interaction-based fashion (what does you modul do with the particular dependencies). It was always a good relieve for me to be able to formulate expections on a particular behaviour instead of asserting the resulting states. You might also like this, too.

Another might be providing value may be the use of diffrent context definition files (xml) for testing diffrent modules. And to never use the same context you use for testing for the production code.

Comment

Something to keep in mind in Spring: if you aren't using any of the specific services Spring provides (like JDBC or Hibernate) Spring is a meerly a way of initializing an object hierarchy and strongly encourages the Strategy Pattern. That's it. You could just as easily replace the Spring application context with a singleton whose initialization would wire up your objects by hand.

So most of the cons of IoC would be the same ones that exist for the Strategy pattern. I feel using this pattern helps the lifecycle of the application because when designing what services to put in other classes, you can write unit tests for them. When you integrate all of the classes into your single facade, you would write more unit tests, possibly with some form of mock objects, especially for classes which do database operations. Most of your debugging happens in these unit tests. And as you encounter problems in your intergrated product, you create new unit tests. This approach isn't unique to Spring, but Spring encourages it. It giaves you some structure to hang your hat on.

Having used Spring and JDBC for a small application myself, and started designing a larger application of Spring I have found a few issues which you have to work through:

- Organizing different XML files. For some files there are multiple versions of them. Specifically things like datasources and transaction managers. You have different versions for unit tests and containers. For some other objects there is only one version, and usually are singletons (although that depends on the thread safety of your objects). I believe putting an application context file in the same package as your business objects and collaborators allows you to compartmentalize your Spring files. That file would be analagous to a singleton which initializes your objects. An advantage of having a context file per Java package would be you can generate the file using XDoclet. Or perhaps generating a single files for a logical hierarchy of objects.

- When you have multiple XML files you have to understand how to incorpoate multiple files into a single context or possibly a hierarchical context. Its not that difficult, especially when using a listener at web startup.

- As you allude to, there can be issues when debugging initialization. You often get these large stack traces where you have to find why some collaborator didn't initialize. Again, using unit tests for doing your early work is recommended. Also try to avoid complicated setter methods. Each collaborating class should just be an attribute on the business object. If you need to do something special once the various properties are set you have a few options:
- Implement InitializingBean interface and do your initialization in afterPropertiesSet
- specify an init-method in your XML file that will be called. This is recommended over the first option because it doesn't tie your object to the Spring API
- Use a constructor taking those objects which need to have special initialization. I prefer using properties because it makes your objects more self documenting in the context XML files.

- There is nothing to say that your main business object can't have its own business logic. Don't take "Spring-ifying" too far. Only split out those services which make the most sense. Spring is just the expression of some very useful design patterns, with some additional convenience services, and tries not to be much more than that. If you are worried Spring is going to take over your app, try to design things in a Spring like way, but try to minimize the number of places you use Spring specific APIs. In your case you probably are going to have a few DAOs for Hibernate and everything is going to be POJOs wired together with Spring (or if you prefer you can wire it up yourself)

- Design your package structure ahead of time. Since Spring recommends using more interfaces and more wiring than you might otherwise do if you weren't using Spring (althgough nothing stops you from doing so) you can create quite a mess quickly. Personally I like to put my interfaces and DTOs in a .api package, with the actual implementations in .impl. Maybe putting your database specific classes in a .db package or something like that. This is especially important if you ever want to convert your application to call the services remotely and will need to put the .api files int a seperate client jar than the actual implementation.

Comment

- Design your package structure ahead of time. Since Spring recommends using more interfaces and more wiring than you might otherwise do if you weren't using Spring (althgough nothing stops you from doing so) you can create quite a mess quickly. Personally I like to put my interfaces and DTOs in a .api package, with the actual implementations in .impl. Maybe putting your database specific classes in a .db package or something like that. This is especially important if you ever want to convert your application to call the services remotely and will need to put the .api files int a seperate client jar than the actual implementation.

I would like to suggest another package-naming here. The problem is that .db, .api, .impl are names that are more about the how than the what. Package names (like any other names) should reflect the what (the reasons of existing, being declarative/descriptive). We use persistance or persist instead of db over here. (referring to the persistance layer related (domain) aspects).

Also putting interfaces in a seperated package is something I don't like though. There is a packaging principle being called 'Interface belongs to client'. According to this principle one places the interfaces one package ahead (or at least the same package) as the implementation (parent package). This will allow you to hide the implementations. To access the implementations static service classes (like a factory) are used and placed within the interfaces.

Instead of .impl, I would like to suggest to use the .internal packagename instead. The reason is to state internal (implementation) details by a naming convention to get away form sealing them for the main version (backward compatibility). Internal implementations (or any other placed in subpackages of an internal package) are ment to be subject of change and are only garanteed to be backward-compatible during the same sub(!)-version.

Maybe you find such a package structure helpful, too.

Cheers,

Martin (Kersten)

Comment

If any of you have other remarks about package naming, class naming, Interface, xml files... this is exacly what I am looking for. I am starting the project and I have benefits a lot from theses posts.