我正在开发一个 REST-API,目前正在尝试解决一个问题。问题是当我在 chrome 中访问我的网页时,REST-API 无法连接到 pgsql 数据库。为了说明这个问题,我将发布我的堆栈的精简版本并附上一些解释,描述所涉及的 Java 类和 XML 的起源和功能。之后,我将展示一些涉及的 XML 文件和 java 类的代码。我期待您对我的第一篇文章的回答和反馈。
更新:在帖子的最后,我将披露我在寻找答案方面的主要进展。
到目前为止,我正在使用以下工具:
- Eclipse EE(目前是 Oxygen II)
- Apache Tomcat 8.5.14
- 马文
- 铬合金
- PG-管理员 4
堆栈从这条线开始,这可能意味着泽西遇到了一些困难。
WARNING: The following warnings have been detected: WARNING: Unknown HK2 failure detected:
我的堆栈继续出现下面所示的 java.lang.ExceptionInInitializerError,它源自我的数据库连接代理。
MultiException stack 1 of 2
java.lang.ExceptionInInitializerError
at nl.hu.v1wac.PostgresDAO.webservices.WorldResource.<init (WorldResource.java:25)
Caused by: java.lang.RuntimeException: javax.naming.NameNotFoundException: Name [jdbc/PostgresDS] is not bound in this Context. Unable to find [jdbc].
at nl.hu.v1wac.PostgresDAO.jdbc.BaseDAO.<init>(BaseDAO.java:38)
at nl.hu.v1wac.PostgresDAO.jdbc.CountryDAO.<init>(CountryDAO.java:13)
at nl.hu.v1wac.PostgresDAO.model.WorldService.<init>(WorldService.java:9)
at nl.hu.v1wac.PostgresDAO.model.ServiceProvider.<clinit>(ServiceProvider.java:4)
... 61 more
多堆栈中的第二个异常是 IllegalStateException,它源自我的 WorldResource 类,包含统一资源标识符和 JSON 解释器,用于将 json 消息解析到我的前端。
MultiException stack 2 of 2
java.lang.IllegalStateException: Unable to perform operation: create on nl.hu.v1wac.PostgresDAO.webservices.WorldResource
Caused by: java.lang.RuntimeException: javax.naming.NameNotFoundException:
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:393)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
下面我将展示我的 web.xml。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>MavenJersey</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>nl.hu.v1wac.PostgresDAO.webservices</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/restservices/*</url-pattern>
</servlet-mapping>
</web-app>
下面将展示我的 BaseDAO。此类是我的数据访问对象的连接代理。
import java.sql.Connection;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.net.URI;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
public class BaseDAO {
private static final String URL = "jdbc:postgresql://";
private static final String JDBC_DRIVER = "org.postgresql.Driver";
private static final String CONTEXT = "java:comp/env/jdbc/PostgresDS";
private DataSource connectionPool;
public BaseDAO() {
try {
final String DATABASE_URL_PROP = System.getenv("DATABASE_URL");
if (DATABASE_URL_PROP != null) {
URI dbUri = new URI(DATABASE_URL_PROP);
String dbUrl = URL + dbUri.getHost() + dbUri.getPath();
BasicDataSource pool = new BasicDataSource();
if (dbUri.getUserInfo() != null) {
pool.setUsername(dbUri.getUserInfo().split(":")[0]);
pool.setPassword(dbUri.getUserInfo().split(":")[1]);
}
pool.setDriverClassName(JDBC_DRIVER);
pool.setUrl(dbUrl);
pool.setInitialSize(1);
connectionPool = pool;
} else{
InitialContext ic = new InitialContext();
connectionPool = (DataSource) ic.lookup(CONTEXT);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected final Connection getConnection() {
try {
return connectionPool.getConnection();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
最后,我将以我的 WorldResource 课程结束这篇文章。请注意,大多数代码都被排除在外。
public class WorldResource{
private WorldService service = ServiceProvider.getWorldService();
@GET
@RolesAllowed({"admin"})
@Path("/getAll")
@Produces(MediaType.APPLICATION_JSON)
public String getCountries() {
JsonArrayBuilder jab;
jab = Json.createArrayBuilder();
for (Country c : service.getAllCountries()) {
jab.add(makeCountryObj(c));
}
return jab.build().toString();
}
编辑: @Alok Sinha 发布 context.xml 丢失后,我添加了我已经存在的 context.xml 以提供一些额外的见解。
<?xml version="1.0" encoding="UTF-8"?>
<Context> <Resource name="jdbc/PostgresDS"
url="jdbc:postgresql://localhost:5432/mydb" driverClassName="org.postgresql.Driver"
auth="Container"
type="javax.sql.DataSource"
username="javaduser"
password="javadude"
/>
<ResourceLink name="jdbc/PostgresDS" global="jdbc/PostgresDS" type="javax.sql.DataSource"
/>
</Context>
更新:在向我的 web.xml 添加资源引用后,由Apache 手册推荐,我能够对我的连接问题获得一些新的见解。
<resource-ref>
<description>PostgreSQL Datasource example</description>
<res-ref-name>jdbc/PostgresDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
如下面的堆栈所示,添加资源引用似乎有助于将我的应用程序指向正确的方向。但是,名称和 url 似乎是空的。
Cannot create JDBC driver of class '' for connect URL 'null'
java.sql.SQLException: No suitable driver
at java.sql.DriverManager.getDriver(Unknown Source)
at nl.hu.v1wac.PostgresDAO.jdbc.BaseDAO.getConnection(BaseDAO.java:47)
at nl.hu.v1wac.PostgresDAO.webservices.WorldResource.getCountries(WorldResource.java:34)
UPDATE2: 我尝试了另一种方法。我从一个最初的 Maven 项目开始,然后从那里构建我的应用程序。我摆脱了 IllegalstateException。我已经完全按照Alok Sinha的描述实现了您的 context.xml。所以,没有资源链接。我还把 BaseDAO 脱掉到只有 Initialcontext 和 Datasource 的地步。现在我可以在没有 basedao 的情况下将应用程序部署为 war 文件。如果我尝试使用 BaseDAO 部署它,由于我的 tomcat 日志中出现以下错误,我无法运行:
org.apache.catalina.deploy.NamingResourcesImpl.cleanUp Failed to retrieve
JNDI naming context for container [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/holidayboardapp]] so no cleanup was performed for that container
javax.naming.NameNotFoundException: Name [comp/env] is not bound in this Context. Unable to find [comp].`