2

I recently configured spring based maven project and I just want to replace all my XML (except POM) with java. I explore a lot of articles and docs regarding this, But, the reason I am here is, I have doubts which I think to be get resolved by you people.

As we know, every dynamic web project has single XML, which is called web.xml in absence of a framework.

Now If we integrate some framework say Struts, Spring, ORM etc. It is necessary to configure those also, so we write another XML config file.

I configured spring project so I have one deployment descriptor,application-context, and dispatcher servlet.

WEB.XML

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-ctx.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
     <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
    </welcome-file-list>
</web-app>

app-ctx.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:flow="http://www.springframework.org/schema/webflow-config"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:osgi="http://www.springframework.org/schema/osgi"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"

       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop 
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context  
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/webflow-config 
                           http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
                           http://www.springframework.org/schema/jee 
                           http://www.springframework.org/schema/jee/spring-jee.xsd
                           http://www.springframework.org/schema/jms 
                           http://www.springframework.org/schema/jms/spring-jms.xsd
                           http://www.springframework.org/schema/lang 
                           http://www.springframework.org/schema/lang/spring-lang.xsd
                           http://www.springframework.org/schema/osgi 
                           http://www.springframework.org/schema/osgi/spring-osgi.xsd
                           http://www.springframework.org/schema/tx 
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/util 
                           http://www.springframework.org/schema/util/spring-util.xsd">

    <context:component-scan base-package="com.mzk.mavenproject1"/>

<!--    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
          p:location="/WEB-INF/config_local.properties" />-->


</beans>

dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:flow="http://www.springframework.org/schema/webflow-config"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:osgi="http://www.springframework.org/schema/osgi"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"

       xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop 
                           http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context  
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc 
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/webflow-config 
                           http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
                           http://www.springframework.org/schema/jee 
                           http://www.springframework.org/schema/jee/spring-jee.xsd
                           http://www.springframework.org/schema/jms 
                           http://www.springframework.org/schema/jms/spring-jms.xsd
                           http://www.springframework.org/schema/lang 
                           http://www.springframework.org/schema/lang/spring-lang.xsd
                           http://www.springframework.org/schema/osgi 
                           http://www.springframework.org/schema/osgi/spring-osgi.xsd
                           http://www.springframework.org/schema/tx 
                           http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/util 
                           http://www.springframework.org/schema/util/spring-util.xsd">

    <mvc:resources mapping="/resources/**" location="/resources/"  cache-period="31556926" />
    <context:component-scan base-package="com.mzk.mavenproject1"/>

    <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>    

    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <!--Turn off working out content type based on URL file extension, should fall back to looking at the Accept headers-->
        <property name="favorPathExtension" value="false" />
    </bean>   

    <!-- 2. HandlerMapping : Used default handler mapping internally -->

    <!-- 3. ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>   

</beans>

CONFUSION:

I am confused to know that, exactly how java many classes we need to replace the same. We need three java classes or the two classes are enough?

because, a lot of articles demonstrated the two java classes, which replace web.xml and dispatcher-servlet.xml, so what about app-ctx.xml?

EDITS:

 @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addRedirectViewController("/", "home");
    }

OR

@Override
        public void addViewControllers(ViewControllerRegistry registry) {
           registry.addViewController("/").setViewName("home");
        }

CONTROLLER CLASS

@Controller
public class HomeController {

    @RequestMapping(value="/")
    public ModelAndView showhomePage() {
        ModelAndView mav = new ModelAndView("home");
        mav.addObject("successMsg", "Congratulations! Your Cortana is Properly congigured");
        return mav;
    }
}

I also do one trick, I created a global index.jsp, and specify only one scriptlet which will redirect the request to the Controller by using `sendRedirect().

LIKE

@Override
            public void addViewControllers(ViewControllerRegistry registry) {
               registry.addViewController("/").setViewName("forward:/index.jsp");
            }

No snippet work for me, every time I am facing 404, something I am missing i think?

4
  • You can also replace app-ctx.xml by Java class - look here: stackoverflow.com/questions/45002435/… Commented Oct 15, 2018 at 7:17
  • Hi @cgrim, I am expecting you, thanks for your coming, can you demonstrate the replacement, so it will be helpful for me, actually I am confused, because for three XML, how can we configured all three only in two classes. Commented Oct 15, 2018 at 7:20
  • the above article didn't help me much Commented Oct 15, 2018 at 9:16
  • As per above article, I still need to have dispatcher-servlet.xml, but my requrement is pure java based configuration Commented Oct 15, 2018 at 9:20

1 Answer 1

5

If I understand it well you want to get rid of all XML configurations.

Then at first you have to implement WebApplicationInitializer which replaces web.xml config file. You can do it like this:

public class CustomWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(RootConfig.class);

        ContextLoaderListener contextLoaderListener = new ContextLoaderListener(rootContext);
        servletContext.addListener(contextLoaderListener);

        AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
        webContext.register(MvcConfig.class);

        DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet);
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

Another step is to implement Spring configuration for root context which replaces app-ctx.xml:

@Configuration
@EnableWebMvc
@ComponentScan({"com.mzk.mavenproject1.service", "com.mzk.mavenproject1.model"})
public class RootConfig {
// ... provide another custom beans when needed
}

And the last step is to implement configuration for MVC which replaces dispatcher-servlet.xml:

@Configuration
@EnableWebMvc
@ComponentScan("com.mzk.mavenproject1.controller")
public class MvcConfig extends WebMvcConfigurerAdapter {
    @Bean
    ViewResolver internalViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }

// ... provide another custom beans when needed
}

Regarding of your question about classes count - yes, you can do it only by two classes: CustomWebAppInitializer and MvcConfig and have only one context for everything.

CustomWebAppInitializer.onStartup() method body will then look like:

    AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
    webContext.register(MvcConfig.class);

    ContextLoaderListener contextLoaderListener = new ContextLoaderListener(webContext);
    servletContext.addListener(contextLoaderListener);

    DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
    ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet);
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("/");
Sign up to request clarification or add additional context in comments.

9 Comments

Tons of thanks @cgrim, you just nailed it, now finally I got a clear clarity
But now i am concerning about the attributes inside @ComponentScan, because, the number of packages will increase in future in that case i need to hardcode the same, I wish, there should be way to declare packages in properties file and refer that property file inside componentscan, so we do not need to modify the MvcConfig.java again and again isn't?
You can partly return to XML approach and have DispatcherServlet configuration in XML - then no need to recompile ;-) Another option is to have package mvc for MvcConfig and core for RootConfig and ten separate it by your need on sub-packages for example. Or you can go from the opposite side and scan everything and prepare filters for packages you dont want to scan - see stackoverflow.com/questions/16238089/…
one more thing, is it mandatory to specify the full path in @ComponentScan, what If I provided only @ComponentScan("com.mzk.mavenproject1"),may be it stuck or may be not?
I'm not sure what do you mean by full path. But you can have @ComponentScan("com.mzk.mavenproject1") whether there are other sub-packages or not.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.