views:

76

answers:

2

My idea is to create a .jar file that contains Services

managed by Spring, that should be got by getBean()

I want to put it to WEB-INF/lib of a Web-app

Then in web-app Servlets I want to get use of the functionality of a Jar file.

1 Idea. Create classes that encapsulate invokation to Spring Context (getBean() etc) For example, the class I'll be using will simply get a parameter and return a parameter, but inside that class there'll be an invocation to Spring's getBean etc.

In this case, I suppose there'll be no problem in using those in Servlets through jar import. Only thing, what kind of context I should use inside .jar to get beans so that it worked after packing into jar? ApplicationContext or what?

2 Idea. Is there another simple solution how to pack into jar and then use Services in a non-managed by Spring environment?

+2  A: 

If you're calling getBean() on an ApplicationContext, I have to think that you're somewhat missing the point. Spring was invented to get rid of this exact problem. Spring works on the principle of dependency injection (inversion of control). That means you inject the services to where they're needed rather than you ask for them by name and if they are named, that naming is part of configuration not code.

There is no issue using classes from another jar as long as its part of the classpath. They're just loaded like any other class. Even if they're not in the class path you can use a ClassLoader if required to get them. Where it gets a bit more complicated is where the classes are in another JVM. Even that can be done but it sounds like its not the case here.

Where is this parameter you're talking about? I would strongly urge you to consider to binding named services to some context in a RESTful kind of way (something well-supported in Spring 3 MVC) rather than implementing some kind of registry or even explicit service location from a manually loaded context.

cletus
@cletus you right, but if you look at a Service as a whole block, then you should be able to get it from somewhere right? getBean() is a way to go.
EugeneP
@Eugene it's *a* way to go. It's just not a very good way to go. It's an implementation detail that Spring is built to hide from you. For good reason.
cletus
@cletus Parameter I'm talking about is this thing. I mean, I construct an object that needs to be saved in a database and pass it to a ServiceLayerWraper method. It looks like there's no DAO inside, but in reality that wrapper class [SeviceLayerWraper] will getBean() to get a ServiceLayer object from Spring and pass the reference object by chain to it. Then, ServiceLayer will save it in a database (invoking its dependency, DAO).
EugeneP
@cletus Also, could you please clarify your point? Dependencies must be configured through spring. But the whole Service, I mean the objects you use on the highest level of abstraction, should be got in some way. If not by getBean() then how? Using @Configurable and AOP?
EugeneP
+1  A: 

There's a lot possibilities of doing that. To use Spring, you don't need EVERYTHING to be Spring.

For instance, you can configure Spring in your web.xml:

<web-app ...>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:com/acme/foo/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    ...
</web-app>

In your servlets you can do WebApplicationContextUtils.getWebApplicationContext(servletContext).getBean("myBean") to access beans.

Depending on the environment there are other means for integration. For instance, you can use org.springframework.web.jsf.el.SpringBeanFacesELResolver in JSF. Here is an example of JSF application with Spring-managed beans.

lexicore
@lexicore Your config snippet looks great (if it works). Could I ask you about some details? You see, it seems to me that in that case we should put Spring-managed classes somewhere to WEB-INF/classes. What about a separate .jar file. Will this config work if everything is packed into a jar and it is put into WEB-INF/lib?
EugeneP
@EugeneP Surely it works, check the sample project I posted the link to. And it certainly does not matter if the classes and applicationContext.xml is in WEB-INF/classes or as jar in WEB-INF/lib. They will be loaded from the classpath. I'm 100% sure of this, this is exactly what we do in a number of projects.
lexicore
@lexicore I use "context:component-scan" in beans.xml, maybe that is a problem. I compiled a jar, put it in WEB-INF/lib, edited web.xml as you suggested. I don't understand one thing: where to put beans.xml? Shall I keep it in a jar file or put it in WEB-INF directory? I tried both ways and the result is the same: I can get beans that present explicitly in beans.xml, but cannot get component-scan work (@Autowired). The error is: "No bean named ... is defined". Any ideas?
EugeneP
@EugeneP Sorry, I'm not using context:component-scan.
lexicore
@lexicore You helped me greatly. That component-scan issue is resolved. Your snippet works perfectly. Also, we can getAutowireCapableBeanFactory() and even make a Servlet itself a bean ! Thank you very much!
EugeneP