aspose file tools*
The moose likes Spring and the fly likes nonintrusive in spring Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Frameworks » Spring
Bookmark "nonintrusive in spring" Watch "nonintrusive in spring" New topic
Author

nonintrusive in spring

sam liyanage
Ranch Hand

Joined: Nov 25, 2008
Posts: 1085
what is mean by spring is nonintrusive?
Eduardo Bueno
Ranch Hand

Joined: Jun 04, 2009
Posts: 155
It means Spring does everything in the background, that is, you don't have to explicitly call Spring functions in your code.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
Eduardo, I believe that is a mistaken statement. You do need to call spring functions in your code. Something as simple as introducing spring for IOC requires you to call the application context getBean() method.

Spring is non intrusive because it leaves a very small footprint if any on your code. In web applications the JSPs don't need to have any special tags to work with Spring's web framework. If your business logic is well contained it should not be coupled to the actual controller you use. Any normal everyday class can be used by Spring in its application context. You don't need to say "oh I'll be using this class with Spring so I better extend this abstract one first". That just isn't needed in Spring.

On the other side of the Spring spectrum you have things like Hibernate support. Which pretty much goes into the deepest of my DAO code and is strongly coupled to my Spring/Hibernate data access code. But event though it is extremely intrusive there, it isn't so for the overall application. By defining a clear interface for data access. I can remove a spring/hibernate based dao solution and replace it with a JDBC one with no effect on the overall application.
Hong Anderson
Ranch Hand

Joined: Jul 05, 2005
Posts: 1936
I think Eduardo is right.
We shouldn't use getBean() directly, we should use DI instead.


SCJA 1.0, SCJP 1.4, SCWCD 1.4, SCBCD 1.3, SCJP 5.0, SCEA 5, SCBCD 5; OCUP - Fundamental, Intermediate and Advanced; IBM Certified Solution Designer - OOAD, vUML 2; SpringSource Certified Spring Professional
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
Kengkaj Sathianpantarit wrote:I think Eduardo is right.
We shouldn't use getBean() directly, we should use DI instead.


Could you illustrate an example of that?
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Calling getBean() directly should definitely be a last resort -

The normal way to do this would be dependency injection through the spring framework.

Example - note no dependency on Spring classes in the code...



-Nate
Write once, run anywhere, because there's nowhere to hide! - /. A.C.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
Ok, now use bean "something" somewhere in your code.
Hong Anderson
Ranch Hand

Joined: Jul 05, 2005
Posts: 1936
For web applications, we don't need (and shouldn't) to use a single getBean(), just config ContextLoaderListener in web.xml is enough, the rest will be performed by DI. Our code will not have a single dependency to Spring Framework regarding IoC things.

But I'm not sure about desktop applications.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
Looking back at the first work I did with Spring, it just seems more and more intrusive. Not that this is a bad thing. But every time less code is free of Spring dependencies. First with plain servlets there wasn't much of a dependency. But now with the incorporation of Spring MVC, Spring is all around the application. Surely I don't use getBean(), but I extend all those controller types. So Spring is all over the code. It isn't in the code that does the work though so yes it isn't intrusive in that sense. From the other end I see more Spring in the data access. Before it was just Hibernate, now it includes Spring support. So now there are Spring method calls inside the DAOs which I didn't use to have before.

Kengkaj, in regards to your comment about desktop applications. I'm still bound to the use of getBean. I use JFormDesigner to do all the GUI code. It doesn't mix too well with Spring. So I can't really wire panels with Spring. Technically I can, but I'll loose the graphic design view which is the whole point after all. So I've worked around it by using getBean in key points as the app sets up. That aside, Spring is not intrusive in the rest of the code that does the work.
Hong Anderson
Ranch Hand

Joined: Jul 05, 2005
Posts: 1936
Spring Web MVC, Spring Data Access Templates are different topic.
It's obvious that if we use Spring Web MVC (or XXX), our code will have dependency to Spring Web MVC (or XXX).
Assume that we don't use Plug-in Architecture.

But our code shouldn't have dependency to the container, like our code shouldn't have dependency to Tomcat, Jetty, JBoss AS API. Regarding IoC, web applications code will not have a single dependency to Spring IoC.

But if you want to use Spring Data Access Templates, it's obvious that there will be dependency actually they're just kind of utility classes, you could write yourself, but Spring already offers them so we don't need to write ourselves.

The point is in theory, if you don't have dependency to Spring IoC you could change IoC container without impact any source code. But if we use getBean(), our code will be locked to Spring Framework only.

Right now, there are not many mature IoC containers available, but if there are, we'll not want to lock our code to a specific implementation.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
The solution I've come to use in Swing applications is using a static class with a delegate method. The getBean(String beanName) then calls Spring's getBean method to return the appropriate object.. But it could make use of other ways to obtain the object if I change IoC implementation.

Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Gerardo,

I'd use bean "something" elsewhere in my code the same way I used bean "aDependency" in "something"....



Edited:

Ah, I see you were asking about this in relation to your Swing question. I do see static construction methods (aka Factory pattern) one way to do this. I think another way might be to use the form designer to just design your GUI, and rather than create your components inside the constructor - expose the component references via getters/setters, and then use Spring to wire everything together... this probably isn't how JFormDesigner works - but if you can get it to work through static calls, it may be possible to make a "mock launcher" for a wireable Panel... getting an evaluation license for JFormDesigner and seeing if this works...

Edited again :
This seems to be a drawback in JFormsDesigner - there's really no support for DI. Under the code generation tab, you can choose to expose getters for components or use local variables for components - but JFormDesigner always assumes that the class's constructor is going to invoke initComponents() right away and that you're going to call the component constructors in the initComponents() method - I don't see an option for "call initComponents when you're ready to layout the form and get the component from a getter..."

I've made some DI friendly classes that take components and wire them up through the getters exposed through JFormsDesigner generated classes... however, you don't see this in JFormsDesigner, just the original placeholder values... not sure if this helps / is too much work for the results...

My personal preference would be to not use a GUI builder :P - or only use it to generate layout code and then paste the layout code into a DI friendly class - however, you lose the "round-trip" ability to update this code directly in JFormsDesigner... you'd have to have parallel codebases and copy the code between them... stinks either way.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
The objective would be to arrive at something like this:



And have all marvelously wired inside. And it would pretty much work if the application is simple and all the elements you use are buttons, text inputs, selects etc. Let JFormDesigner do all that work and then you just wire the JPanels and JFrames with Spring. But things get a bit more complicated when you register your own components or use i18n. Then you have to graphically edit the design and then verify that the application context is doing the DI.

You can for example comment out the initComponents(); statement in the constructor and then call it from the Spring XML declaration after all dependencies have been injected. But then you don't get a preview. And I really dislike doing that comment uncomment thing all the time.

The solution I've come up with is create controller interfaces for all panels and frames I use. Any action that matters anything will call some method in the interface. It is that interface that is initialized to a particular implementatoin by a getBean call. But not directly to a Spring getBean. I construct a static class whose function is to provide a getBean method that returns an object. Internally in know it is using Spring. So I'm not bound to a particular implementation (in this case Spring).

This way my panels and frames become a bit like the jsps of web applications. Unaware of what they do until runtime. And of course I can easily change the actual implementation of the controller easily. And easily wire it to the business and data logic through Spring. I'm not 100% DI nor am I 100% decoupled from Spring, but there is only one Spring point of presence instead of hundreds. The benefit of using a GUI tool like JFormDesigner outweighs this.
Eduardo Bueno
Ranch Hand

Joined: Jun 04, 2009
Posts: 155
Nathan Pruett wrote:Gerardo,

I'd use bean "something" elsewhere in my code the same way I used bean "aDependency" in "something"....



Actually, you didn't show how you would use the bean "something". I think Gerardo was right; anywhere in your application you will have to call a Spring function to instantiate a bean for you, which will cause all subsequent beans to also be injected. Please correct (and clarify) me if I am wrong.
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Eduardo Bueno wrote:
Actually, you didn't show how you would use the bean "something". I think Gerardo was right; anywhere in your application you will have to call a Spring function to instantiate a bean for you, which will cause all subsequent beans to also be injected. Please correct (and clarify) me if I am wrong.


That's the idea behind Dependency Injection - have all of your dependencies handled by something outside your class - so in the previous example Spring handles wiring together all bean dependencies. However, you are not *dependent* on Spring for this - if you felt like it, you could remove Spring and make a top level class that wired all of your beans together.



Now these classes are set up the same way without Spring as they were with Spring - you can't do this if you have code that calls getBean() directly.
Eduardo Bueno
Ranch Hand

Joined: Jun 04, 2009
Posts: 155
Ok, but still there's no clear explanation on how to use attribute 'something' from SomewhereElse class.

If I create another class:


So it means SomewhereElse should be injected by something (not the attribute, jumbling names) other than you doing new SomewhereElse();.

Does a Servlet (which is injected by the container) solves the problem? I tried in an example here but got no success.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
Nathan we are quite aware that the classes inside the XML are not aware of the usage of Spring. "something" and "somewhere" are not calling getBean to obtain "aDependency" and "something" respectively. Spring is handling the wiring. But at some point you will need to use getBean or some other method of obtaining "somewhere". You still haven't shown us how you make use of "somewhere". Up till now it remains an entity inside the Spring application context. In my experience this is achieved either by calling getBean at some point in your application (preferably something like a factory pattern so you can decouple Spring) or by using some class which is inherently aware of the Spring context (for example a Spring MVC controller). In this case, the classes are not aware they're being used by a Spring MVC controller. You don't even need to do anything special to them to wire them through Spring. This is were the "nonintrusiveness" of Spring resides. But I wouldn't go so far as to say "you don't have to explicitly call Spring functions in your code."
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
Eduardo Bueno wrote:

So it means SomewhereElse should be injected by something (not the attribute, jumbling names) other than you doing new SomewhereElse();.

Does a Servlet (which is injected by the container) solves the problem? I tried in an example here but got no success.


Eduardo, if you use Spring MVC for example then the container handles all the DI at startup and your controllers are initialized in the X-servlet.xml file

You would put this in your web.xml


An then create the someservlet-servlet.xml file to wire the internals.
Eduardo Bueno
Ranch Hand

Joined: Jun 04, 2009
Posts: 155
I'm not using Spring MVC, it's just a simple application with Spring and JSPs. I have a ControllerServlet which tried to inject spring dependencies via @Controller annotation but wasn't succesful. I think the only way to work this out is to do what you said, use a factory method.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
I'd strongly recommend you use spring MVC. Even if it is a simple application. After a while of using it I turned to do a simple servlet and though I wouldn't use spring because it was "too simple". I was a bit mistaken. Just the databinding benefits are worth the trouble.
Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Eduardo Bueno wrote:Ok, but still there's no clear explanation on how to use attribute 'something' from SomewhereElse class.

If I create another class:


So it means SomewhereElse should be injected by something (not the attribute, jumbling names) other than you doing new SomewhereElse();.


That's no different than leaving off the property in the Spring configuration -


A Spring solution to this is to use the @Required annotation. Another way would be to use constructor injection as opposed to setter injection - Spring supports both styles. And using constructor injection without Spring, at least you're making it obvious that you need to supply a dependency to construct an instance.

Eduardo Bueno wrote:
Does a Servlet (which is injected by the container) solves the problem? I tried in an example here but got no success.


Not sure what problem would be solved by using a Servlet - you can use init-params - but there's no way to say that a servlet "requires" these values to exist.
Gerardo Tasistro
Ranch Hand

Joined: Feb 08, 2005
Posts: 362
Nathan what Eduardo means to ask is what would you put instead of the question marks to make the beans configured in you XML available in the main

Nathan Pruett
Bartender

Joined: Oct 18, 2000
Posts: 4121

Gerardo Tasistro wrote:Nathan we are quite aware that the classes inside the XML are not aware of the usage of Spring. "something" and "somewhere" are not calling getBean to obtain "aDependency" and "something" respectively. Spring is handling the wiring. But at some point you will need to use getBean or some other method of obtaining "somewhere". You still haven't shown us how you make use of "somewhere". Up till now it remains an entity inside the Spring application context. In my experience this is achieved either by calling getBean at some point in your application (preferably something like a factory pattern so you can decouple Spring) or by using some class which is inherently aware of the Spring context (for example a Spring MVC controller). In this case, the classes are not aware they're being used by a Spring MVC controller. You don't even need to do anything special to them to wire them through Spring. This is were the "nonintrusiveness" of Spring resides. But I wouldn't go so far as to say "you don't have to explicitly call Spring functions in your code."


Ah, OK - I agree with you Gerardo - you *do* either need to use a framework that understands Spring (like Spring MVC or Spring Rich Client) - or if you're not, you'll need to start up the application context yourself and call getBean() yourself to get a top level bean from your application context. Or you could load your configuration in an ApplicationContext and implement an ApplicationListener to listen for when the context is loaded/refreshed - but then you've got a reference to a Spring specific interface. I guess a better way to say it would be something like - "other than some code to start up the Spring application context and/or get your first bean, you don't need to call Spring functions in your code."
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: nonintrusive in spring