0

Here my files.

struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
    <constant name="struts.devMode" value="true"/>

    <!-- restrictToGET to false makes the response to be of JSON type when request if of type POST, PUT, DELETE-->
    <constant name="struts.rest.content.restrictToGET" value="false"/>

    <constant name="struts.convention.action.suffix" value="Controller"/>
    <constant name="struts.convention.action.mapAllMatches" value="true"/>
    <constant name="struts.convention.default.parent.package" value="rest-default"/>
    <constant name="struts.convention.package.locators" value="action"/>

    <constant name="struts.enable.SlashesInActionNames" value="true"/>
    <constant name="struts.mapper.alwaysSelectFullNamespace" value="false"/>
    <constant name="struts.patternMatcher" value="regex"/>
    <constant name="struts.matcher.appendNamedParameters" value="true"/>

    <package name="action" namespace="/" extends="rest-default,json-default">

        <interceptors>
            <interceptor name="json" class="org.apache.struts2.json.JSONInterceptor"/>
            <interceptor-stack name="jsonStack">
                <interceptor-ref name="json"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>
        </interceptors>

        <action name="hello" class="com.wildcard.action.HelloController">
            <interceptor-ref name="jsonStack"/>

            <result type="json">
                <param name="root">uid</param>
            </result>
        </action>

        <action name="hello/*" class="com.wildcard.action.HelloController">
            <interceptor-ref name="jsonStack"/>

            <param name="id">{1}</param>

            <result type="json">
                <param name="root">uid</param>
            </result>
        </action>

    </package>

</struts>

HelloController.java

package com.wildcard.action;

import com.opensymphony.xwork2.ModelDriven;
import com.wildcard.model.Hello;
import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;

public class HelloController implements ModelDriven<Object> {

    private Hello hello = new Hello();
    private String id;
    private String uid;
    private Object model = new Object();

    public HttpHeaders index() {
        hello.setName("index");
        System.out.println("index() : " + hello);
        System.out.println("index() uid: " + uid);
        return new DefaultHttpHeaders("index");
    }

    public HttpHeaders show() {
        hello.setName("show");
        System.out.println("show() : " + hello);
        System.out.println("show() id: " + id);
        System.out.println("show() uid: " + uid);
        return new DefaultHttpHeaders("show");
    }

    public HttpHeaders create() {
        //hello.setName("create");
        System.out.println("create() : " + hello);
        System.out.println("create() id: " + id);
        System.out.println("create() uid: " + uid);
        return new DefaultHttpHeaders("create");
    }

    public HttpHeaders update() {
        hello.setName("update");
        System.out.println("update() : " + hello);
        System.out.println("update() id: " + id);
        System.out.println("update() uid: " + uid);
        return new DefaultHttpHeaders("update");
    }

    public HttpHeaders destroy() {
        hello.setName("destroy");
        System.out.println("destroy() : " + hello);
        System.out.println("destroy() id: " + id);
        System.out.println("destroy() uid: " + uid);
        return new DefaultHttpHeaders("destroy");
    }


    @Override
    public Object getModel() {
        model = hello;
        return model;
    }

    public void setModel(Object model) {
        this.model = model;
    }

    public Hello getHello() {
        return hello;
    }

    public void setHello(Hello hello) {
        this.hello = hello;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }
}

Hello.java

package com.wildcard.model;

public class Hello {
    private String name;

    public Hello() {
    }

    public Hello(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "name='" + name + '\'' +
                '}';
    }
}

When I send the requests GET [/hello.json,/hello/{id}.json], POST [/hello.json], PUT [/hello/{id}.json], DELETE [/hello/{id}.json], without JSON Body, it's working fine. When I add JSON Body to the above requests, only the following are working, GET, POST [/hello.json]. And when I add the {id} to the URL path, I am getting the following error.

> HTTP ERROR: 500 Unable to show problem report:
> 
> freemarker.core.InvalidReferenceException: The following has evaluated
> to null or missing:
> 
> ==> rootloc.URI  [in template "org/apache/struts2/dispatcher/error.ftl" at line 84, column  15]
> 
> ---- Tip: It's the step after the last dot that caused this error, not those before it.
> ---- Tip: If the failing expression is known to legally refer to something that's sometimes  null or missing, either specify a default
> value like myOptionalVar!myDefault, or use <#if 
> myOptionalVar??>when-present<#else>when-missing</#if>. (These only
> cover the last step of  the expression; to cover the whole expression,
> use parenthesis:  (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
> ----
> 
> ---- FTL stack trace ("~" means nesting-related):
> - Failed at: ${rootloc.URI}  [in template "org/apache/struts2/dispatcher/error.ftl" at line 84, column 13]
> ----
> 
> Class: freemarker.core.InvalidReferenceException File:
> InvalidReferenceException.java Method: getInstance Line: 134 -
> freemarker/core/InvalidReferenceException.java:134:-1
> RequestURI=/wildcard_sample/hello/2.json
> 
> Powered by Jetty://

Java stack trace (for programmers):

freemarker.core.InvalidReferenceException: [... Exception message was already printed; see it above ...]
        at freemarker.core.InvalidReferenceException.getInstance(InvalidReferenceException.java:134)
        at freemarker.core.EvalUtil.coerceModelToTextualCommon(EvalUtil.java:481)
        at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:401)
        at freemarker.core.EvalUtil.coerceModelToStringOrMarkup(EvalUtil.java:370)
        at freemarker.core.DollarVariable.calculateInterpolatedStringOrMarkup(DollarVariable.java:100)
        at freemarker.core.DollarVariable.accept(DollarVariable.java:63)
        at freemarker.core.Environment.visit(Environment.java:334)
        at freemarker.core.Environment.visit(Environment.java:340)
        at freemarker.core.Environment.visit(Environment.java:340)
        at freemarker.core.Environment.process(Environment.java:313)
        at freemarker.template.Template.process(Template.java:383)
        at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleErrorInDevMode(DefaultDispatcherErrorHandler.java:118)
        at org.apache.struts2.dispatcher.DefaultDispatcherErrorHandler.handleError(DefaultDispatcherErrorHandler.java:76)
        at org.apache.struts2.dispatcher.Dispatcher.sendError(Dispatcher.java:923)
        at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:589)
        at org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:79)
        at org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:141)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
        at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
        at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
        at org.mortbay.jetty.Server.handle(Server.java:324)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
        at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
        at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
        at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

Error screenshot while sending a PUT Request along with JSON Body

Roman C
  • 49,761
  • 33
  • 66
  • 176
Kavin Raju S
  • 1,214
  • 2
  • 17
  • 25

1 Answers1

0

The rest plugin works well along with convention plugin, where configuration is added automatically by convention. To let the convention plugin create the configuration for actions in your application use the following settings

struts.xml:

<constant name="struts.convention.action.suffix" value="Controller"/>
    <constant name="struts.convention.action.mapAllMatches" value="true"/>
    <constant name="struts.convention.default.parent.package" value="rest-default"/>
    <constant name="struts.convention.package.locators" value="action"/>

web.xml: The parameter to struts2 filter

<init-param>
            <param-name>actionPackages</param-name>
            <param-value>com.wildcard.action</param-value>
 </init-param>
Roman C
  • 49,761
  • 33
  • 66
  • 176