can we implement Spring Autowiring in Java Standalone Application (Swing) - java

I have created an application using Java Swing. Now, i want to integrate Spring Autowiring(Dependency Injection) in this application.
Doubt in mind is that to create UI(User Interface), i would be using "new" keyword, but to use DAO and POJO classes, i want them to auto-wired.
Can somebody suggest and help me out.

Not sure if I understood you right. I assume, that you want to autowire your DAOs, Services etc. in UI classes. But in order do to that, these UI classes would have to be Spring Beans themselves.
What you could do, is to register each UI class in the Spring application context, when its created. To do that, you could create the following class:
public class BeanProvider {
private static ApplicationContext applicationContext;
/**
* Autowires the specified object in the spring context
*
* #param object
*/
public static void autowire(Object object) {
applicationContext.getAutowireCapableBeanFactory().autowireBean(object);
}
#Autowired
private void setApplicationContext(ApplicationContext applicationContext) {
BeanProvider.applicationContext = applicationContext;
}
}
and then in the constructor of each UI class:
public MyUiClass(){
BeanProvider.autowire(this);
}

Related

Ensure spring bean loaded from non spring context

I have spring application alongside (jersey 2.6 classes and ) servlets .
I need to get Spring bean(s) from jersey/non spring context,
Similar question suggested to get context in a static wrapper of context
public static ApplicationContext getContext() {
return context;
}
How can I be sure the context is already loaded or not null?
If I can't, how should I wait/check until it spring context is loaded?
In case of calling from jersey context or calling bean from a simple HttpServlet code
EDIT
Jersey is working fine using jersey-spring3 dependency jar, so my question is only about Servlets out of Spring control
EDIT 2
The application is loading spring different than #entpnerd suggested article
It register a Servlet implementing a WebApplicationInitializer
public class MyWebAppInitializer implements WebApplicationInitializer {
But also have DispatcherServlet configured in web.xml
How can the DispatcherServlet loaded only after Spring loaded?
Because we add Autowiring capabilities on its init method:
WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext())
.getAutowireCapableBeanFactory().autowireBean(this);
Is adding a timeout before serving requests is the most prefer solution or is there a tweak in class loading that can take care of it?
EDIT 3
I found answers and answers of injecting, but not why Spring is loaded before Servlet.
The idea is quite simple, although the actual implementation may vary depending on an exact way of Spring boot and Jersery initialization.
An idea:
Spring boot, as being a purely runtime framework, is all about proper loading the application context (from the question standpoint).
So, bottom line, when it's loaded there is an application context somewhere in memory, and its possible to access beans from this application context.
Now, since you say that Jersey is not spring/spring-boot driven, this application context has to be reachable from some kind of static global variable by Jersey, it's quite ugly but should work.
So the idea has two steps:
Put an application context reference to some static holder accessible from Jersey.
Read this value in some infrastructure level code from Jersey component.
A Possible Implementation
Technically step one can be done by implementing some kind of spring boot listener that will store application context in some kind of singleton:
enum ApplicationContextHolder {
INSTANCE;
private ApplicationContext ctx;
void setApplicationContext(ApplicationContext ctx) {
this.ctx = ctx;
}
ApplicationContext getCtx() {
return this.ctx;
}
}
// and a listener (spring boot provides many ways to register one, but the
// implementation should be something like this):
// The main point is that its managed by spring boot, and hence and access to
// the application context
class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContextHolder
.INSTANCE
.setApplicationContext(event.getApplicationContext());
}
}
Now the step 2 is:
class MyJerseyOrWhateverComponentThatWantsToAccessApplicationContext {
public void foo() {
ApplicationContext ctx = ApplicationContextHolder.INSTANCE.getCtx();
...
ctx.getBean(...);
}
}
So a viable solution for this could happen in two stages:
A Spring bean gets the ApplicationContext instance and sends it to a static singleton outside of the Spring context.
Your standalone servlet gets the ApplicationContext instance from the static singleton and verifies that the right beans have been loaded.
Consider the following code as an example:
SpringMetaBean.java
// #Component so that it's part of the Spring context
// Implement ApplicationContextAware so that the ApplicationContext will be loaded
// correctly
#Component
public class SpringMetaBean implements ApplicationContextAware {
private ApplicationContext appCtx;
public setApplicationContext(ApplicationContext appCtx) {
this.appCtx = appCtx;
}
// #PostConstruct so that when loaded into the Spring context, this method will
// automatically execute and notify ApplicationContextHolder with a reference to
// the ApplicationContext
#PostConstruct
public void setup() {
ApplicationContextHolder.set(this.appCtx);
}
}
ApplicationContextHolder.java
public class ApplicationContextHolder {
// ensure the reference is thread-safe because Spring and standalone Servlet will
// probably be running on different threads.
private final AtomicReference<ApplicationContext> appCtxContainer = new AtomicReference<>();
public void set(ApplicationContext appCtx) {
this.appCtxContainer.set(appCtx);
}
public ApplicationContext get() {
return this.appCtxContainer.get();
}
}
MyStandaloneServlet.java
public class MyStandaloneServlet {
// my request handler method
public void getResponse(HttpServletRequest rq) {
ApplicationContext springAppCtx = ApplicationContextHolder.get();
// if not null, we know that Spring has been loaded and we can dig into the
// application context.
}
}

how to access spring beans from objects not created by spring [duplicate]

This question already has answers here:
spring autowiring not working from a non-spring managed class
(10 answers)
Closed 1 year ago.
In my web application i use hibernate and spring. Entity classes that are returned from Hibernate layer need to access other service classes in some scenarios. Entity classes are not just DTO's they contains some business logic, and to perform some business logic (like may be send out emails etc when some conditions are met) these need to access service classes. Service classes are spring beans. so what's the recommended method in such scenarios to get hold of spring beans from within these entity classes which are created outside spring context?
You are looking for Service-locator pattern,
Implementation in Spring
You can register ApplicationContextAware and get reference to ApplicationContext and statically serve bean
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext ctx;
private static final String USER_SERVICE = "userServiceBean";
#Override
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
public static UserService getUserService(){return ctx.getBean(USER_SERVICE);}
}
Read about #Configurable annotation that allows to configure beans using AspectJ:
Spring reference
Spring blogs
If you don't want to use AspectJ, you could use the
ApplicationContext.getAutowireCapableBeanFactory().autowireBean()
method to configure beans that live outside the spring container. (see java docs).

Spring application context

Is there any other way in J6SE to get spring (spring 3.0) application context than implement ApplicationContextAware interface?
Sorry I must improve my question. I have running application context in my J6SE app and in some classes I need it.
After reading your question, I know you're looking for an alternative to ApplicationContextAware but I read it that you have a goal of many classes using the ApplicationContext but want to avoid implementing the interface for all these classes. This approach still uses the ApplicationContextAware but encapsulates it into a single class for reuses.
I typically load the configuration at application start up via a ContextLoaderListener in the web.xml. After this occurs, I set "MyApplicationContext" as the contextApplicationContextProvider.
<bean id="contextApplicationContextProvider" class="pkg.MyApplicationContext"></bean>
The class must implement ApplicationContextAware as you already suggested:
public class MyApplicationContext implements ApplicationContextAware {
private static ApplicationContext appContext;
/* (non-Javadoc)
* #see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
#Override
public void setApplicationContext(ApplicationContext globalAppContext)
throws BeansException {
this.appContext = globalAppContext;
}
public static ApplicationContext getApplicationContext() {
return appContext;
}
}
The key here is that you now have a static reference to the single instance of the ApplicationContext object. Retrieving it is simple by using the static method call MyApplicationContext.getApplicationContext() for any class, spring-managed or not.
You can load it from the CLASSPATH.
new FileSystemXmlApplicationContext(APPLICATION_CONTEXT_FILE);
#Inject
private ApplicationContext ctx;
(or #Autowired instead of #Inject). This is the annotation replacement of ApplicationContextAware. This of course mean that the objects needs to be a spring bean.

Injecting dependencies using #Autowired into objects created with "new ..."

I have a problem with injecting a bean into a helper class. It works basically like this: I create an object in the page constructor that does some work, returns some data and I show these on the page. In this helper object, a service should be injected via #Autowired annotation. However, I always get a null pointer exception when I use it. I also tried #SpringBean but it didn't help. On the other hand, when I inject this service directly into the page with #SpringBean, it's accessible and works fine. Do you know where the problem is?
This is the page:
public class Page extends BasePage {
public Page() {
HelperObject object = new HelperObject(new Application("APP_NAME"));
String result = object.getData();
add(new Label("label", result));
}
}
Helper object:
public class HelperObject {
private Application app;
#Autowired
private Service service;
public HelperObject(Application app) {
this.app = app;
}
public String getData() {
// use service, manipulate data, return a string
}
}
You can inject dependencies into non-Spring-non-Wicket-new-created objects using #SpringBean by calling InjectorHolder.getInjector().inject(this); in its constructor.
For example:
class MyPojo {
#SpringBean
MyDumbDAO dao;
MyPojo() {
InjectorHolder.getInjector().inject(this);
}
void justDoIt() {
dao.duh(); // dao is there!
}
}
Note that it will only work if called within a Wicket-managed request. If not (ie, if it's a Quartz job, or a Filter executed before Wicket's), the Application instance will not be available, and the injector won't know how to get the dependencies.
Another solution is to use Spring's #Configurable. It uses AspectJ to intercept creation of annotated objects, and inject its dependencies, even if you instantiate them directly with new (or some other framework, like Hibernate, creates them internally). But this requires runtime or build-time (works better for me) bytecode manipulation, which may be too much magic for some people.
#SpringBean only injects dependencies into classes that inherit from Wicket's Component. #Autowired only injects dependencies into classes created by Spring itself. That means you can't automatically inject a dependency into an object you create with new.
(Edit: you can also add a #SpringBean injection to your class by injecting in the constructor:
InjectorHolder.getInjector().inject(this);)
My normal workaround for this is to use my application class to help. (I'm a little puzzled by your use of new Application(...). I assume this isn't actually org.apache.wicket.Application.) For example:
public class MyApplication extends AuthenticatedWebApplication implements
ApplicationContextAware {
private ApplicationContext ctx;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.ctx = applicationContext;
}
public static MyApplication get() {
return (MyApplication) WebApplication.get();
}
public static Object getSpringBean(String bean) {
return get().ctx.getBean(bean);
}
public static <T> T getSpringBean(Class<T> bean) {
return get().ctx.getBean(bean);
}
....
}
In my Spring application context:
<!-- Set up wicket application -->
<bean id="wicketApplication" class="uk.co.humboldt.Project.MyApplication"/>
My helper object then looks up the service on demand:
public class HelperObject {
private Service getService() {
return MyApplication.getSpringBean(Service.class);
}
The best practice would be to create your objects via a factory bean (that has those properties injected by Spring, and have that factory inject those properties to objects it spawns - pure IoC).
You should really avoid using SpringContext all over the place (or any other similar solution for that matter).
Here is a partial list of reasons:
Your code gets coupled with Spring way too much (low-cohesion).
You mix plumbing code with the business-logic.
Your code is less readable.
It's less maintainable (e.g., changing the name of the service bean would lead to code modification - this violates SRP & OCP).
It's less testable (e.g., you need the Spring framework to test it).

Good way to access Spring singleton from within domain objects?

I have a domain model that consists of fairly large object graphs, where domain objects are creating other domain objects and so forth. Each of these domain objects needs access to a small handful of singleton-type helper objects for various purposes.
I was about to implement them using the Java singleton pattern when I remembered that I am already using Spring and I can use Spring to instantiate one of each of these helpers at application startup.
My question is how to I find them from within my domain objects? These are all objects that are created via the "new" operator and are not under the control of Spring.
I'm thinking I could use the "getBean" method if I had my hands on the Spring application context (which I don't) -- but is the performance of this good? I need this stuff to be fast... And how to quickly get the application context?
In a typical Spring application, the kind of cross-entity logic you're describing is usually implemented in the business service layer (i.e. the Spring-managed singletons), not the domain objects. Domain classes in Spring apps tend to be fairly simple data containers, perhaps with some methods for performing basic operations on the data they encapsulate, but stopping well short of managing complex object graphs outside of themselves. So business service objects manage domain objects, not the other way around.
If you insist on injecting singletons into your domain objects, though, you can achieve this using AspectJ. Spring itself does not support this very well.
public class SpringApplicationContextProvider implements ApplicationContextAware {
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
// Wiring the ApplicationContext into a static method
SpringApplicationContext.setApplicationContext(ctx);
}
}
And define SpringApplicationContext as,
public class SpringApplicationContext {
private static ApplicationContext ctx;
public static void setApplicationContext(
ApplicationContext applicationContext) {
ctx = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
private SpringApplicationContext(){
}
}
Define SpringApplicationContextProvider as a spring bean in your config file. Now the application context can be accessed using this provider.
look at the answer to the question # Injecting beans into a class outside the Spring managed context

Categories

Resources