I am working on a Spring application using Tomcat 6 and Spring 2.5. I'm trying to get my URL mapping correct. What I would like to have work is the following:
http://localhost:8080/idptest -> doesn't work
But instead, I have to reference the context name in my URL in order to resolve the mapping:
http://localhost:8080/<context_name>/idptest -> works
How can I avoid the requirement of referencing the context name in my URL without using a rewrite/proxy engine e.g. Apache?
Here is the servlet definition and mapping from my web.xml:
<servlet>
<servlet-name>idptest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conf/idptest.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>idptest</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Here's the outline of my controller (showing annotations for request mappings):
#Controller
#RequestMapping("/idptest")
public class MyController {
#RequestMapping(method=RequestMethod.GET)
public String setupForm(Model model){
MyObject someObject = new MyObject();
model.addAttribute("someObject", someObject);
return "myform";
}
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(#ModelAttribute("someObject") MyObject someObject) throws Exception {
// POST logic...
}
}
Thanks!
That's going to depend on your servlet container, for Tomcat - you pretty much have to deploy your webapp as the ROOT webapp, that is, under $CATALINA_HOME/webapps/ROOT/
More info here
Just rename your war file to ROOT.war, then the application runs in root context (i.e. with empty context name)
Related
I'm currently trying to understand how the Dispatcher Servlet works with the Rest Controller ,but Postman returns 404 on everything I tried thus far.
The rest controller
#RestController
#RequestMapping(value = "/applications")
public class ApplicationController {
private static final Logger logger = LoggerFactory.getLogger(ApplicationController.class);
#Autowired
#Qualifier("ApplDAO")
private ApplDAO applDAO;
#Autowired
ApplicationService objServices;
#RequestMapping(value = "for_user\\{username:\\d+}", method = RequestMethod.GET)
public Application getApp(#PathVariable("username") String username){
Application app = applDAO.getByUsername(username);
return app;
}
}
My web.xml
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring4-servlet.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
I tried using url-pattern /* but with no results.
This is the url I was trying to access http://localhost:8080/project/applications/for_user/username:acid
Is there something wrong with the URL I'm using or have I used the dispatcher wrong.
Here is the spring error
No mapping found for HTTP request with URI [/project/applications/for_user/username:acid
Answered by JB Nizet
Why do you use backslashes instead of slashes in your RequestMapping?
Why do you use the regex \d+ if you want to send username:acid (or
acid?) as user name. Just use value = "/for_user/{username}", and use
http://localhost:8080/project/applications/for_user/acid.
I would like to test that when an unknown url is requested and a 404 error is generated that my web app actually redirects to the right place.
I havent been able to get this working, I think because tomcat is handling the 404 errors so the forwardedUrl is always null for the tests. I know this works in reality because if I enter some rubbish into the url my app does redirect to my custom page.
My unit test looks like:
#Test
public void testUnknownUrl() throws Exception {
mockMvc.perform(get("/url_doesnt_exist"))
.andExpect(status().isNotFound())
.andExpect(forwardedUrl("/static/error/Sorry.html"));
}
My web.xml configuration is:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/static/error/Sorry.html</location>
</error-page>
The mapping for /static is defined in my spring config like:
<resources mapping="/static/**" location="/resources/" />
Ultimately I would like to mock a request to an unknown url and then check that the page being returned is /static/error/Sorry.html.
Am I doing something wrong or is this not the way to handle 404 etc in spring? The check of the forwarded url in the unit test is always null.
A slightly different question but related all the same is, at what point does the tomcat error handling get invoked over and above the spring controller advice handling?
I'm not sure about the configuration with the /static path in your web.xml, it shouldn't be like that depending on your dispatcher-servlet (default name) configuration; but as far as I can tell you are in the right path.
This is what I have for mine:
#WebAppConfiguration
#ActiveProfiles("development")
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = AppConfig.class)
public class ErrorControllerTest {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)/*.alwaysExpect(status().isOk())*/.build();
}
#Test
public void testError() throws Exception {
mockMvc.perform(get("/error").contentType(MediaType.TEXT_HTML))
.andExpect(status().isOk()) // See "alwaysExpect" above
.andExpect(view().name("error"))
.andExpect(forwardedUrl("/WEB-INF/views/error.jsp"));
}
#Test
public void testResourceNotFound() throws Exception {
mockMvc.perform(get("/resource-not-found").contentType(MediaType.TEXT_HTML))
.andExpect(status().isNotFound())
.andExpect(view().name("resource-not-found"))
.andExpect(forwardedUrl("/WEB-INF/views/resource-not-found.jsp"));
}
}
Sample project is here. I'm using JSPs but you can switch to .html just by changing the InternalResourceViewResolver configuration.
I am using spring 3 and after some reading around I have found out the dispatcher servlet just returns a response code without throwing an exception which I guess is why tomcat always handles this.
Removing the error page tags from web.xml results in a tomcat generic 404 page, so I think the answer to this is to upgrade to spring 4 where I can then pass an init param to the dispatcher servlet requesting it throw an error for a page not found.
I am happy to be corrected on this though as it may help my understanding.
I have a web application with Spring MVC.
web.xml
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/companies/*</url-pattern>
</servlet-mapping>
spring controller method:
class RealmInfoController{
#ResponseBody
#RequestMapping(value = {"/companies/{companyId}/realms/{realmName}"})
public RealmInfo realmInfo(#PathVariable long companyId, #PathVariable String realmName)
Handler match:
http://localhost:6122/context/companies/15877/realms/firstRealm
When the server gets this url, the spring servlet gets called. but it cannot match the controller method.
But if I change the request mapping to "/{companyId}/realms/{realmName}" then it matches the controller method. But it is not nice to define the url mapping without '/companies'. Can Spring be instructed in some way to look for match including the url pattern specified in the servlet?
Thanks.
if you want to use "companies" in request mapping you should map your dispatcher servlet to the root:
<url-pattern>/*</url-pattern>
So I am tring to get a JAX-RS application working on my WebSphere 8.5 instance. I created the following interface...
#Path("service")
public class RestService {
#GET
#Produces("text/plain")
public int getCount(){
return 1;
}
}
And This is my Application...
public class RESTConfig extends Application{
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new Hashset<?>();
classes.add(RestService.class);
return classes;
}
}
And then this is my web.xml...
<servlet>
<servlet-name>Rest Servlet</servlet-name>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>jaxrs.ws.rs.Application</param-name>
<param-value>com.company.rest.RESTConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
....
<servlet-mapping>
<servlet-name>Rest Servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Then I have an EAR configured with the WAR as a module. But when I start everything and try going to http://localhost:[port]/war/rest/app/service I see..
[TIME] 00000115 RequestProces I org.apache.wink.server.internal.RequestProcessor logException The following error occurred during the invocation of the handlers chain: WebApplicationException (404 - Not Found) with message 'null' while processing GET request sent to http://localhost:[port]/war/rest/service
Please Help!
WAS8.5 supports v2.4 and v3 servlets. The reason removing your web.xml contents (and using 3.0 code) worked for you is because you had a mistake in the param-name tag of your web.xml. v2.4 servlet works fine in WAS8.5 when you use the correct param-name.
This is incorrect.
<param-name>jaxrs.ws.rs.Application</param-name>
This is correct:
<param-name>javax.ws.rs.Application</param-name>
Details:
http://pic.dhe.ibm.com/infocenter/wasinfo/v8r5/topic/com.ibm.websphere.nd.multiplatform.doc/ae/twbs_jaxrs_configwebxml.html
The RestConfig class (that is defined as the JAX-RS Application) should override getClasses to return the resources:
#Path("app")
public class RESTConfig extends Application{
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new Hashset<?>();
classes.add(RestService.class);
return classes;
}
}
The issue appears to be related to 8.5 only supporting v3 servlets. this seems to fix the issue....
#Path("service")
public class RestService {
#GET
#Produces("text/plain")
public String getCount(){
//Text-Plain cannot be int apparently
return String.valueOf(1);
}
}
#ApplicationPath("rest")
public class RESTConfig extends Application{
//Override no longer needed.
}
This should now deploy fine...
Here was my source IBM
Also, You can try buy changing the below web.xml File
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Also, In Project Facets - Change Web Module version to 3.0
For More Reference Visit: How to deploy a JAX-RS application?
trying to use the spring extension of Restlet ,
have configured as per the example http://wiki.restlet.org/docs_2.1/13-restlet/28-restlet/70-restlet/196-restlet.html
In addition to that trying to capture the request parameters using the #RequestParam annotation but end up getting the parameter value as null.
Resource looks like,
class MyResource extends ServerResource implements IResource {
#Get
#RequestMapping(value="/id")
public void get(#RequestParam(value="name") String name) {
...
}
}
HTTP Request http://localhost:8080/messages/id?name=XXX
Web.xml looks like
<servlet>
<servlet-name>test-servlet</servlet-name>
<servlet-class>org.restlet.ext.spring.RestletFrameworkServlet</servlet-class>
</servlet>
<!-- Catch all requests -->
<servlet-mapping>
<servlet-name>test-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
In the end the name value is 'null'. I think the spring based annotations are not detected. I have no clue why this is happening?