简体   繁体   中英

Is Servlet 3.0 XML-less configuration possible with tapestry-spring?

I started writing an app using Spring MVC, then decided to go with Tapestry instead. I want to keep the XML-less configuration approach that I was using originally. I first tried this:

public class ServletConfig implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // Spring //
        AnnotationConfigWebApplicationContext rootContext = new
        AnnotationConfigWebApplicationContext();
        rootContext.register(PersistenceContext.class, ApplicationContext.class);
        servletContext.addListener(new ContextLoaderListener(rootContext));

        // Tapestry //
        servletContext.setInitParameter("tapestry.app-package", "...");
        FilterRegistration.Dynamic filter = servletContext.addFilter("app", TapestrySpringFilter.class);
        filter.addMappingForUrlPatterns(null, false, "/*");
    }
}

The problem here is that tapestry creates another ContextLoaderListener, using the empty constructor. Instead of taking in a WebApplicationContext, it looks at the contextClass and contextConfigLocation init parameters. So I tried this:

@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    // Spring //
    servletContext.setInitParameter("contextClass",
            "org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
    servletContext
            .setInitParameter(
                    "contextConfigLocation",
                    "...config.PersistenceContext ...config.ApplicationContext");

    // Tapestry //
    servletContext.setInitParameter("tapestry.app-package", "...");
    FilterRegistration.Dynamic filter = servletContext.addFilter("app", TapestrySpringFilter.class);
    filter.addMappingForUrlPatterns(null, false, "/*");
}

Which caused this:

 java.lang.IllegalArgumentException: When using the Tapestry/Spring integration library, you must specifiy a context class that extends from org.apache.tapestry5.spring.TapestryApplicationContext. Class org.springframework.web.context.support.AnnotationConfigWebApplicationContext does not. Update the 'contextClass' servlet context init parameter.

TapestryApplicationContext inherits from org.springframework.web.context.support.XmlWebApplicationContext. So my question(s): is there a way to make annotation-based configuration work with this approach? If not, is there another approach that will allow me to use it? Or is there no way to avoid the XML?

I tried reverting to the first version of ServletConfig I put up on here, but I added

servletContext.setInitParameter("tapestry.use-external-spring-context", "true");

I'm no longer getting the error message, but the page isn't loading either. When I try to load /app/, instead of loading the index page I get this:

<html>
    <head>
        <title>Error</title>
    </head>
    <body>/app/index.jsp</body>
</html>

I'm not sure what's causing this, I can't find anything in the logs to indicate any problems. I'm thinking that there's some sort of issue with the dispatcher service. Has anybody seen this type of error before? I'm not sure if this is unrelated to my original problem or if this is a symptom of my approach not being valid. If somebody can tell me that this is a separate issue I'll take the appropriate action.

The out-of-the-box spring integration expects an XML file.

It wouldn't be too hard to extend SpringModuleDef and override locateApplicationContext to return an AnnotationConfigApplicationContext

You would then write your own TapestrySpringFilter implementation which loads your new SpringModuleDef subclass.

--edit---

I was wrong, the tapestry spring integration uses WebApplicationContextUtils.getWebApplicationContext(servletContext) to lookup the ApplicationContext. So you could initialize the servlet context with an ApplicationContext prior to loading the TapestryStringFilter and it should just work.

eg

ApplicationContext myContext = createAnnotationBasedAppContext();
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, myContext);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM