MrPlow MrPlow - 1 month ago 27
AngularJS Question

Which spring view resolver plays nice with angularjs?

I'm writing a webapp using angularjs and spring mvc as a REST service provider and as a partial view provider(I'm also using angular-ui-router so that I can have multiple nested partials). I currently don't have any use for template languages since I plan on doing everything in angular, however every single view resolver I've tried has some type of template language which clashes with angular and either crashes the application and/or fills my logs with errors.

First I tried using InternalResourceViewResolver but no luck as it seems that it only expects .jsp files and won't show anything else.

Then I tried using Thymeleaf. Thymeleaf follows the XML standard which forced me to rewrite most of my html to follow the xml requirements, and after I'd done that it died upon encountering a

&&
inside an ng-show directive. So no luck with that either.

Then I tried Velocity. I've had most luck with velocity so far. It serves up html files nicely, doesn't stop upon encountering parse errors and allows me to serve up partial views the same way InternalResourceViewResolver does. However upon encountering angular variables prefixed by
$
Velocity tries to parse them as VTL variables and fills my logs with messages like

velocity - Null reference [template 'clients/createOrEdit.html', line 1, column 65] : $invalid cannot be resolved.


Everything keeps working as it should but I'm not the one to just leave errors be, and I've found no way of disabling VTL.

That's my current experience with view resolvers.

I've also had an idea to treat .html files as static resources(which they kinda are before angular does it's magic) using
mvc:resources
but without any view resolver my application failed to start even if I set the main layout.html to be the welcome-file in web.xml

My question is. What should I use as a view resolver so that it plays nice with angularjs, and if I should even use view resolvers?

EDIT: I'm trying to use the
ContentNegotiatingViewResolver
and I get:

DEBUG ContentNegotiatingViewResolver - Requested media types are [text/html] based on Accept header types and producible media types [*/*])
DEBUG ContentNegotiatingViewResolver - No acceptable view found; returning null
DEBUG DispatcherServlet - Could not complete request
javax.servlet.ServletException: Could not resolve view with name 'layout.html' in servlet with name 'springDispatcherServlet'


webapp-config.xml (contextconfig in dispatcher servlet)

<mvc:annotation-driven />

<!-- Resources -->
<mvc:resources location="/libs/" mapping="/libs/**" />
<mvc:resources location="/css/" mapping="/css/**" />
<mvc:resources location="/js/" mapping="/js/**" />
<!-- Angular application data -->
<mvc:resources location="/WEB-INF/appjs/" mapping="/appjs/**" />
<!-- View locations -->
<mvc:resources location="/WEB-INF/html/" mapping="/**"/>

<!-- Controllers -->
<context:component-scan base-package="com.mrplow.controller" />

<!-- Views -->
<util:map id="contentMediaTypes">
<entry key="json" value="application/json" />
<entry key="html" value="text/html" />
</util:map>

<!-- <util:list id="defaultViews"> -->
<!-- <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> -->
<!-- </util:list> -->

<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
p:order="1"
p:ignoreAcceptHeader="false"
p:defaultContentType="text/html"
p:mediaTypes-ref="contentMediaTypes" />


LayoutController.java

@Controller
@RequestMapping("/")
public class LayoutController {

@RequestMapping
public String getIndexPage() {
return "layout";
}
}

Answer

In order to use static resource(html,css,img,js) in spring, use a directory structure that looks like the following:

src/
   package/
   LayoutController.java
WebContent/
   WEB-INF/
    static/
      html/
       layout.html
      images/
       image.jpg
      css/
       test.css
      js/
       main.js
     web.xml
    springmvc-servlet.xml



@Controller 
public class LayoutController {

 @RequestMapping("/staticPage") 
public String getIndexPage() { 
return "layout.htm"; 

} }



  <!-- in spring config file -->
 <mvc:resources mapping="/static/**" location="/WEB-INF/static/" />

layout.html

<h1>Page with image</h1>
<img src="/static/img/image.jpg"/>

Note you have to mention /static/img/image.jpg not just /image.jpg ..Same applies for css and js.

OR

You can also use content negotiating view resolver as shown below:

 <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
          <property name="order" value="1" />
          <property name="mediaTypes">
            <map>
               <entry key="json" value="application/json" />
               <entry key="xml" value="application/xml" />
               <entry key="rss" value="application/rss+xml" />
                <entry key="html" value="text/html"/>
            </map>
          </property>

          <property name="defaultViews">
            <list>
              <!-- JSON View -->
              <bean
                class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
              </bean>

Spring MVC will use “ContentNegotiatingViewResolver” (order=1) to return a suitable view (based on file extension declared in “mediaTypes” property), if not match, then use “InternalResourceViewResolver” (order=2) to return a default JSP page.

<bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="order" value="2" />
        <property name="prefix">
            <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
            <value>.jsp</value>
        </property>
    </bean>

Now from your jsp you can redirect to your static html page as well

   @Controller
    public class LayoutController {

        @RequestMapping("/index")
        public String getIndexPage() {
            return "index";
        }

    }

index.jsp

<form:form method="GET" action="/static/html/layout.html">

Now try to access your service through http://yourapp.com//index show the form action mentioned above.It will show the layout.html

click on a button or submit in jsp page to invoke the layout.html page