Question:

I have a stripped down test project which contains a Servlet version 3.0, declared with annotations like so:

    @WebServlet("/test")
public class TestServlet extends HttpServlet { private static final long serialVersionUID = -3010230838088656008L; @Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException{
response.getWriter().write("Test");
response.getWriter().flush();
response.getWriter().close();
}
}

I also have a web.xml file like so:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"> <servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>g1.TestServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/testWebXml</url-pattern>
</servlet-mapping> </web-app>

I've tried to make a JUnit test using Embedded Tomcat 7. When I start the Embedded Tomcat I can only access the servlet via the url-pattern declared in web.xml (/testWebXml). If I try to access it via the url-pattern declared via annotation (/test) it sais 404 page not found.

Here's the code for my test:

    String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080); tomcat.addWebapp("/jerseyTest", new File(webappDirLocation).getAbsolutePath()); tomcat.start();
tomcat.getServer().await();

Just to make sure I've set up my project correctly, I've also installed an actual Tomcat 7 and deployed the war. This time, both web.xml declared url and annotation url for my servlet work ok.

So my question is: does anyone know how to make Embedded Tomcat 7 take into account my Servlet 3.0 annotations?

I should also state that it's a Maven project, and the pom.xml contains the following dependencies:

    <dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>7.0.29</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>7.0.29</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>7.0.29</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>

== UPDATE ==

Here's an issue that seems similar to this (except the Servlet 3.0 annotation that is not working is on Listener, not Servlet), which has a suggested fix:

https://issues.apache.org/bugzilla/show_bug.cgi?id=53903

I've tried it and it didn't work:

Changed the Embedded Tomcat start code to:

String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat(); tomcat.enableNaming();
tomcat.setPort(8080); Context ctx = tomcat.addWebapp(tomcat.getHost(), "/embeddedTomcat", new File(webappDirLocation).getAbsolutePath());
((StandardJarScanner) ctx.getJarScanner()).setScanAllDirectories(true); tomcat.start(); tomcat.getServer().await();

Other things I've tried, also without success:

  • specifically setting metadata-complete="false" in web.xml "web-app" tag

  • updating the Maven dependencies to version 7.0.30

  • debugging the org.apache.catalina.startup.ContextConfig class. There's code there that checks for @WebServlet annotations, it's just that it never gets executed (line 2115). This may be a good way to get to the root of the issue, but the class is pretty big, and I don't have time to do this now. Maybe if someone would be willing to look how this class works, and under which conditions (config params) does it get to correctly check your project's classes for that annotation, it might get to a valid answer.

Answer:

Well I finally solved it by looking in the Tomcat7 sources, namely in the unit tests that deal with EmbeddedTomcat and servlet 3.0 annotations.

Basically, you must start your Embedded Tomcat 7 like this to make it aware of your annotated classes:

String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080); StandardContext ctx = (StandardContext) tomcat.addWebapp("/embeddedTomcat",
new File(webappDirLocation).getAbsolutePath()); //declare an alternate location for your "WEB-INF/classes" dir:
File additionWebInfClasses = new File("target/classes");
VirtualDirContext resources = new VirtualDirContext();
resources.setExtraResourcePaths("/WEB-INF/classes=" + additionWebInfClasses);
ctx.setResources(resources); tomcat.start();
tomcat.getServer().await();

For the sake of clarity I should mention that this works for a standard Maven project where your "web resources" (such as static and dynamic pages, WEB-INF directory etc) are found in:

[your project's root dir]/src/main/webapp

and your classes get compiled into

[your project's root dir]/target/classes

(such that you'd have [your project's root dir]/target/classes/[some package]/SomeCompiledServletClass.class)

For other directories layouts, these locations need to be changed accordingly.

==== UPDATE: Embedded Tomcat 8 ====

Thanks to @kwak for noticing this.

The APIs have changed a bit, here how the above example changes when using Embedded Tomcat 8:

String webappDirLocation = "src/main/webapp/";
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080); StandardContext ctx = (StandardContext) tomcat.addWebapp("/embeddedTomcat",
new File(webappDirLocation).getAbsolutePath()); //declare an alternate location for your "WEB-INF/classes" dir:
File additionWebInfClasses = new File("target/classes");
WebResourceRoot resources = new StandardRoot(ctx);
resources.addPreResources(new DirResourceSet(resources, "/WEB-INF/classes", additionWebInfClasses.getAbsolutePath(), "/"));
ctx.setResources(resources); tomcat.start();
tomcat.getServer().await();

原文地址:http://stackoverflow.com/questions/11669507/embedded-tomcat-7-servlet-3-0-annotations-not-working/12688842#12688842

Embedded tomcat 7 servlet 3.0 annotations not working--转的更多相关文章

  1. 关于 tomcat nio connector, servlet 3.0 async, spring mvc async 的关系

    tomcat 的 org.apache.coyote.http11.Http11NioProtocol Connector 是一个使用 Java NIO 实现的异步 accept 请求的 connec ...

  2. Spring boot Unable to start embedded Tomcat报错 java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()

    Spring boot Unable to start embedded Tomcat 报错 java.lang.NoSuchMethodError: javax.servlet.ServletCon ...

  3. Spring Cloud Gateway报错:Unable to start embedded Tomcat

    最近搭建Spring Cloud Gateway时启动项目出现如下报错信息: Error starting ApplicationContext. To display the conditions ...

  4. gradle中使用嵌入式(embedded) tomcat, debug 启动

    在gradle项目中使用embedded tomcat. 最开始部署项目需要手动将web项目打成war包,然后手动上传到tomcat的webapp下,然后启动tomcat来部署项目.这种手动工作通常还 ...

  5. embedded tomcat context.xml

    在网络下载相关的embedded tomcat jar.也可直接在maven中检索. 在main方法中,输入以下代码: //新建tomcat实例 Tomcat tomcat = new Tomcat( ...

  6. 【tomcat启动失败问题】Unable to start embedded Tomcat

    启动spring boot 项目后抛出如下异常: org.springframework.context.ApplicationContextException: Unable to start em ...

  7. embedded tomcat运行java web,Unable to compile class for JSP

    环境 eclipse:4.5.2 jre:1.8 java project compiler:1.8 embedded tomcat:7.0.32 可以正常启动,但是访问时,会报错. HTTP Sta ...

  8. SpringBoot:springboot整合eureka报错 Unable to start embedded Tomcat

    报错信息: org.springframework.context.ApplicationContextException: Unable to start web server; nested ex ...

  9. [转]Servlet 3.0 新特性详解

    原文地址:http://blog.csdn.net/xiazdong/article/details/7208316 Servlet 3.0 新特性概览 1.Servlet.Filter.Listen ...

随机推荐

  1. JS中区分参数方法

    实现功能:在使用cocosjs制作游戏过程中,很多东西都可以重复使用,例如菜单栏等等.今天尝试写了一个自定义的Js文件用作菜单方便以后使用. 将菜单按钮,以及触发事件作为参数生成一个层 直接在游戏中使 ...

  2. thinkphp 邮件发送

    最近项目上要求,要做个邮件发送的功能,因为用到的框架是ThinkPHP,于是就自己整理一下. 引入class.phpmailer.php,大家可以去这个链接去下载: http://pan.baidu. ...

  3. 【转】lua random()

    先来看看这两段代码: ① math.randomseed(os.time())for i=1,10 do n = math.random(10) print(n) 运行结果是: 63210754341 ...

  4. php小知识点

    1.字符串可以里面的字符可以像数组一样访问,比如$s = "123";$s[1]就等于2,如果字符串为中文则会乱码,需要使用mb_substr进行截取: 2.php中的单引号(' ...

  5. iPhone 6 图像渲染揭秘(转)

    几天前,Apple发布了iPhone 6 Plus. 新的iPhone大幅改变了图像在屏幕上渲染的方式.我们做了一个图表进行详细分析. 分析. 转自:转送

  6. nginx配置无效的问题

    今天修改nginx的一个配置文件,却怎么都没效果,发现是启动nginx指定的配置文件不一样. #ps aux|grep nginx root     17672  0.0  0.0  45856  2 ...

  7. linux的du和df命令

    今天也有同学问我Linux下查看目录大小的命令,现在也将前阵子学习到du/df两个命令总结一下吧.前阵子测试工作中有遇到过由于磁盘空间满导致程序无法执行到情况,所以使用了df和du两个命令. du查看 ...

  8. PHP mongoDB 操作

    <?php /** * PHP操作MongoDB学习笔记 */ //************************* //** 连接MongoDB数据库 **// //************ ...

  9. 【行为型】Iterator模式

    迭代器模式提供一种方法顺序访问聚合对象中的各个元素,而又不需要暴露该聚合对象的内部表示.对于该模式,估计几乎所有的人都使用过,在此直接给出类结构图参考如下: 如前所述,迭代器模式的思想主要是:一能提供 ...

  10. typedef , static和 extern

    typedef 1.作用:给已经存在的类型起一个新的名称 2.使用场合: 1> 基本数据类型 2> 指针 3> 结构体 4> 枚举 5> 指向函数的指针 #include ...