I am trying to implement the SEO friendly URL something like /movies/{id}/actors/{actor_id}
to point out to the actor details of a particular movie. So I tried using the Advanced Wildcard mappings, but it isn't working when I have the REST API implemention in my project, but the same is working in a project where I have a simple struts2 application, which shows the JSP pages as results.
Here are the files of the simple struts2 application that works:
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" />
<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="basicstruts2" extends="struts-default">
<action name="index">
<result>/index.jsp</result>
</action>
<action name="/{uid}/hello/{userName}" class="com.struts.kavin.action.HelloWorldAction" method="execute">
<result name="success">/hello_world.jsp</result>
</action>
</package>
</struts>
HelloWorldAction.java
package com.struts.kavin.action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorldAction extends ActionSupport {
private String userName;
private String uid;
public String execute(){
return SUCCESS;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
}
hello_world.jsp
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World!</title>
</head>
<body>
<p>Username: <s:property value="userName" /></p>
<p>UID: <s:property value="uid" /></p>
</body>
</html>
index.jsp
: Displays the Hyperlinks to navigate to various pages.
OUTPUT:
URL:
http://localhost:8080/Sample/dsadsadsad/hello/kavin.action
Displays:
UID: dsadsadsad
Username: kavin
Here are the files of the struts2 REST API application that doesn't work:
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"/>
<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"/>
<constant name="struts.rest.content.restrictToGET" value="false"/>
<package name="movies" 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="movies" class="com.struts.movie.action.MoviesController">
<interceptor-ref name="jsonStack"/>
<result type="json">
<!-- declarations for mappings from Request JSON Body goes here-->
<param name="root">movie</param>
</result>
</action>
</package>
<package name="actors" namespace="/movies" 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="/{movie_id}/actors/" class="com.struts.movie.action.ActorsController">
<interceptor-ref name="jsonStack"/>
<!-- <param name="movie_id">{1}</param> -->
<result type="json">
<!-- declarations for mappings from Request JSON Body goes here-->
<param name="root">actor</param>
</result>
</action>
</package>
</struts>
ActorsController.java
package com.struts.movie.action;
public class ActorsController implements ModelDriven<Object> {
private Actor actor;
private String id;
private String movie_id;
private Object model;
@Override
public Object getModel() {
return model;
}
// RESETful method implementations
// Respective getters & setters are added
}
OUTPUT:
URL:
GET:
http://localhost:8080/movie_api/movies/1/actors.json
Error:
Struts Problem Report
Struts has detected an unhandled exception:
Messages: There is no Action mapped for namespace /movies and action name 1. Stacktraces There is no Action mapped for namespace /movies and action name 1. - [unknown location] com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:195) com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:76) org.apache.struts2.rest.RestActionProxyFactory.createActionProxy(RestActionProxyFactory.java:50) org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:564) org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:79) org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:141) org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084) org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360) org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181) org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726) org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405) org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206) org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114) org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) org.mortbay.jetty.Server.handle(Server.java:324) org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505) org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843) org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648) org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211) org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380) org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395) org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)
Can someone please help me to figure out what should be done to make it working? I also tried adding <constant name="struts.mapper.class" value="org.apache.struts2.dispatcher.mapper.Restful2ActionMapper" />
from Restful2ActionMapper.