Spring JSON View: ApplicationObjectSupport does not run in an ApplicationContext - java

I'm trying to use a Json View for Spring (http://spring-json.sourceforge.net/) (org.springframework.web.servlet.view.json.JsonView) but whenever I write a controller class that extends AbstractController I get the following Error:
java.lang.IllegalStateException: ApplicationObjectSupport instance [org.springframework.web.servlet.view.json.JsonView] does not run in an ApplicationContext
The weird thing is, that when I implement the Controller interface directly and do not inherit, it is fine. The error only happens when I inherit from AbstractController.
In my current case though I would like to extend AbstractFormController and hence can't write a class that does not inherit from AbstractController.
Any ideas?

That's a rather misleading error message, it's actually complaining that the JsonView is not running inside an app context. What it means is that the JsonView bean was not instantiated by Spring, but that you instantiated it yourself (JsonView extends ApplicationObjectSupport, and should therefore be Spring-managed).
However, you haven't given us any of your code, so it's hard to tell for sure. I'm guessing your controller is instantiating JsonView itself? You need to let Spring do that, either by injecting a JsonView bean into the controller, or perhaps using a ViewResolver (if Spring-Json supplies one).

If you are doing Java configuration ( as opposed to XML ), in your configuration class you may want to call setApplicationContext method on object that is complaining.
This is what did the trick for me in Spring MVC 3.2.2 when trying to initialize ContentNegotiatingViewResolver in Java.
Here is the sample configuration class:
#Configuration
#EnableWebMvc
...
public class MyConfig
{
#Inject
private ApplicationContext appContext;
#Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver ( )
{
ContentNegotiatingViewResolver retVal =
new ContentNegotiatingViewResolver( );
...
retVal.setApplicationContext( appContext );
return retVal;
}
}

Related

How to call Spring Framework repositories methods

I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:
#SpringBootApplication
public class Application {
private static final Logger log =
LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
...
// more lines, etc...
What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.
The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?
When creating a #Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding #Autowired annotation inside a class that is annotated as #Component or something similar.
Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.
Can you try #Repository before the declaration of class? Worked for me in a Spring MVC structure.
#Repository
public class EntityDAOImpl implements EntityDAO{
...
}
The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with #Service, #Repository, etc.
This means the default constructor (or the one marked with #Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.
Where the #Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an #Configuration annotation on it, and expose an #Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.
Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with #PostConstruct.
Some useful links / references:
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
Running code after Spring Boot starts
Execute method on startup in Spring

AnnotationConfigApplicationContext has not been refreshed yet

I am developing a spring MVC application. When I try to use AnnotationConfigApplicationContext in my controller class I am getting the following error. I have no idea what this statement exactly means.
#RequestMapping(value = "/generate", method = RequestMethod.POST)
public ModelAndView generateMappingFile(#ModelAttribute Mapping mapping)
{
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
MappingFileGenerator mfg = ctx.getBean(MappingFileGenerator.class);
}
Error Message -->
java.lang.IllegalStateException:org.springframework.context.annotation.AnnotationConfigApplicationContext#116b3c0 has not been refreshed yet
Can someone explain me what went wrong here ? I am using Spring 4.0.1.. I am new to spring mvc.
When you are creating a new instance of an ApplicationContext (regardless which type) you are basically creating new instances of each and every bean configured in that ApplicationContext. That is nice the first time, it might work the second and depending on the amount of beans, the type of beans will crash after that. As the context will never be destroy (until the app crashed and is restarted) you will run into possible memory issues, performance issues, strange transactional problems etc.
A general rule of thumb is to never construct a new instance of an ApplicationContext but to use dependency injection instead.
If you really want access to the ApplicationContext put a field of that type in your controller and put #Autowired on it.
#Controller
public class MyController {
#Autowired
private ApplicationContext ctx;
….
}
Then you can do a lookup for the bean you need in the method. This can be handy if you use the ApplicationContext as a factory for your beans. If all the beans you need are singletons it is better to simply inject the bean you need.
#Controller
public class MyController {
#Autowired
private MappingFileGenerator mfg ;
….
}
Now Spring will inject the MappingFileGenerator and it is available for use in your methods. No need to create a new instance of an ApplicationContext.
More information is in the Spring Reference Guide.
#M.Deinum's comment will get quite a few more upvotes.
Think of creating a new ApplicationContext as instantiating a new (instance of an) application. Do you want to do that every time this (or any other method in said application) is called? No, you don't.
I'm guessing you think you do because you need access to your ApplicationContext in this method. To do that - i.e. to get access to the running application context (rather than creating a new one), you want to do
#Controller // or #Service / #Component / ... : tells Spring that this is a bean, and to inject the specified dependencies
class YourClass {
#Autowired // tells Spring that this object is a dependency should should be injected
ApplicationContext ctx;
#RequestMapping(value = "/generate", method = RequestMethod.POST)
public ModelAndView generateMappingFile(#ModelAttribute Mapping mapping) {
MappingFileGenerator mfg = ctx.getBean(MappingFileGenerator.class);
}
The key here is the Autowired annotation, which tells Spring to inject the annotated object as a dependency.
I highly suggest following the links I've included (for starters), as what you're doing here suggests pretty strongly that you haven't wrapped your head around what DI is and does for you, and until you do, using it is likely to be counterproductive toward it's own ends for you.
In case it helps someone, i was having this issue on a new URL Mapping added to a gradle project, i was missing the first slash of the url and that causing this "illegalstate not refreshed yet" on my tests

Spring - passing a custom instance to a constructor

I'm trying to implement a command-query design pattern into
a MVC spring based application.
I have, for example, some decorated commands using decorator pattern
like bellow:
ICommandHandler handler =
new DeadlockRetryCommandHandlerDecorator<MoveCustomerCommand>(
new TransactionCommandHandlerDecorator<MoveCustomerCommand>(
new MoveCustomerCommandHandler(
new EntityFrameworkUnitOfWork(connectionString),
// Inject other dependencies for the handler here
)
)
);
How can I inject such a handler into a controller constructor? Where should
I instantiate this handler? A place where this can be instantiated can be
the controller constructor, but this isn't the best solution. Any other ideeas?
Thanks
If you're using PropertyPlaceholderConfigurer (old) or PropertySourcesPlaceholderConfigurer (new), and your connection string is in a .properties file or environment variable you can do the following for the connection string. You can also autowire objects into a configuration class and annotate a method with #Bean to do what the Spring context xml does. With this approach you can create your beans as you wish and they're available to autowire just like you defined them in xml.
#Configuration
public class MyAppConfig {
#Autowired private MyType somethingToAutowire;
#Bean
public ICommandHandler iCommandHandler(#Value("${datasource.connectionString}")
final String connectionString) {
return new DeadlockRetryCommandHandlerDecorator<MoveCustomerCommand>();
// You obviously have access to anything autowired in your configuration
// class. Then you can #Autowire a ICommandHandler type into one of your
// beans and this method will be called to create the ICommandHandler (depending on bean scope)
}
}

#Resource annotation producing NPE

I "inherited" a large Spring application with a spring-ws service in it.
The service is the typical Spring-WS code:
package service;
#Endpoint
public class ServiceEndpoint {
#Resource EntityDao entityDao;
#PayloadRoot(localPart=...)
#ResponsePayload
public ResponseWrapperClass getServiceMethod(#RequestPayload RequestWrapperClass request) {
return new ResponseProcessorClass(request).generateResponse();
}
}
The service is massive, and the entityDao injected with the #Resource annotation is used widely in the class.
Because the specific method I'm working on is a bit complex, I have encapsulated it in a separate class in a subpackage.
The ResponseProcessorClass looks like this:
package service.business;
#Component
public class ResponseProcessorClass {
#Resource EntityDao entityDao;
public ResponseWrapperClass generateResponse() {
entityDao.getSomeData(); //encapsulates hibernate logic -> Null Pointer Exception
}
}
As you can see by my comments above, I get a Null Pointer Exception when using the #Resource annotation in my new class.
I haven't used this annotation before, but for what I understood from the documentation the type should be inferred and injected. I could not find any configuration in any XML file for it either.
Could anyone tell me why am I getting the NPE?
Spring can only inject Spring managed beans into Spring managed beans. Therefore, if you create the object yourself, Spring can't do anything about it. This
return new ResponseProcessorClass(request).generateResponse();
is the problem. You are expecting Spring to inject a field of the ResponseProcessorClass object you created.
Try injecting a prototype bean instead of creating it yourself. This depends on your ResponseProcessorClass class.

Injecting beans into a class outside the Spring managed context

I'm an end-user of one of my company's products. It is not very suitable for integration into Spring, however I am able to get a handle on the context and retrieve the required bean by name. However, I would still like to know if it was possible to inject a bean into this class, even though the class is not managed by Spring itself.
Clarification: The same application which is managing the lifecycle of some class MyClass, is also managing the lifecycle of the Spring context. Spring does not have any knowledge of the instance of MyClass, and I would like to some how provide the instance to the context, but cannot create the instance in the context itself.
You can do this:
ApplicationContext ctx = ...
YourClass someBeanNotCreatedBySpring = ...
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(
someBeanNotCreatedBySpring,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
You can use #Autowired and so on within YourClass to specify fields to be injected etc.
One way to bring a bean into Spring despite its manufacture being external is to use a helper class marked as a #Configuration bean that has a method (marked with #Bean) that actually makes the instance and hands it back through Spring (which does its property injection and proxy generation at that point).
I'm not quite sure what scope you need; with prototype, you'll get a fresh bean in each place.
#Configuration
public class FooBarMaker {
#Bean(autowire = Autowire.BY_TYPE)
#Scope("prototype")
public FooBar makeAFooBar() {
// You probably need to do some more work in here, I imagine
return new FooBar();
}
}
You can inject properties required for manufacture into the #Configuration bean. (I use this to create instances of an interface where the name of the class to instantiate is defined at runtime.)
suppose that u have the following dependency chain:
A --> B --> C --> x --> y -- > Z
A, B, C are spring managed beans (constructed and manged by spring framework)
x, y are really simple POJOs that constructed by your application, without spring assistance
now if you want that y will get a reference to Z using spring that you need to have a 'handle' to the spring ApplicationContext
one way to do it is to implement ApplicationContextAware interface . In this case I would suggest that either A, B or C will implement this interface and will store the applicationContext reference in a static member.
so lets take Class C for example:
class C implmenets ApplicationContextAware{
public static ApplicationContex ac;
void setApplicationContext(ApplicationContext applicationContext) {
ac = applicationContext;
}
.............
}
now, in class y you should have:
(Z)(C.ac.getBean("classZ")).doSomething()
HTH -- Yonatan
Another way to do this is to us use AspectJ. This is the recommended way of injection Spring beans into non-managed objects that are created with the new operator. See this for details:
http://www.javacodegeeks.com/2011/02/domain-driven-design-spring-aspectj.html
Searching endless combos of autowire inject spring bean into pojo applicationcontextaware beanaware etc circled me back here but this didnt provide a complete enough solution for me.
This is a much better implementation/tutorial of this IMO:
I hope it helps everyone like it finally helped me.
Accessing Spring Beans from outside Spring Context
Be careful that in oldest version of Spring, there is thread-safe problem with bean factory http://jira.springframework.org/browse/SPR-4672
If you want to create an object outside the Spring context, and make that object available for injection into other beans that are in the Spring context, you can follow the steps in this article.
Basically, you create a parent application context and push your external object into this parent context as a singleton. Then you create you main application context (for example, from xml files), with the parent application context as its parent.
Object externalObject = ...
GenericApplicationContext parent = new StaticApplicationContext();
parent.getBeanFactory().registerSingleton( "externalObject", externalObject );
parent.refresh();
ApplicationContext appContext = new ClassPathXmlApplicationContext( ... , parent);
From a Spring configuration class, set a static field on the non-Spring class that needs the beans.
I have an example in my answer to a Liquibase question: https://stackoverflow.com/a/71191546/5499391

Categories

Resources