Page 1 of 2 12 LastLast
Results 1 to 10 of 17

Thread: Access application context from code without servlet context

  1. #1
    Join Date
    May 2006
    Location
    Zug, Switzerland
    Posts
    89

    Default Access application context from code without servlet context

    Hi

    I'm designing a pretty straight-forward web application. As we'll have approx. 40-50 business classes and around 50 DAO implementation classes, I'd like to provide factory classes for these (DAOFactory). However, as soon as I move the bean creation into the code and away from the Spring context, I loose the references.

    For the DAOFactory, I'd need a reference to the Hibernate sessionFactory. How do I get such a reference? I'm aware of WebApplicationContextUtils.getWebApplicationContex t, but I'd need a servlet context for that method. I don't have a servlet context in my DAOFactory, and I'd rather not couple the DAOFactory with some presentation layer class.

    Currently, I've added an ApplicationContext class which implements BeanFactoryAware, stores the BeanFactory and and has a getter for the BeanFactory. But that's ugly.

    An obvious but - imho - short-sighted solution would be to create a DAOFactory bean in the Spring context XML and pass a reference of the sessionFactory bean. With this, my problem would simply be shifted from

    How does the DAOFactory get the sessionFactory instance

    to

    How does the business layer get the DAOFactory instance

    Nothing solved, really.

    Appreciate any help, links (or even a RTFM if a chapter is provided).
    Simon

  2. #2
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    The clean approach would be to wire everything inside the spring context. That way you would not need a reference to the ApplicationContext as all beans would be configured completely.

    If that is not feasible (e.g. for porting an existing application) the best approach would IMHO be to store the ApplicationContext in a well known place. As I understand this is the approach you are currently taking. So, if you cannot (yet) wire everything inside the context, that approach would be fitting. As alternative to subclassing ApplicationContext, you could also use a ServletListener (executed after ContextLoaderListener) to retrieve the context and store it in some place accessible by the application.

    Regards,
    Andreas

  3. #3
    Join Date
    May 2006
    Location
    Zug, Switzerland
    Posts
    89

    Default

    Andreas,

    thank you very much for your feedback. I feel I understand the "Spring way" more or less, but I can't understand how it's possible to write large applications where ALL beans are wired together in the context XML.

    Say I need to load a specific client (based on an field from an order provided in a HTML form) from the database to validate something. How do I retrieve this client object?

    Could you send me a sample application context configuration (or images of the Spring bean graph) for a middle-sized application? (simon dot niederberger at want dot ch). We'll have around 50 business classes, approx. 80 JSP pages.
    I feel the Spring tutorials which just show a "login" or something fall short of showing how to handle larger applications.

    Thanks
    Simon

  4. #4
    Join Date
    Nov 2004
    Location
    Hilversum - The Netherlands
    Posts
    1,054

    Default

    Quote Originally Posted by sniederb
    Andreas,

    thank you very much for your feedback. I feel I understand the "Spring way" more or less, but I can't understand how it's possible to write large applications where ALL beans are wired together in the context XML.
    You don't wire all beans up in the application context. In most cases you just need to wire the 'singleton' beans: Managers, Dao, Controllers etc.

  5. #5
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    Quote Originally Posted by sniederb
    I feel I understand the "Spring way" more or less, but I can't understand how it's possible to write large applications where ALL beans are wired together in the context XML.
    Think of it like that: Without Spring you wire the objects constituting your application programmatically. Spring allows you to do this declaratively, relieving you from singletons and programmatic factories, thus encouraging the use of interfaces.

    Quote Originally Posted by sniederb
    Could you send me a sample application context configuration (or images of the Spring bean graph) for a middle-sized application?
    I have no sample application at hand, but have a look at the "samples" folder of your spring distribution. There are some applications which show how spring-apps can be wired.

    Regards,
    Andreas

  6. #6
    Join Date
    May 2006
    Location
    Zug, Switzerland
    Posts
    89

    Default

    Alarmnummer

    Then, what is the "best practice" to access the singletons from your code?

    Thanks
    Simon

  7. #7
    Join Date
    Nov 2004
    Location
    Hilversum - The Netherlands
    Posts
    1,054

    Default

    Quote Originally Posted by sniederb
    Alarmnummer

    Then, what is the "best practice" to access the singletons from your code?

    Thanks
    Simon
    A good example can tell more than a 1000 words.

    example:
    Code:
    class EmployeeManager{
       	private EmployeeDao employeeDao;
    
     	public void setEmployeeDao(EmployeeDao employeeDao){
     		this.employeeDao = employeeDao;
     	} 
     	
     	public void fire(long employeeId){
     		Employee employee = employeeDao.load(employeeId);
     		.. some fire logic
     		employeeDao.update(employee);
     	} 
    }
    
    class EmployeeDao{
    	Employee load(long id){....}
    	void update(Employee e){....}
    }
    
    class FireController extends SomeSpringMVCController{
    
    	private EmployeeManager employeeManager;
    	
    	public void setEmployeeManager(EmployeeManager employeeManager){
    		this.employeeManager = employeeManager;
    	}
    
    	ModelAndView onSubmit(HttpRequest request, HttpResponse resp){
    		long employeeId = RequestUtils.getRequiredLong(request,"employeeId");
                    employeeManager.fire(employeeId);
                    return new ModelAndView("success");
    	}
    }
    
    
    <bean id="employeeDao" class="EmployeeDao"/>
    
    <bean id="employeeManager class="EmployeeManager">
    	<property name="employeeDao" ref="employeeDao"/>
    </bean>
    
    <bean id="fireController" class="FireController">
    	<property name="employeeManager" ref="employeeManager"/>
    </bean>
    You can see that nobody needs to access the ApplicationContext directly.
    Last edited by Alarmnummer; Jun 8th, 2006 at 03:54 AM.

  8. #8
    Join Date
    Sep 2004
    Posts
    1,086

    Default

    Quote Originally Posted by sniederb
    Andreas,

    thank you very much for your feedback. I feel I understand the "Spring way" more or less, but I can't understand how it's possible to write large applications where ALL beans are wired together in the context XML.

    Say I need to load a specific client (based on an field from an order provided in a HTML form) from the database to validate something. How do I retrieve this client object?

    Could you send me a sample application context configuration (or images of the Spring bean graph) for a middle-sized application? (simon dot niederberger at want dot ch). We'll have around 50 business classes, approx. 80 JSP pages.
    I feel the Spring tutorials which just show a "login" or something fall short of showing how to handle larger applications.

    Thanks
    Simon

    I have applications in production with over 100 Spring configured beans (120-150).

    It works well if you split context files into logical units, put each context file in the same package with classes that are wired in it (when it's possible) and use <import/> tags.

    Personally, I find it totally unnecessary to try to "visualize" the whole bean graph and I don't use any kind of special Spring support for my IDE. The whole graph may be huge but you are almost always working with one tiny part of it and the wiring of that tiny part is more often then not trivial. (Injecting datasources into daos, for example - it's a pretty big chunk of xml, even when using abstract parent, but it's totally trivial.)

  9. #9
    Join Date
    Jul 2006
    Posts
    2

    Default Access application context from code without servlet context

    I feel like a moron, but here goes...

    I have a problem similar to the question asked by sneiderb. I feel I've painted myself into a corner 'over-using' dependency injection.

    I have two web applications. One is a Tapestry user interface program that creates XML requests and sends them to a remote servlet via Hessian. The remote back-end servlet uses Spring to inject dependencies. Being a Spring novice, I naively used singleton mode for all the spring injected beans. Needless to say, this can wreak havoc in the multi-threaded environment that is a web application/servlet.

    Now I find that I need several of the back-end beans to be prototypes rather than singletons. The problem is, even if I change some of the beans to prototypes, they are injected into singleton's which are in-turn injected into singletons, etc. So my prototype beans will only ever be created once themselves!

    My first thought was to extend the DispatcherServelet, grab the WebApplicationContext in the servlet, and create a wrapper around the context that other beans 'down stream' from the servlet can create new instances of beans using the 'getBean("beanId")' interface. This doesn't fee right, either.

    The general architecture is this: The servlet is hooked to a bean whose interface is exported by a HessianExporter. All the spring beans are wired together in the configuration for this front-end exported bean.
    The exported class contains a reference to a command factory. Commands are retrieved from the command factory and a service manager is used to obtain references to services that are called by the commands. Unfortunately, the command factory, commands, and services are all configured to be singletons.

    Hopefully, I'm not a unique moron and you folks have seen this type of quandry before. Any advice on how to 'un-paint' myself from this corner would be appreciated.

  10. #10
    Join Date
    Feb 2005
    Location
    Cambridge, UK
    Posts
    37

    Default

    In general the thread-safety issue is best attacked through simply not using prototypes. If you can rewrite your service beans to this model, you probably should - the "base" Spring idiom is to package your services as a set of thread-safe, fully re-entrant singleton "service" beans which are wired together once only at app startup and then afterwards not touched by the framework. The use of "prototypes" or Spring "non-Singletons" can get you out of a couple of tight corners, but as you find in your design, ultimately not terribly many :P

    As a more general solution to the non-singleton problem, I do find the "request-scope IoC" idiom in something like RSF extremely helpful, and it's worth noting that Spring itself is moving in this direction with the new support for "scoped" beans coming in Spring 2.0. Obviously I am not entirely impartial here :P

    But, having an explicitly identified and characterised "scope" in which more ephemerally created beans are wired together is worth its weight in gold.

    You're right that solutions based on interfering with "irrelevant" dependencies like the DispatcherServlet, and using explicit fetch of beans using "getBean()" is not right. Explicit bean fetches "by name" should occur in at most one point in a Spring application, at some major integration boundary with a foreign technology, and ideally should not occur at all (since this integration code is in general already written for you by Spring for most major technologies).

    In the general context of the thread, I'm not sure your question actually *is* the same as sneiderb's. In his case the issue simply seems to be making the necessary conceptual shift to working with indeed *all* of your (singleton) beans wired together in the application context. For example he asks, "how do I access the sessionFactory from my DAOFactories", to which the answer is simply "inject it there". And if you find yourself with a pattern where you have "too many" (i.e. an "auto-definition" requirement) products to be configured into the Spring context, simply inject the dependency one higher up. I.e. at the point you want to leave Spring behind, terminate the managed bean tree in a "DAOFactoryFactory" which has the sessionFactory injected into it, which it supplies in the usual way (via constructor arguments, or properties), in code, to its products. This solution is not "short-sighted", you merely see as far as you need to :P
    Last edited by Bosmon; Jul 2nd, 2006 at 06:29 PM.

Posting Permissions

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