我在Resteasy工作,我要向服务器发出异步请求。真正的目的是,我将提交一个表格,该表格将被转换为.xlsx文件,至少需要10秒才能完成。所以异步请求是最好的方法。我按照以下链接中的步骤进行操作。
我正在制作像这样的ajax请求。
$.ajax({
url : 'rest/parentPath/childPath',
type : 'GET',
success : function(data, status, xhr) {
console.log(xhr.getResponseHeader('Location'));
},
failure : function(data) {
console.log(data);
},
error : function(error,status) {
}
});
ParentClass.java
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
@Component
@Path("/parentPath")
public class ParentClass {
@GET
@Path("childPath")
@Produces("text/plain")
public void asyncFunction(@Suspended final AsyncResponse response){
Thread t = new Thread() {
@Override
public void run()
{
try
{
Response jaxrs = Response.ok("basic").type(MediaType.TEXT_PLAIN).build();
System.out.println("entered======================= =================================================");
response.resume(jaxrs);
}
catch (Exception e){
e.printStackTrace();
}
}
};
t.start();
}
}
如果我只是发出ajax请求,它会给我503 Service unavailable error
但是我确实执行了异步任务,我可以通过查看wildfly日志中的sysout来确认。但这不是异步应该如何完成的方式。我将能够在第二个请求中看到我的异步任务的响应。我按照此链接中的步骤进行操作。
https://docs.jboss.org/resteasy/docs/3.0.9.Final/userguide/html_single/#async_job
如果我将?asynch=true
放在请求网址中,我会立即得到202 Accepted
的响应,其响应位置为异步作业。但它甚至没有进入try声明。这样的wildfly终端会抛出一个错误。
19:11:41,733 WARN [org.jboss.resteasy.core.ExceptionHandler] (pool-4-thread-1) Failed executing GET /parentPath/childPath: org.jboss.resteasy.spi.BadRequestExcept
ion: Failed processing arguments of org.jboss.resteasy.spi.metadata.ResourceMethod@44d4407c
at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:104) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:112) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:237) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.AsynchronousDispatcher.invokeSuper(AsynchronousDispatcher.java:237) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.AsynchronousDispatcher$1.call(AsynchronousDispatcher.java:278) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.AsynchronousDispatcher$1.call(AsynchronousDispatcher.java:269) [resteasy-jaxrs-3.0.10.Final.jar:]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [rt.jar:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [rt.jar:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [rt.jar:1.8.0_25]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_25]
Caused by: java.lang.NullPointerException
at org.jboss.resteasy.core.ResourceMethodInvoker.initializeAsync(ResourceMethodInvoker.java:374) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.AsynchronousResponseInjector.inject(AsynchronousResponseInjector.java:43) [resteasy-jaxrs-3.0.10.Final.jar:]
at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:89) [resteasy-jaxrs-3.0.10.Final.jar:]
... 12 more
如果我使用asynch=true
再次提出相同的请求,则会显示相同的错误,但会显示(pool-4-thread-2)
而不是(pool-4-thread-1)
这意味着在服务器端但在运行时层没有发生异常。因为我的代码中出现的任何异常都将出现在日志文件中,但不会出现在wildfly终端中。我将发布web.xml,WebConfig.java,build.gradle文件。我只是在jboss docs中复制了同样的东西,但是我无法弄清楚为什么在wildfly层发生这种异常。
Web.xml中
<?xml version="1.0" encoding="UTF-8"?>
<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">
<display-name>Web Application</display-name>
<distributable />
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<!-- Context Configuration locations for Spring XML files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/applicationContext-resources.xml
classpath:/applicationContext-dao.xml
classpath:/applicationContext-service.xml
classpath*:/applicationContext.xml
/WEB-INF/applicationContext*.xml
</param-value>
</context-param>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<context-param>
<param-name>resteasy.async.job.service.enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.async.job.service.max.job.results</param-name>
<param-value>100</param-value>
</context-param>
<!-- Maximum wait time on a job when a client is querying for it -->
<context-param>
<param-name>resteasy.async.job.service.max.wait</param-name>
<param-value>300000</param-value>
</context-param>
<!-- Thread pool size of background threads that run the job -->
<context-param>
<param-name>resteasy.async.job.service.thread.pool.size</param-name>
<param-value>100</param-value>
</context-param>
<!-- Set the base path for the Job uris -->
<context-param>
<param-name>resteasy.async.job.service.base.path</param-name>
<param-value>/asynch/jobs</param-value>
</context-param>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.mypackage.service.WebConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.html</welcome-file>
</welcome-file-list>
</web-app>
WebConfig.java
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class WebConfig extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
public WebConfig() {
// ADD YOUR RESTFUL RESOURCES HERE
this.singletons.add(new SignupService());
this.singletons.add(new UserService());
this.singletons.add(new ParentClass());
}
public Set<Class<?>> getClasses()
{
return this.empty;
}
public Set<Object> getSingletons()
{
return this.singletons;
}
}
的build.gradle
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
apply plugin: 'eclipse'
// Uses JDK 8
sourceCompatibility = 1.8
targetCompatibility = 1.8
// 1. Get dependencies from Maven local repository
// 2. Get dependencies from Maven central repository
repositories {
mavenLocal()
mavenCentral()
maven {
url "http://repo1.maven.org/maven2"
}
}
configurations {
provided
}
sourceSets {
main { compileClasspath += configurations.provided }
}
//Project dependencies
dependencies {
//Spring framework core
compile 'org.springframework:spring-web:4.1.4.RELEASE'
compile 'org.springframework:spring-core:4.1.4.RELEASE'
compile 'org.springframework:spring-context:4.1.4.RELEASE'
compile 'org.springframework:spring-context-support:4.1.4.RELEASE'
compile 'org.springframework:spring-orm:4.1.4.RELEASE'
compile 'org.springframework.security:spring-security-core:4.0.0.RELEASE'
//MySQL database driver
//compile 'mysql:mysql-connector-java:5.1.34'
compile 'com.oracle:ojdbc6:11.2.0.1.0'
//Hibernate framework
compile 'org.hibernate:hibernate-core:4.3.8.Final'
compile 'commons-dbcp:commons-dbcp:1.2.2'
//Servlet API
compile 'javax.servlet:servlet-api:2.5'
//Base-64 Apache commons
compile 'commons-codec:commons-codec:1.10'
//log4j
compile 'log4j:log4j:1.2.17'
compile 'org.slf4j:slf4j-simple:1.7.10'
//XmlBeans Equity Valuation
compile 'org.apache.xmlbeans:xmlbeans:2.6.0'
//Poi Equity Valuation
compile 'org.apache.poi:poi:3.10.1'
//Poi ooxml Equity Valuation
compile 'org.apache.poi:poi-ooxml:3.10.1'
//Poi ooxml Schemas Equity Valuation
compile 'org.apache.poi:poi-ooxml-schemas:3.10.1'
//Jacob Equity Valuation
compile 'jacob:jacob:1.18-M2'
//Google gson
compile 'com.google.code.gson:gson:2.3.1'
provided 'org.jboss.resteasy:resteasy-jaxrs:3.0.11.Final'
provided 'org.jboss.resteasy:resteasy-spring:3.0.11.Final'
}
答案 0 :(得分:1)
尝试添加评论但字数限制。
我现在可以做异步工作了。我发现使用 AsynchResponse 和 Suspended 注释会导致此异常。这不是异步作业处理所必需的。
空指针的原因是两者混淆了。
有两个异步的东西,文档真的把它们混合起来 1. 异步响应:使用Suspended和AsynchResponse将释放收到请求的服务器线程,工作将由创建的新线程完成。但是客户端会等待响应。直到您的新线程完成并将其发回。为此,web.xml不需要进行任何更改。
2。 异步作业处理:您可以在此处将 resteasy.async.job.service.enabled 设置为web.xml中的 true 以及任何其他可选项参数(如果需要)。 APi无需进行任何其他更改。我的方法是
@POST
@Path("/helloworld")
public Response getHelloWorld() {
log.info("API invoked");
longLiftingJob();
log.info("API invoke done");
return Response.status(200).entity("Hello World").build();
}
使用web.xml中的true参数,框架将调用您在新线程中调用(简单地放入)并在202响应中返回相同的作业ID。作为位置标题为
Location → http://127.0.0.1:8080/myrest/asynch/jobs/1432015827488-1
客户端在上面的URL上执行GET / POST,并在API完成后获得API返回的响应。但实际的客户端永远不会等待如此异步的工作。