如何指示 JAXB Marshaller 仅出于审核目的清理 base64Binary 数据?
我正在 JAXWS/JAXB Web 服务环境中工作。 JAXWS 开箱即用,使用 JAXB 来编组/解组 Web 服务有效负载。
我还需要审核所有请求和响应负载。
我想要一个紧凑而简洁的审计有效负载的编组表示(作为一个不相关的旁注 - 我正在使用 java.util.concurrent.BlockingQueue 和一些消费者线程进行审计,以将批量的审计数据放入审计数据源中)。
我在一些 Web 服务响应负载中包含二进制内容(mtom),但我不想对这些内容进行编组审计,因为序列化的 base64 太大。
所以我的需要是创建一个编组器(专门用于auditng),在所有情况下都会擦除二进制内容,但不会出于编组Web服务响应有效负载的主要目的进行擦除。我将 XSD 转换为 Java xjc。我需要对两个上下文/编组器使用相同的 XSD/JAXB 命名空间。
Java 类型转换器:
<jxb:javaType name=""
parseMethod="com.xxx.xxx.ws.converter.XXXLongConverter.parseXXXLong"
printMethod="com.xxx.xxx.ws.converter.XXXLongConverter.printXXXLong" />
将不起作用,因为 1. 我需要取消注册适配器 http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#setAdapter%28java.lang.Class,%20A%29 对于编组器,我不认为我对 JAXWS 有兴趣。 2. 我无法保证 JAXB 将决定创建以便取消注册的类名。
我创建了自己的 XMLAdapter 并使用了 annox jaxb 插件 但这并没有真正起作用,原因与上述不起作用相同。
更新:我现在尝试在编组以清理二进制数据之前手动并反思性地遍历有效负载(待审核),但这对于它的价值来说实在是太痛苦了。
我还应该提到,为了简洁起见,我正在使用 jersey 支持 JAXB 的 JSON 序列化 但我不认为这会消除或增加我的基本问题:
如何在一个编组器/解组器中清理数据,而不是另一个编组器/解组器中的数据,但两者的来源都是相同的 JAXB 上下文?
更新:从来没有想出一个简单的方法来做到这一点。对于目前的框架来说,这实际上是不可能的。更新:不正确。扩展 AttachmentMarshaller (我非常喜欢这个并将使用它)或创建一个“需要感知”的 XmlAdapter 将适用于审计特定的编组器,正如@Blaise 在下面的回答。
更新:如果我可以进一步完善我的用例...我在上面提到,为了简化审计,我想对 JSONJAXBContext 使用 jersey api,特别是使用 JSONMarshaller 但接口未定义 setAdapter 和 setAttachmentMarshaller。来自 JSONJAXBContext.createJSONMarshaller() 是一个 JSONMarshallerImpl 实现确实定义了这些方法。我将不情愿地转换为 impl,以便我可以设置我的自定义附件编组器。
I am working in a JAXWS/JAXB web service environment. JAXWS out of the box uses uses the JAXB to marshal/unmarshaler the web service payloads.
I also have a requirement to audit all request and response payloads.
I want a compact and concise marshaled representation of the payload for the audit (as a irrelevant side note - I am auditing using a java.util.concurrent.BlockingQueue and some consumer threads to put batches of audit data in the audit datasource).
I have binary content(mtom) included on some web service response payloads but I DO NOT want to marshal audit these because the serialized base64 would be too large.
So my need is to create a marshaller (exclusively for auditng) that in all cases will scrub binary content but then NOT scrub for the prime purpose of marshalling web service response payloads. I do XSD to Java xjc. I need to use the same XSD/JAXB namespace for both contexts/marshallers.
Java type converter:
<jxb:javaType name=""
parseMethod="com.xxx.xxx.ws.converter.XXXLongConverter.parseXXXLong"
printMethod="com.xxx.xxx.ws.converter.XXXLongConverter.printXXXLong" />
is will not work because 1. I would need to unregister the adapter http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html#setAdapter%28java.lang.Class,%20A%29
for the marshaller and I don't THINK I have a hook into that for JAXWS. 2. I can't be guaranteed the class name that JAXB will decide to create in order to unregister it.
I created my own XMLAdapter and used the annox jaxb plugin
but that didn't really work for the same reasons the above didn't work.
Update: I now tried manually and reflectively walking through payload(to be audited) prior to marshalling to scrub the binary data but that got to be too much pain for what it was worth.
I should also mention that for brevity of the audit I am using jersey JSON serialization supporting JAXB
but I don't think that takes away or adds to my base problem:
How can I scrub data in one marshaller/unmarshaller but not another but both whose origin is the same JAXB context?
UPDATE: Never figured out an elegate way to do this. Not really possible at this point with the frameworks as they are. UPDATE: Not true. Extending AttachmentMarshaller (I like this a lot and will use it) or creating a "need-aware" XmlAdapter would work for the audit specific marshaller as @Blaise answers below.
UPDATE: If I may take this a step further to round out my use case...I mentioned above that for brevity of the audit I'd like to do Json Serialization of the JSONJAXBContext using jersey apis, specifically using the JSONMarshaller but the interface does not define setAdapter and setAttachmentMarshaller. Coming out of JSONJAXBContext.createJSONMarshaller() is a JSONMarshallerImpl implementation which do define these this methods. I will grudgingly cast to impl so I can set my custom attachment marshaller.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以设置自己的
AttachemntMarshaller
实现,并将其设置在您用于审核的Marshaller
上。Root
下面是一个具有
byte[]
属性的示例域对象,默认情况下该属性将表示为base64Binary
类型的元素。演示
下面的演示代码首先将对象编组为 XML,然后使用
AttachmentMarshaller
集的自定义实现对其进行第二次编组。输出
下面是运行演示代码的输出。如果 byte[] 很大,第一个 XML 文档可能会变得相当大。第二个 XML 文档将保持相同的大小。
You could set your own implementation of
AttachemntMarshaller
and set it on theMarshaller
that you are using for auditing.Root
Below is a sample domain object with a
byte[]
property that by default will be represented as an element of typebase64Binary
.Demo
The demo code below first marshals the object to XML, and then marshals it a second time with a custom impplementation of
AttachmentMarshaller
set.Output
Below is the output from running the demo code. The first XML document could grow to be quite large if the byte[] was big. The second XML document would stay the same size.
您可以使用
XmlAdapter
支持此用例。XmlAdapter (ByteArrayAdapter)
下面的
XmlAdapter
用于将byte[]
转换为byte[]
。在默认状态下,它将返回原始的byte[]
,它还有一个审核状态,它将返回一个空的byte[]。package-info
@XmlJavaTypeAdapter
注释用于注册XmlAdapter
。在包级别使用时,它将应用于该包中指定类型的所有属性(请参阅:http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html)。Root
下面是一个具有 byte[] 属性的示例域对象,默认情况下该属性将表示为 base64Binary 类型的元素。
演示
下面的演示代码首先使用
ByteArrayAdapter
的默认状态来编组对象,该状态将返回真实的byte[]
并编组对象第二次使用有状态的ByteArrayAdapter
集,它将所有byte[]
值转换为空的byte[]
。输出
下面是运行演示代码的输出。
XmlAdapter
将应用于byte[]
类型的所有映射字段/属性。You could support this use case with an
XmlAdapter
.XmlAdapter (ByteArrayAdapter)
The following
XmlAdapter
is used to convert abyte[]
to abyte[]
. In its default state it will return the originalbyte[]
, it also has a audit state where it will return an empty byte[].package-info
The
@XmlJavaTypeAdapter
annotation is used tp register theXmlAdapter
. When used at the package level it will apply to all properties of the specified type in that package (see: http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html).Root
Below is a sample domain object with a byte[] property that by default will be represented as an element of type base64Binary.
Demo
The demo code below first marshals the object with the default state of the
ByteArrayAdapter
which will return the realbyte[]
and the marshals the object a second time with a statefulByteArrayAdapter
set which will convert allbyte[]
values to an emptybyte[]
.Output
Below is the output from running the demo code. The
XmlAdapter
would apply to all mapped fields/properties of typebyte[]
.