Lỗi Tomcat: Servlet mapping specifies an unknown servlet name

Tiếp tục với loạt bài “Tổng hợp lỗi Server Tomcat thường gặp và cách khắc phục“, hôm nay mình sẽ phân tích và hướng dẫn khắc phục một lỗi không hề mới “Servlet mapping specifies an unknown servlet name

Đây là cái lỗi quái gì thế?

Mình cũng chả biết gọi nó với cái tên là gì nhưng khi gặp lỗi, server Tomcat sẽ lập tức stop đồng thời mọc lên hộp thoại huyền thoại.

Lỗi Tomcat: Servlet mapping specifies an unknown servlet name
Hộp thoại thông báo lỗi huyền thoại

Chắc hẳn các bạn không xa lạ gì với hộp thoại này nhỉ 😀

Đối với những bạn mới vào nghề có vẻ còn hơi lúng túng, cuống cuồng hơn cả lần đầu làm chuyện ấy (lần đầu code java web ý nhá). Nhưng cứ yên tâm, trấn an con tim vài giây và bắt đầu click chuột vào tab console xem thử có gì không nhé (tab console là gì? Chưa biết thì comment bên dưới mình hướng dẫn nhé :v ).

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/HowToFixError]]
	at java.util.concurrent.FutureTask.report(Unknown Source)
	at java.util.concurrent.FutureTask.get(Unknown Source)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1122)
	at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:819)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1574)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1564)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/HowToFixError]]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
	... 6 more
Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name ADuController
	at org.apache.catalina.core.StandardContext.addServletMapping(StandardContext.java:3321)
	at org.apache.catalina.core.StandardContext.addServletMapping(StandardContext.java:3300)
	at org.apache.catalina.deploy.WebXml.configureContext(WebXml.java:1438)
	at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1357)
	at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:889)
	at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:386)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
	at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5419)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	... 6 more

May 23, 2017 7:17:59 PM org.apache.catalina.core.ContainerBase startInternal
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
	at java.util.concurrent.FutureTask.report(Unknown Source)
	at java.util.concurrent.FutureTask.get(Unknown Source)
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1122)
	at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:300)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:739)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:689)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:321)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1574)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1564)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1130)
	at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:819)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	... 6 more

May 23, 2017 7:17:59 PM org.apache.catalina.startup.Catalina start
SEVERE: The required Server component failed to start so Tomcat is unable to start.
org.apache.catalina.LifecycleException: Failed to start component [StandardServer[8005]]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:689)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:321)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:455)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardService[Catalina]]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
	at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:739)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	... 7 more
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina]]
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
	at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	... 9 more
Caused by: org.apache.catalina.LifecycleException: A child container failed during start
	at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1130)
	at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:300)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	... 11 more

Một mớ hỗn độn từ console. Chúng ta khoan hãy bàn tới đó là những thông báo gì. Cứ từ từ, đừng nôn nóng. Tới đây mình chỉ khuyên các bạn khi gặp lỗi server Tomcat có hiện lên hộp thoại như trên “Server Tomcat vx.x server at localhost failed to start” thì nhanh chóng đọc các thông báo lỗi từ console nhé.

Đọc thông báo lỗi từ console

Bên trên là những thông báo mà server trả về trên màn hình console khi có lỗi xảy ra, hỗn độn đến nỗi hoa cả mắt. Bạn hãy đọc từ trên cùng đến hết thông báo, tìm đoạn nào quen thuộc nhất với mình, chẳng hạn từ ADuController rất quen thuộc mà mình tìm thấy trong đống chữ đỏ loè ở console. Kèm theo nó là dòng thông báo “Servlet mapping specifies an unknown servlet name ADuController“.

Phân tích lỗi

Bạn đã tìm ra dòng thông báo lỗi “Servlet mapping specifies an unknown servlet name…“. Vậy nó là lỗi gì? Nguyên nhân do đâu gây ra.

Giải đáp: “Servlet mapping specifies an unknown servlet name ADuController” được server trả về khi nó không tìm thấy servlet name nào có tên ADuController. Khi config web.xml để mapping một url pattern cho một servlet nào đó, bạn sẽ dùng cặp thẻ <servlet-name>…</servlet-name> trong cả 2 cặp thẻ cha là <servlet>…</servlet> và <servlet-mapping>…</servlet-mapping>

Và đây là đoạn config mà mình cố tình làm sai trong web.xml:

<servlet>
    <servlet-name>A Du Controller</servlet-name>
    <servlet-class>ADuController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ADuController</servlet-name>
    <url-pattern>/a-du</url-pattern>
</servlet-mapping>

Có thể thấy, mình muốn mapping url “/a-du” cho servlet “ADuController” nhưng phần servlet-name ở thẻ servletservlet-mapping đã khác nhau (“A Du Controller” và “ADuController” bạn nghĩ chúng khác nhau chứ?).

Khắc phục lỗi

Như đã phân tích, bạn chỉ cần config lại nội dung trong cặp thẻ servlet-name giống nhau ở cả 2 cặp thẻ serlvet và servlet-mapping là đã fix xong lỗi rồi đó.

<servlet>
    <servlet-name>ADuController</servlet-name>
    <servlet-class>ADuController</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ADuController</servlet-name>
    <url-pattern>/a-du</url-pattern>
</servlet-mapping>

Cuối cùng, mình có vài lời tâm tình nhỏ dành cho các bạn trước khi dứt điểm bài này:

  1. Đừng tỏ ra quá nguy hiểm khi mapping: Đặt nội dung thẻ servlet-name giống với tên class trong thẻ servlet-class cho khoẻ.
  2. Đừng tỏ vẻ bay bướm chim chuột: Nếu lỡ đặt nội dung servlet-name khác với servlet-class thì đừng có văn chương vẽ vời làm gì trong phần config. Ví dụ: <servlet-name>Mapping cho servlet ADuController Ahihi</servlet-name>

Dứt điểm bài này, mong được các bạn góp ý nhiệt tình để những bài sau trong loạt bài có ý nghĩa hơn 😀

2.3 7 votes
Đánh giá bài viết
Nhận thông báo
Thông báo khi có
guest

2 Bình luận
cũ nhất
mới nhất vote nhiều nhất
Phản hồi nội tuyến
Xem tất cả các bình luận
Sớm

Danh hài