The following is the situation :
I have a business layer, that is an EJB project. In fact, there is only one EJB that is created. This EJB is responsible to expose the service classes to other layers, that calls the EJB. I want to introduce spring (to use DI feature) in this layer.
My concern is, what is the best way to load the spring context in this business layer, so that the spring context does not get loaded again and again, whenever the EJB gets called ?
(In a Web project, there is an advantage rather to configure the spring context in contextLoaderListener, and it gets loaded once only when the application gets started)
I have thought of including spring in the same layer because :
Configure the dependencies of all DAO and service classes and inject them wherever necessary.
To use spring support for hibernate in the business layer.
Ease of Unit testing, by injecting the properties into classes and simulating the same. Don't need to run the other layers again and again, to test my business classes/methods.
To be able to use AOP (Aspect Oriented Programming) for Logging and method level auditing.
Kindly help me suggesting the best way, to load the spring context in an EJB project. I also want to know , if there are any alternatives if I can load the same in the app server (I am using Web sphere app server).
Thanks and Regards,
Jitendriya Dash
Spring should be configured as part of your application in the normal way that you always set it up. Then you need to access the Spring beans from the EJB layer. To access (adapted from this post), create a Spring bean as follows:
#Component
public class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext CONTEXT;
public void setApplicationContext(ApplicationContext context) throws BeansException {
CONTEXT = context;
}
public static Object getBean(String beanName) {
return CONTEXT.getBean(beanName);
}
}
Then, to call the bean in question from the legacy app:
SomeService someService = (SomeService)SpringApplicationContext.getBean("someServiceImpl");
The Spring context is initialized once, and your EJB layer can access at will.
For EJB3, Spring recommends using an EJB3 Injection Interceptor. Basically you specify your Spring context using a ContextSingletonBeanFactoryLocator which entails creating your Spring context in a beanContextRef.xml in your classpath. Probably as part of your EAR. The SpringBeanAutowiringInterceptor injects your bean into your EJB.
Marking the EJB been as a Singleton (#Singleton). And storing the spring context in a variable in this bean, after it is created once, so that you can return the same context again and again.
Related
I am trying to understand how to best make use of spring application context hierarchies. Assuming I have an Application where I have #Controller beans, #Service beans, and #Repository beans, representing a front-end, business and persistence layer, it would seem nice if the layers had contexts in which only beans are visible which are relevant to the context. It would also be nice if I did not need special code for creating beans, just using #Autowired should be enough.
I can create a context for my repositories, let's say repoContext, in which there exist only the repository beans. The service layers needs access to those, but not vice versa, so I'd might create another context serviceContext which has repoContext as parent. Now the front-end layer needs the services, so I might create a controllerContext with serviceContext as parent. But doing so, the controllerContext would also be able to deliver repository beans to the front-end layer, which is the opposite of what I wanted.
So it seems to me that to properly separate bean dependencies in separate contexts, the parent-child relationship is not very useful to provide dependencies to a context.
Is there any better way? Could there be a front-end and a backend context sharing configuration of the service beans, but with the backend context being resposible to insatntiate service beans first (because only this context has repositories)? Or would that approach lead to the frontend context trying to instantiate own service beans?
After forced switching from Spring to EJB (EJB3) in my workspace, I find it problematic to rewrite the utility functions, that made some manual tasks like creating a few records or importing some dictionaries into database.
In Spring I could easily initialize the application by calling new ClassPathAXmlApplicationContext('spring.xml'). Is there any similar utility class for EJB? I'm using EJB implementation from Websphere 8, to be more specific.
Asking google for "Initializing EJB context" gave me nothing useful, maybe it was not correct search phrase?
In case you're starting (embeded) EJB container or doing something of this kind, singleton session bean can be annotated with #Startup annotation and it's #PostConstruct life cycle method will be invoked after container startup.
#Startup
#Singleton
public class StartupBean {
#PostConstruct
void init {
...
}
...
}
EDIT:
There's WebSpehere documentation on how to run embeded container and invoke EJB's. But note that embeded container has to support only EJB Lite specification:
The embeddable container does not support the use of Contexts and
Dependency Injection (CDI).
I have 2 spring contexts: "webapplication" context and a "core" context. The context "core" is initialized at server startup and attached to a Singleton class that holds the context. The "webapplication" context is initialized when the webapplication is started.
I want to inject bean dependencies from beans in one context to the other (bidirectional access). The webapplication beans are to be "session" scoped beans.
I'm testing this proof of concept with: webapp bean --> (that depends on) core bean --> (that depends on another) webapp bean.
At the webapplication context initialization i could inject "core" beans to the "webapplication" beans (a BeanFactory that acceses the singleton do the magic), but can't figure out how to do the inverse; because the Spring ThreadLocal that holds the WebApplicationContext is not yet initialized.
The question is. Is it what i'm trying to do possible? If the answer is "yes", how would you do that?
Thank's in advance.
EDIT:
I'd realized i'm doing something wrong. The fact is that i'm trying to inject in the service layer a dependency to a session bean, at the wrong time; that is, at the web initialization time when i have no current user session.
This looks to me like an architectural issue, not a technical (and certainly not Spring) one. Your separation between core context and web context is very good. The former handles business processes while the latter is responsible for representation, maybe some API.
The dependency from web (representation, access) to core is understandable and required - after all you are building an interface over business routines. This is how spring-mvc works by default, creating separate child (web) application context of core context.
I can hardly imagine a use case for inverted dependency. Why is your business logic depending on web layer? What if you try to migrate your application one that to a different representation technique (desktop, mobile)? Can you justify the reason for this inverted dependency? What do you mean by session bean?
Bidirectional dependencies, as well as static singletons holding a class-loader wide reference to application context should indicate that something is wrong with the design.
I need to get the servlet application context in the business layer of an spring mvc application.
I've tried implementing ApplicationContextAware interface, autowiring a WebApplicationContext field, and even implementing ServletContextAware and getting the application context with WebApplicationContextUtils, but none of this works.
Is there any other way to get it? I want to avoid having to pass an HttpServletRequest parameter from the controller to get the application context in the business object.
If it helps for something, I'm running on a WebSphere 6.1 server, and I think it has the servlet 2.4 api.
Implementing ApplicationContextAware and injecting ApplicationContext work. So that's the way to go. You must find what other problem stops it from working (how does it not work, actually?)
For example make sure the service class is not instantiated by you using the new operator.
By the way, you cannot and should not get the child application context (defined by dispatcher-servlet) in the service layer. This means that parent would know about child contexts - and it does not. You are thus breaking the layer boundaries. Think of another way of handling this task - for example have the context injected in a controller (it should work there), and then pass the desired arguments to a service.
Can or should a Service layer be a Spring bean?
If so, how should it be got from a calling application, a consumer of a service?
Because the consumer must be aware that such a bean exists, so it in any case must use Spring
to make use of Service methods.
Of course. The service layer is the part of your application that is visible to other users (e.g. a Web layer) so it needs to be configured and setup somewhere. Imho a Spring configuration is the best place to put this configuration in. The Service Layer user then has to take care of instantiating that context and getting the Service Objects he needs.
An alternative - if it needs to run standalone - would be for your service class(es) implementing the Service Layer interface(s) to instantiate the Spring application context themselves.
By making your consumers also spring beans, and inject the service bean with dependency injection.
Yes, It is always nice to configure service beans as spring beans. In the web layer you need to take care of instantiating the needed service objects. Another option is to make the web layer classes also as spring beans and inject the necessary service layer spring beans. From the testing point of view also, this type of design is very helpful when we use Spring testing framework.