我在网上看过一些文章,比如:
NonRepeatableRequestException 使用 jersey 和 apache httpClient 进行 REST 调用
和:
如何使用泽西岛发送经过 NTLM 身份验证的帖子请求?
第二个问题的答案只为GET请求提供了解决方案。我的客户设置如下:
private void init() {
if (client == null) {
client = ClientBuilder.newClient(prepareClientConfig());
}
}
private ClientConfig prepareClientConfig() {
ClientConfig config = new ClientConfig();
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new NTCredentials(userId, password, null, null));
config.property(ApacheClientProperties.CREDENTIALS_PROVIDER, credentialsProvider);
config.connectorProvider(new ApacheConnectorProvider());
return config;
}
这里是我发出GET请求的地方:
@Override
public Response get(String uri, List<HttpUrlParameter> params) throws WebCallException {
init();
String url = baseUrl + restUri + apiVersion + uri;
WebTarget webTarget = client.target(url);
for (HttpUrlParameter param : params) {
webTarget = webTarget.queryParam(param.getKey(), param.getValue());
}
Response response = webTarget.request(MediaType.APPLICATION_JSON).get();
return response;
}
HttpUrlParameter 和 WebCallException 类由我定义。上面的 GET 请求效果很好。然后我尝试开机自检呼叫:
@Override
public Response post(String uri, Object entity, List<HttpUrlParameter> params) throws WebCallException {
init();
String url = baseUrl + restUri + apiVersion + uri;
WebTarget webTarget = client.target(url);
for (HttpUrlParameter param : params) {
webTarget = webTarget.queryParam(param.getKey(), param.getValue());
}
Response response = webTarget
.request(MediaType.APPLICATION_JSON)
.post(Entity.json(entity));
return response;
}
我为这个特定测试传递的实体非常简单:
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public class CrmAccount {
@JsonProperty("accountid")
private String accountId;
@JsonProperty("accountnumber")
private String accountNumber;
private String name;
@JsonProperty("emailaddress1")
private String emailAddress1;
@JsonProperty("telephone1")
private String phoneNumber;
@JsonProperty("address1_addressid")
private String address1Id;
@JsonProperty("address1_line1")
private String address1Line1;
@JsonProperty("address1_line2")
private String address1Line2;
@JsonProperty("address1_city")
private String address1City;
@JsonProperty("address1_stateorprovince")
private String address1StateOrProvince;
@JsonProperty("address1_postalcode")
private String address1PostalCode;
@JsonProperty("address1_county")
private String address1Country;
public CrmAccount() {
super();
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public String getAccountNumber() {
return accountNumber;
}
public void setAccountNumber(String accountNumber) {
this.accountNumber = accountNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmailAddress1() {
return emailAddress1;
}
public void setEmailAddress1(String emailAddress1) {
this.emailAddress1 = emailAddress1;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress1Id() {
return address1Id;
}
public void setAddress1Id(String address1Id) {
this.address1Id = address1Id;
}
public String getAddress1Line1() {
return address1Line1;
}
public void setAddress1Line1(String address1Line1) {
this.address1Line1 = address1Line1;
}
public String getAddress1Line2() {
return address1Line2;
}
public void setAddress1Line2(String address1Line2) {
this.address1Line2 = address1Line2;
}
public String getAddress1City() {
return address1City;
}
public void setAddress1City(String address1City) {
this.address1City = address1City;
}
public String getAddress1StateOrProvince() {
return address1StateOrProvince;
}
public void setAddress1StateOrProvince(String address1StateOrProvince) {
this.address1StateOrProvince = address1StateOrProvince;
}
public String getAddress1PostalCode() {
return address1PostalCode;
}
public void setAddress1PostalCode(String address1PostalCode) {
this.address1PostalCode = address1PostalCode;
}
public String getAddress1Country() {
return address1Country;
}
public void setAddress1Country(String address1Country) {
this.address1Country = address1Country;
}
}
我能够毫无问题地通过Postman进行POST调用,所以我知道这个调用(在我的Java代码之外)工作正常。当我使用Jersey进行POST调用时,我得到以下异常:
javax.ws.rs.ProcessingException: org.apache.http.client.ClientProtocolException
at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:481)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:252)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437)
at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343)
at com.harpercollinschristian.integration.util.rest.crm.RestApiClientCrmImpl.post(RestApiClientCrmImpl.java:119)
at com.harpercollinschristian.integration.service.crm.CrmRestfulApi$4.request(CrmRestfulApi.java:127)
at com.harpercollinschristian.integration.util.rest.crm.CrmRestApiRequest.exec(CrmRestApiRequest.java:53)
at com.harpercollinschristian.integration.service.crm.CrmRestfulApi.createAccount(CrmRestfulApi.java:132)
at com.harpercollinschristian.integration.service.crm.CrmRestfulApiTest.testCreateAccount(CrmRestfulApiTest.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.apache.http.client.ClientProtocolException
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:71)
at org.glassfish.jersey.apache.connector.ApacheConnector.apply(ApacheConnector.java:435)
... 44 more
Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:225)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
... 46 more
在我看来,传递给post()方法的JSON实体可能被设置为只能调用一次的流?我需要为所有的POST和PATCH调用发送的JSON消息并不长,可以很容易地用FasterXML / Jackson库表示为一个字符串——所以我们应该很容易“重复”这个实体。我知道我可能遗漏了一些很明显的东西,但是我找不到解决方法。该项目使用Jersey Client对其他两个非微软(因此也非NTLM)服务进行REST API调用,所以我需要使用Jersey(换句话说,如果可以的话,我不想把Jersey拿出来)。
任何帮助将不胜感激!
我从我们的微软CRM合作伙伴那里收到了一段代码,其中有答案。我们设置配置的方法需要更新为:
private ClientConfig prepareClientConfig() {
ClientConfig config = new ClientConfig();
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
final AuthScope ntlmAuthScope = new AuthScope(null, -1, AuthScope.ANY_REALM, "NTLM");
credentialsProvider.setCredentials(ntlmAuthScope, new NTCredentials(userId, password, null, null));
config.property(ApacheClientProperties.CREDENTIALS_PROVIDER, credentialsProvider);
config.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED);
config.connectorProvider(new ApacheConnectorProvider());
return config;
}
请注意REQUEST_ENTITY_PROCESSING - set的config属性为BUFFERED。我认为,这就是我们所需要的,允许实体被缓冲,从而被后续请求重用(以满足NTLM协议)。还有一些其他的附加功能(例如特定的AuthScope)。
我正在进行一个示例项目,使用: JAX-RS(泽西2) JSR-303 Bean validaiton 泽西测试测试 Grizzly Http容器 杰克逊2.7.3 在添加@JsonIgnore和@JsonProperty之前,一切都按预期进行,在对对象属性执行bean验证时,我能够毫无问题地运行测试。通常情况下,“password”字段不应用于反序列化,所以我用@JsonIgnore标记了它的g
我正在使用Jersey用Java编写一个RESTful应用程序,我需要对用户进行身份验证。我知道我可以使用注释@RolesAllowed来指定资源中的角色,但是我不明白用户是如何与特定角色相关联的。客户端以这种方式发送用户名和密码 假设某些方法只能由超级用户使用,而其他方法只能由任何用户使用,那么当用户名和密码由客户端发送时,我如何区分它们?
我试图将资源的实例注入具有Singleton作用域的JAX-RS应用程序,但当我这样做时,我得到: 警告:在服务器运行时中注册的提供程序com.test.jersey.app.MyResource未实现任何适用于服务器运行时的提供程序接口。由于约束配置问题,将忽略提供程序com.test.jersey.app.MyResource。 我有一个如下的应用程序,它需要一个已经运行的MyResource
我正在创建一个在Karaf中作为OSGi容器运行的应用程序,并使用OSGi HTTP服务和Jersey来公开REST APIs。我需要添加SAML2身份验证和基于权限的授权。为此,我想在Shiro中使用基于注释的方法,因为spring似乎正在远离OSGi。我的问题: 带有SAML罐子的Shiro是否适合OSGi环境? 我想使用WSO2作为身份提供者。Shiro和WSO2一起工作有任何警告吗? 对于
问题内容: 我有一个RESTful API,我正尝试通过Android和RestTemplate与之连接。通过设置HttpEntity的标头,然后使用RestTemplate的方法,对HTTP的所有请求均通过HTTP身份验证进行身份验证。 所有GET请求都可以通过这种方式很好地工作,但是我无法弄清楚如何完成经过身份验证的POST请求。和处理POST,但没有简单的方法来设置Authenticatio