Apache camel Rest 服务与 undertow 和北欧字母
Apache camel Rest service with undertow and nordic letters
我有一个使用 undertow componenet 的休息服务。我用的是wildfly和wildfly patch 4.7.0 (apache camel 2.19)
我无法通过 Rest 服务回复北欧字母。用邮递员测试。
密码是:
@Override
public void configure() throws Exception {
restConfiguration().component("undertow");
rest("/hello").post("/{name}").consumes("application/json").to("direct:testpost");
from("direct:testpost")
.routeId("testpost")
.log("${body}")
.transform().jsonpath("test");
}
当我发送时:
POST /hello/Anton HTTP/1.1 Host: 192.168.56.103:8080 Content-Type:
application/json ; charset=UTF-8 Cache-Control: no-cache
Postman-Token: c7ed9034-8b58-d104-9804-a1ff60a26f65
{"test": "test with Å"}
我收到错误:
2017-06-07 07:06:16,253 INFO [testput] (default task-5) {"test":
"test with Å"}
2017-06-07 07:06:16,258 ERROR [io.undertow.request] (default task-5)
UT005071: Undertow request failed HttpServerExchange{ POST
/hello/Anton request {Accept=[*/*],
Postman-Token=[a3f9c986-e6d1-1f41-e4f8-54f3e38678c3],
Accept-Language=[sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4],
Cache-Control=[no-cache], Accept-Encoding=[gzip, deflate],
Origin=[chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop],
User-Agent=[Mozilla/5.0 (Windows NT 6.1; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86
Safari/537.36], Connection=[keep-alive], Content-Length=[24],
Content-Type=[application/json ; charset=UTF-8],
Host=[192.168.56.103:8080]} response {Accept=[*/*],
Postman-Token=[a3f9c986-e6d1-1f41-e4f8-54f3e38678c3],
Accept-Language=[sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4], name=[Anton],
X-Powered-By=[Undertow/1], Accept-Encoding=[gzip, deflate],
breadcrumbId=[ID-localhost-39384-1496833334654-11-5],
Server=[WildFly/10],
Origin=[chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop],
User-Agent=[Mozilla/5.0 (Windows NT 6.1; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86
Safari/537.36], Content-Type=[application/json ; charset=UTF-8]}}:
org.apache.camel.TypeConversionException: Error during type conversion
from type: java.lang.String to the required type: java.nio.ByteBuffer
with value test with Å due java.nio.BufferOverflowException
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.createTypeConversionException(BaseTypeConverterRegistry.java:629)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:150)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:121)
at org.apache.camel.component.undertow.UndertowConsumer.handleRequest(UndertowConsumer.java:135)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:805)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748) Caused by: org.apache.camel.RuntimeCamelException:
java.nio.BufferOverflowException
at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1756)
at org.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1355)
at org.apache.camel.impl.converter.StaticMethodTypeConverter.convertTo(StaticMethodTypeConverter.java:59)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.doConvertTo(BaseTypeConverterRegistry.java:306)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:133)
... 7 more Caused by: java.nio.BufferOverflowException
at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:189)
at java.nio.ByteBuffer.put(ByteBuffer.java:859)
at org.apache.camel.converter.NIOConverter.toByteBuffer(NIOConverter.java:102)
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.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1351)
... 10 more
暗流配置:
<subsystem xmlns="urn:jboss:domain:undertow:3.1">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<filter-ref name="server-header"/>
<filter-ref name="x-powered-by-header"/>
</host>
</server>
<servlet-container name="default">
<jsp-config/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
<filters>
<response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
<response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
</filters>
</subsystem>
有人知道我该如何解决这个问题吗?感谢所有帮助!
这是 org.apache.camel.converter.NIOConverter (2.18.4)
中的错误
public static ByteBuffer toByteBuffer(String value, Exchange exchange) {
ByteBuffer buf = ByteBuffer.allocate(value.length());
byte[] bytes = null;
if (exchange != null) {
String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
if (charsetName != null) {
try {
bytes = value.getBytes(charsetName);
} catch (UnsupportedEncodingException e) {
LOG.warn("Cannot convert the byte to String with the charset " + charsetName, e);
}
}
}
if (bytes == null) {
bytes = value.getBytes();
}
buf.put(bytes);
buf.flip();
return buf;
}
ByteBuffer 是用 String.length() 分配的,忽略了它可能包含双字节字符的事实。
我正在通过使用事件侦听器替换注册表中的转换器来解决此错误。
void onContextStarting(@Observes CamelContextStartingEvent event) {
def context = event.getContext();
def registry = context.getTypeConverterRegistry();
registry.setTypeConverterExistsLoggingLevel(LoggingLevel.INFO)
registry.setTypeConverterExists(TypeConverterExists.Override)
registry.addTypeConverter(ByteBuffer.class,String.class, new StringToByteBufferConverter());
registry.setTypeConverterExists(TypeConverterExists.Ignore)
}
我替换它的转换器使用 byte.length 分配 ByteBuffer,因此缓冲区与字符串的实际字节数相匹配:
import org.apache.camel.Exchange;
import org.apache.camel.support.TypeConverterSupport;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
public class StringToByteBufferConverter extends TypeConverterSupport {
public <T> T convertTo(Class<T> type, Exchange exchange, Object object) {
String value = (String)object;
byte[] bytes = null;
if (exchange != null) {
String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
if (charsetName != null) {
try {
bytes = value.getBytes(charsetName);
} catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
}
if (bytes == null) {
bytes = value.getBytes();
}
ByteBuffer buf = ByteBuffer.allocate(bytes.length);
buf.put(bytes);
buf.flip();
return (T)buf;
}
}
您还可以通过将正文转换为 String 以外的类型来绕过错误的转换器来解决此错误:
@Override
public void configure() throws Exception {
restConfiguration().component("undertow");
rest("/hello").post("/{name}").consumes("application/json").to("direct:testpost");
from("direct:testpost")
.routeId("testpost")
.log("${body}")
.transform().jsonpath("test")
.convertBodyTo(byte[].class);
}
我有一个使用 undertow componenet 的休息服务。我用的是wildfly和wildfly patch 4.7.0 (apache camel 2.19)
我无法通过 Rest 服务回复北欧字母。用邮递员测试。
密码是:
@Override
public void configure() throws Exception {
restConfiguration().component("undertow");
rest("/hello").post("/{name}").consumes("application/json").to("direct:testpost");
from("direct:testpost")
.routeId("testpost")
.log("${body}")
.transform().jsonpath("test");
}
当我发送时:
POST /hello/Anton HTTP/1.1 Host: 192.168.56.103:8080 Content-Type: application/json ; charset=UTF-8 Cache-Control: no-cache Postman-Token: c7ed9034-8b58-d104-9804-a1ff60a26f65
{"test": "test with Å"}
我收到错误:
2017-06-07 07:06:16,253 INFO [testput] (default task-5) {"test":
"test with Å"}
2017-06-07 07:06:16,258 ERROR [io.undertow.request] (default task-5)
UT005071: Undertow request failed HttpServerExchange{ POST
/hello/Anton request {Accept=[*/*],
Postman-Token=[a3f9c986-e6d1-1f41-e4f8-54f3e38678c3],
Accept-Language=[sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4],
Cache-Control=[no-cache], Accept-Encoding=[gzip, deflate],
Origin=[chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop],
User-Agent=[Mozilla/5.0 (Windows NT 6.1; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86
Safari/537.36], Connection=[keep-alive], Content-Length=[24],
Content-Type=[application/json ; charset=UTF-8],
Host=[192.168.56.103:8080]} response {Accept=[*/*],
Postman-Token=[a3f9c986-e6d1-1f41-e4f8-54f3e38678c3],
Accept-Language=[sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4], name=[Anton],
X-Powered-By=[Undertow/1], Accept-Encoding=[gzip, deflate],
breadcrumbId=[ID-localhost-39384-1496833334654-11-5],
Server=[WildFly/10],
Origin=[chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop],
User-Agent=[Mozilla/5.0 (Windows NT 6.1; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86
Safari/537.36], Content-Type=[application/json ; charset=UTF-8]}}:
org.apache.camel.TypeConversionException: Error during type conversion
from type: java.lang.String to the required type: java.nio.ByteBuffer
with value test with Å due java.nio.BufferOverflowException
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.createTypeConversionException(BaseTypeConverterRegistry.java:629)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:150)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:121)
at org.apache.camel.component.undertow.UndertowConsumer.handleRequest(UndertowConsumer.java:135)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:805)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748) Caused by: org.apache.camel.RuntimeCamelException:
java.nio.BufferOverflowException
at org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException(ObjectHelper.java:1756)
at org.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1355)
at org.apache.camel.impl.converter.StaticMethodTypeConverter.convertTo(StaticMethodTypeConverter.java:59)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.doConvertTo(BaseTypeConverterRegistry.java:306)
at org.apache.camel.impl.converter.BaseTypeConverterRegistry.convertTo(BaseTypeConverterRegistry.java:133)
... 7 more Caused by: java.nio.BufferOverflowException
at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:189)
at java.nio.ByteBuffer.put(ByteBuffer.java:859)
at org.apache.camel.converter.NIOConverter.toByteBuffer(NIOConverter.java:102)
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.apache.camel.util.ObjectHelper.invokeMethod(ObjectHelper.java:1351)
... 10 more
暗流配置:
<subsystem xmlns="urn:jboss:domain:undertow:3.1">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/>
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<filter-ref name="server-header"/>
<filter-ref name="x-powered-by-header"/>
</host>
</server>
<servlet-container name="default">
<jsp-config/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>
<filters>
<response-header name="server-header" header-name="Server" header-value="WildFly/10"/>
<response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
</filters>
</subsystem>
有人知道我该如何解决这个问题吗?感谢所有帮助!
这是 org.apache.camel.converter.NIOConverter (2.18.4)
中的错误public static ByteBuffer toByteBuffer(String value, Exchange exchange) {
ByteBuffer buf = ByteBuffer.allocate(value.length());
byte[] bytes = null;
if (exchange != null) {
String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
if (charsetName != null) {
try {
bytes = value.getBytes(charsetName);
} catch (UnsupportedEncodingException e) {
LOG.warn("Cannot convert the byte to String with the charset " + charsetName, e);
}
}
}
if (bytes == null) {
bytes = value.getBytes();
}
buf.put(bytes);
buf.flip();
return buf;
}
ByteBuffer 是用 String.length() 分配的,忽略了它可能包含双字节字符的事实。
我正在通过使用事件侦听器替换注册表中的转换器来解决此错误。
void onContextStarting(@Observes CamelContextStartingEvent event) {
def context = event.getContext();
def registry = context.getTypeConverterRegistry();
registry.setTypeConverterExistsLoggingLevel(LoggingLevel.INFO)
registry.setTypeConverterExists(TypeConverterExists.Override)
registry.addTypeConverter(ByteBuffer.class,String.class, new StringToByteBufferConverter());
registry.setTypeConverterExists(TypeConverterExists.Ignore)
}
我替换它的转换器使用 byte.length 分配 ByteBuffer,因此缓冲区与字符串的实际字节数相匹配:
import org.apache.camel.Exchange;
import org.apache.camel.support.TypeConverterSupport;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
public class StringToByteBufferConverter extends TypeConverterSupport {
public <T> T convertTo(Class<T> type, Exchange exchange, Object object) {
String value = (String)object;
byte[] bytes = null;
if (exchange != null) {
String charsetName = exchange.getProperty(Exchange.CHARSET_NAME, String.class);
if (charsetName != null) {
try {
bytes = value.getBytes(charsetName);
} catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException(e);
}
}
}
if (bytes == null) {
bytes = value.getBytes();
}
ByteBuffer buf = ByteBuffer.allocate(bytes.length);
buf.put(bytes);
buf.flip();
return (T)buf;
}
}
您还可以通过将正文转换为 String 以外的类型来绕过错误的转换器来解决此错误:
@Override
public void configure() throws Exception {
restConfiguration().component("undertow");
rest("/hello").post("/{name}").consumes("application/json").to("direct:testpost");
from("direct:testpost")
.routeId("testpost")
.log("${body}")
.transform().jsonpath("test")
.convertBodyTo(byte[].class);
}