In my Wicket page I have:
#SpringBean
protected J2EContext j2EContext;
In Configuration I have:
#Bean
#RequestScope
public J2EContext getWebContext() {
return new J2EContext(request, response, getSessionStore());
}
#Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
application starts OK but when I go to home page I got exception:
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:931)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:631)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:
329)
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
when wicket want to inject J2EContext bean. I think this is because page is rendering before #RequestScope create this bean. Any idea how to fix this problem ?
to inject beans Wicket creates a proxy in two different ways:
If bean is an interface a standard java.lang.reflect.Proxy is created
If bean is a class cglib is used by default
Unfortunately cglib can not create proxy for classes without a default constructor. There is however a third way that can solve the problem. Just add objenesis as dependency to your project and Wicket will use it instead of cglib.
Related
Originally, there was a service instance to access the database and now we want to add a readonly instance. So I add the serviceReadonly in my configuration.
#Configuration
public class Config {
#Bean Service service() {...};
#Bean Service serviceReadonly() {...};
#Bean Proxy proxy() {return new Proxy(serviceReadonly())}; // replace the original Proxy(service())
}
But, the service is also autowired to Proxy
#Component
public class Proxy {
#Autowired
public Proxy(Service service) {this.service = service;}
}
I am confused which Service is injected in my API? service or serviceReadonly?
#Component
public class API {
#Autowired
public API(Proxy proxy) {this.proxy = proxy;}
}
The Proxy and API classes are in another shared library and avoiding change to the library is preferred. Also, the service is autowired to other components.
Short answer: #Bean Service service()
Explanation: Excerpt from the Spring documentation here
Autowiring by property name. Spring looks for a bean with the same
name as the property that needs to be autowired. For example, if a
bean definition is set to autowire by name, and it contains a master
property (that is, it has a setMaster(..) method), Spring looks for a
bean definition named master, and uses it to set the property.
I assume it will be #Bean Service service() because the Spring would find the bean with same name as the property i.e. Service as defined in official Spring guide.
You may also need to look into #Qualifier annotation. It is because if there is not exactly one bean of the constructor argument type in the container, a fatal error is raised, as mentioned in Spring documentation here. Have you checked if you receive this error of NoUniqueBeanDefinitionException? In that case you can use #Qualifer annotation to specify the bean you want.
I am implementing Custom Converter in Spring so my beans can convert from java.util.Date to java.time.LocalDateTime. I have implemented Converter already (by implementing Spring Converter interface)
Here is bean definition in #Configuration class
#Bean
ConversionService conversionService(){
DefaultConversionService service = new DefaultConversionService();
service.addConverter(new DateToLocalDateTimeConverter());
return service;
}
My question is : shall I pass my custom converter as Java Object or Spring Bean to service.addConverter?
In general what are the guidelines (criterias) whether to bean or not to bean in such scenarios?
Making an object a Spring Bean makes sense as you want that this object may benefit from Spring features (injections, transaction, aop, etc...).
In your case, it seems not required.
As conversionService is a Spring bean singleton that will be instantiated once, creating during its instantiation a plain java instance of DateToLocalDateTimeConverter seems fine : new DateToLocalDateTimeConverter().
Now, if later you want to inject the DateToLocalDateTimeConverter instance in other Spring beans, it would make sense to transform it to a Spring Bean.
For information Spring provides already this utility task in the Jsr310Converters class (included in the spring-data-commons dependency) :
import static java.time.LocalDateTime.*;
public abstract class Jsr310Converters {
...
public static enum DateToLocalDateTimeConverter implements Converter<Date, LocalDateTime> {
INSTANCE;
#Override
public LocalDateTime convert(Date source) {
return source == null ? null : ofInstant(source.toInstant(), ZoneId.systemDefault());
}
}
...
}
You could directly use it.
If you intend to inject this as a dependency of some kind into your application, and/or you intend to reuse it in multiple places, then it makes sense to register it as a bean. If you're not, then newing an instance up is acceptable.
Dependency injection and inversion of control are just that - how you inject dependencies into your app, and an acknowledgment that you no longer control how that's instantiated. Should you desire either of these, beans are suitable; if you don't, then new it up.
In you simple case, it does not seem to be necessary to add DateToLocalDateTimeConverter as a spring bean.
Reasons to add DateToLocalDateTimeConverter as a spring bean:
If it would make the implementation of conversionService() more readable (not the case in the question example)
You need the DateToLocalDateTimeConverter in other beans
The implementation of DateToLocalDateTimeConverter itself would need to have Spring beans injected, i.e. using #Autowired
I have following situation. There is POJO which has autowired implementation of an interface, using some spring magic as shown bellow. However this dependency doesn't get resolved if creation of channels is managed via spring bean. It only works if POJO factory creates channels. Example bellow.
#Controller
public class Test{
#RequestMapping(value = "/load", method = RequestMethod.GET)
public #ResponseBody String testConfiguration() {
// this is pojo and here it works, channels within have wired interface implementation
StaticFactory.getChannels(null);
// if i call same method within spring managed bean (#Service)
// then it doesnt work
System.out.println("channels created");
return "alive";
}
}
Created Channels are POJO but they have autowired interface implementation, which should be enabled with the following in constructor:
public DummyChannel() {
// enables dependency injection of spring managed beans into POJO
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
public class StaticFactory {
public static List<SmppChannel> getChannels(Map<ChannelMode, Integer> channelsDefinition) {
List<SmppChannel> dummyChannels = new ArrayList<>();
DummyChannel d = new DummyChannel();
System.out.println("here");
dummyChannels.add(new DummyChannel());
return dummyChannels;
}
}
Now, this thing works if i have non-spring managed Factory. Regardless if mentioned factory is static or not when it creates channels, they have properly wired interface implementation.
However, if i copy paste exactly same code form the factory into Spring managed Bean annotated with #Service, wired dependency is null in created channel.
Could somebody tell me what am i missing here, why things get injected when the factory of channels is not managed by the Spring ?
Edit Solution: // Okay, so the problem is in the fact that DummyChannels enable autowiring support in constructor while Spring beans are still not loaded. It is working if i do this within method that should access autowired service rather then the constructor of DummyChannel.
Have you enabled annotation-config and component-scan in your xml or java configuration? Is the class that you want to inject annotated with #Service or #Resource?
Are you building a Web Service with JAX-WS? If yes, then I think your class (the one doing the autowiring) must implement SpringBeanAutowiringSupport so that Spring's IoC container can handle the injection.
In my SpringMVC project I need a certain tactic to call a class which does parse a xml file which does own my RMI server ip & port & the url must be relative to servletContext url :
HttpServletRequest request;
request.getServletContext().getRealPath("/WEB-INF/LABLAB/RMI-Config.xml")
I want to load these classes when I start my application in tomcat not when I call a Controller Class because my application depend to my RMI so before anything else I have to parse my file & using the IP & PORT fields to start connecting to my RMI & then call the rmi method to do some stuffs later on ...
now
how I'm gonna do it ? please tell me how I can initialize an instance of HttpServletRequest & give an intial value when I'm not on the Controller classes as well .
Thank you
You are using Spring, then you can create a class and implement IntializingBean. If you want to get hold of ServletContext you can simple use #Autowired annotation in your initializing bean. For e.g.:
#Component
public class SomeBean implements InitializingBean {
#Autowired
private ServletContext context;
public void afterPropertiesSet() throws Exception {
String path = context.getRealPath("/WEB-INF/LABLAB/RMI-Config.xml");
//do something.
}
}
As per docs:
IntializingBean - Interface to be implemented by beans that need to
react once all their properties have been set by a BeanFactory.
Or take a look here how to do this using ServletContextListener.
You need to implement the ServletContextListener interface and refer to it from your web.xml:
<listener>
<listener-class>InitializingListener</listener-class>
</listener>
The interface has a contextInitialized(ServletContextEvent sce) method, in which you can call sce.getServletContext(), so you don't need a HttpServletRequest.
If this doesn't work out, because you also need to access some of your Spring beans from the initializing class, then forget about implementing the ServletContextListener interface, and do the following instead:
Instantiate your initialization class via Spring (make a bean of that type).
Make the class implement ServletContextAware. This will cause Spring to inject the ServletContext into your class.
Define an init method on that bean (use the init-method bean attribute, or define a #PostConstruct annotated method)
Make all your Controller beans depend on the initializing bean by using the depends-on bean attribute. As a result, the initialaizing bean will be created before any Controller bean.
Without the last step, it cannot be guaranteed that your controllers won't start processing requests before the initialization bean finishes its work. However, specifying the depends-on attribute on each and every controller bean is also problematic, especially that they are usually created by applying the #Controller annotation instead of xml configuration. A nice workaround is described in this post.
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;
}
}