Superclass has no null constructors but no arguments were given
Asked Answered
M

3

33

Im using Spring Social in my application:

<spring.framework.version>3.2.0.RELEASE</spring.framework.version>
<hibernate.version>4.1.9.Final</hibernate.version>
<commons-dbcp.version>1.4</commons-dbcp.version>
<org.springframework.social-version>1.1.0.BUILD-SNAPSHOT</org.springframework.social-version>
<org.springframework.social.facebook-version>1.1.0.BUILD-SNAPSHOT</org.springframework.social.facebook-version>
<org.springframework-version>3.2.1.RELEASE</org.springframework-version>
<org.springframework.security.crypto-version>3.1.3.RELEASE</org.springframework.security.crypto-version>

When I apply

private final Facebook facebook;

@Inject
public SearchController(Facebook facebook) {
    this.facebook = facebook;
}

To my HomeController:

@Controller
public class HomeController {


    private final Facebook facebook;

    @Inject
    public HomeController(Facebook facebook) {
        this.facebook = facebook;
    }

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Model model) {
        return "home";
    }

}

The injection works like intented and I can get information from facebook. However, when I apply it to one of my other Cotrollers like this one

@Controller
@Transactional
@RequestMapping(value = "/search")
public class SearchController {

    private static final Logger logger = LoggerFactory.getLogger(SearchController.class);

    private final Facebook facebook;

    @Inject
    public SearchController(Facebook facebook) {
        this.facebook = facebook;
    }

    @PersistenceContext
    private EntityManager entityManager;

    ...

I getting this error:

mar 05, 2013 12:46:36 EM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/project] threw exception [Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'searchController' defined in file [C:\Users\Nilsi\Downloads\springsource\vfabric-tc-server-developer-2.7.2.RELEASE\base-instance\wtpwebapps\course_info\WEB-INF\classes\com\courseinfo\project\controller\SearchController.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.courseinfo.project.controller.SearchController]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given] with root cause
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
    at org.springframework.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285)
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:111)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:412)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1492)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:524)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:461)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1117)
    at org.springframework.web.method.HandlerMethod.createWithResolvedBean(HandlerMethod.java:202)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:233)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:55)
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:297)
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1091)
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1076)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:896)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

My guess is that I can't inject facebook to a Controller with annotation @Transactional?

Marden answered 5/3, 2013 at 12:3 Comment(2)
Is it working if you use property based injection?Capo
Wow, it worked! if you put it as an answer I will mark it as correct. I simply deleted the constructor and changed to this: @Inject private Facebook facebook; Tested that before but couldn't get it to work cause the variable originally was final. (Was final in Springs example code i got it from).Marden
C
69

CGlib has one important restriction: the target class must provide a default constructor.

If you use property-based injection instead of constructor-based injection, the problem will go away.

Capo answered 5/3, 2013 at 17:52 Comment(9)
Expanding on this answer: This would have worked fine via constructor-injection (which is preferred) had you not added @Transactional to the controller. Once you added @Transactional, AOP kicks in and a proxy must be created. CGLib needs a default constructor. Another solution is to configure Spring transactions to use AspectJ instead of proxies. This requires a bit more setup, but would allow transactions on a class with no default constructor.Aboveground
This is a very good comment! I think it should be added to the answer.Bergamo
Prior to Spring 4, CGLIB-based proxy classes require a default constructor. And this is not the limitation of CGLIB library, but Spring itself. Fortunately, as of Spring 4 this is no longer an issue. CGLIB-based proxy classes no longer require a default constructor. See this article: blog.codeleak.pl/2014/07/…Arcograph
I found a way to make it work with constructor-injection and @Transactional. Create an interface that SearchController implements, and change the contructor of HomeController to take an instance of this interface instead.Offing
Basically make HomeController depend on an interface, not an implementation.Offing
This interface hint really is worth a mint, should be an answer!Calistacalisthenics
The comment from @Offing is useful in that allows you to use both constructor injection and @Transactional at the same time. Just make the class with @Transactional to implement an interface.Fricassee
I don't really remember making this comment, and I find it a bit confusing. Why did I say that HomeController should take a SearchController as an argument? Is anyone able to decode what I meant? :)Offing
@CraigWalls - How do you suggest injecting a constructor using cglib?Antiparticle
L
1

I just created an empty default constructor to deal with this.

Lavettelavigne answered 2/3, 2016 at 16:5 Comment(0)
U
-2

If you are using Lombok in your code, then you can just add the following annotation to get rid of this error:

@NoArgsConstructor
public class SearchController {
Urticaria answered 15/8, 2018 at 13:18 Comment(5)
Seriously dude? Do you really believe that writing an empty constructor is a big deal that requires an additional library and IDE plugin?Bain
@Bain If its already included in your project, why wouldn't you use it? I clearly stated "if you are using Lombok". It can do a lot more than just add an empty constructor by the way.Urticaria
Thank you for your opinion. I'm sorry you feel that way.Urticaria
The @NoArgsConstructor is one of the reasons why I hate Lombok today. It provides a negligible code length reduction while preventing me from using my IDE's "find usages" option. Just write the constructor and document why it exists (see that you failed to document why the annotation is needed).Stoddard
@Stoddard That issue is with your IDE, using "open call hierarchy" in Eclipse reports all usages correctly. There might be a setting you can change to get it to work in whatever IDE you are using.Urticaria

© 2022 - 2024 — McMap. All rights reserved.