英文:
Jetty and Jersey 404 error on an old project
问题
以下是翻译好的内容:
作为我的工作的一部分,我正在尝试更新一些我们的服务,其中一个服务使用Jetty和Jersey进行部署。不幸的是,这段代码非常老旧(一些依赖来自于2014年),虽然它能够编译并且服务器能够启动,但是每当我在我的IDE中使用mvn jetty:run
命令运行它时,根目录显示Directory /
消息,但对于其他所有URL,我都会得到404 NOT FOUND
错误。
我在控制台上没有收到任何警告/错误消息,也找不到为什么会发生这种情况。我已经进行了大量搜索,但代码似乎是正确的,唯一缺少的是web.xml
文件,但我认为Jetty是嵌入式的。需要注意的是,这段代码已经作为一个JAR文件在生产环境中运行。
以下是一些文件内容:
pom.xml
(POM文件内容)
下面的类被引用以启动服务器:
ApiService.java
(ApiService.java的代码内容)
restEndpoint.java
(restEndpoint.java的代码内容)
有任何想法为什么会发生这种情况吗?
http://localhost:8080/v4/restEndpoint/getsamplejson
返回404 NOT FOUND
。
http://localhost:8080/
显示Directory: /
。
我应该尝试将其构建为JAR文件,并通过该方式运行,而不是使用mvn jetty:run
命令吗?
英文:
As part of my work, I am trying to update some of our services and one is being deployed with Jetty & Jersey. Unfortunately the code is very old (some dependencies are from 2014), and while it is compiling and server starts, whenever I run it from my IDE with mvn jetty:run
the root directory shows the Directory /
message correctly whereas for all other URLs I get the error 404 NOT FOUND
.
I don't get any warning/error messages on console and I can't find why it happens. I've searched a lot but the code seems correct, the only thing that is missing is the web.xml
but I think Jetty is embedded, and I need to mention that this code is already running in production as a JAR.
Below you can see some of the files:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>sample</artifactId>
<version>2.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.2.v20140723</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.2.3.v20140905</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.2.3.v20140905</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160212</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
The class below is referenced to start the server:
ApiService.java
import com.simple.api.restendpoint.*;
import org.apache.log4j.Logger;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.IPAccessHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import java.util.HashSet;
import java.util.Set;
public class ApiService {
Logger log = Logger.getLogger(ApiService.class);
private static ApiService instance;
private final Server server;
private ApiService(){
//CREATE CONFIG
Set<Class<?>> s = new HashSet<>();
s.add(restEndpoint.class);
ResourceConfig config = new ResourceConfig(s);
//CREATE CONTAINER
ServletContainer container = new ServletContainer(config);
//CREATE CONTEXT
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
context.addServlet(new ServletHolder(container),"/*");
//CREATE RPC SERVER
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(50);
server = new Server(threadPool);
server.setHandler(context);
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("testkeystore");
sslContextFactory.setKeyStorePassword("testkeystore");
sslContextFactory.setKeyManagerPassword("testkeystore");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration();
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
ServerConnector sslConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),
new HttpConnectionFactory(https_config));
sslConnector.setPort(Settings.getInstance().getRpcPort());
server.addConnector(sslConnector);
}
public static ApiService getInstance() {
if (instance==null) {
instance = new ApiService();
}
return instance;
}
public void start() {
try {
//START RPC
server.start();
server.join();
log.info("Server started");
}
catch (Exception e) {
//FAILED TO START RPC
log.error("Error starting server");
} finally {
server.destroy();
}
}
}
restEndpoint.java
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.Context;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
@Path("/v4/restEndpoint")
@Produces({"application/json"})
public class restEndpoint {
Logger log = Logger.getLogger(restEndpoint.class);
private static final String VERSION = "v4";
private static final ExecutorService executors = Executors.newFixedThreadPool(20);
@Context
HttpServletRequest request;
@GET
@Path("/getsamplejson")
public void getSampleJson(@Suspended final AsyncResponse asyncResponse) {
executors.execute(new Runnable() {
@Override
public void run() {
String result = veryExpensiveOperation();
asyncResponse.resume(result);
}
private String veryExpensiveOperation() {
JSONObject sampleJson = new JSONObject().put("test", 0);
return sampleJson.toString();
}
});
}
}
Any idea why is it happening?
http://localhost:8080/v4/restEndpoint/getsamplejson
returns 404 NOT FOUND
http://localhost:8080/
shows Directory: /
Should I try to build it as a JAR and run it through that, instead of using the mvn jetty:run
command?
答案1
得分: 2
你有一个从代码中启动的嵌入式Jetty实例。
这可以从您提供的ApiService
源代码中看出。
您不能使用jetty-maven-plugin
来管理/启动/运行该类。
jetty-maven-plugin
专门用于处理Web应用,可以是打包为WAR文件,也可以是作为已解压的Web应用目录。(Web应用通常会包含WEB-INF/web.xml文件和/或带有Servlet注解的类)
您需要使用其他方法启动服务器,这对于您的项目是独特的,可能是某种主类或测试用例,最终会实例化ApiService
并在其上调用.start()
方法。
英文:
You have an embedded-jetty instance, started from code.
That is evidenced by the ApiService
source you have provided.
You cannot use the jetty-maven-plugin
to manage / start / run that class.
The jetty-maven-plugin
is exclusively for working with webapps, either as WAR packaged files, or as exploded webapp directories. (webapps will either have a WEB-INF/web.xml and / or Servlet annotated classes within it)
You'll need to start the server using other means that is unique to your project, likely some kind of main class, or testcase, that eventually instantiates the ApiService
and calls .start()
on it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论