It is indeed possible to compose complex XContent by implementing helper 
methods and delegating construction to them as you propose. Indeed this is a 
common pattern within the Elasticsearch code itself. 

The basic idea is that you pass your XContentBuilder to your helper methods 
which return a reference to the same builder after mutating it in some fashion. 
Just design your helper classes to have methods with this signature: @Override 
public XContentBuilder toXContent(XContentBuilder builder, Params params) 
throws IOException.

Then you can simply delegate to your helper classes by passing your builder 
reference down to their toXContent() methods. For a real-world example see: 
https://github.com/elasticsearch/elasticsearch/blob/master/src/main/java/org/elasticsearch/action/admin/indices/recovery/RecoveryResponse.java#L91

Hope that helps.

On Mar 28, 2014, at 4:32 PM, Jacob Stultz <[email protected]> wrote:

> Thanks, appreciate the quick response and I'll just move forward with using 
> XContentBuilder then.
> 
> I do want to be clear that my intent was not to "bypass" the ES API, but 
> rather I was thinking that it would be very useful for things like mappings, 
> where the structure and content is well defined by ElasticSearch and there 
> are rules determining whether a mapping is valid or invalid beyond just JSON 
> syntax (unlike documents, for example), to have a stronger interface for 
> creating them on the client side, even if it would just get serialized into 
> the same JSON for transport to the server. Given that there are already 
> classes written for the server that represent mappings and fields, and are 
> readily serializable to JSON, giving JVM clients the ability to leverage 
> these would be very useful.
> 
> One followup question, regarding XContentBuilder. I'd like to be able to 
> define some simple helper classes for defining field mappings with common 
> configurations within my project. It's not clear how to cleanly delegate 
> construction of substructures to other methods or classes. I would love to be 
> able to do something like the following (in Scala)
> 
> XContentFactory.jsonBuilder()
>   .startObject
>     .startObject("properties")
>       .field("subject", stringField(store = true))
>       .field("content", stringField())
>     .endObject
>   .endObject
> 
> where stringField is something that I implement. It would be ideal if that 
> just returned an XContentBuilder as well, and there were a version of the 
> field method that would accept that (in addition to the ones that accept a 
> String, Double, Map, etc). However, it doesn't appear that it does, and I'm 
> at a loss to figure out a way to use XContentBuilder to build smaller pieces 
> that are then later composed into a larger whole. Is the only option to 
> either generate Map objects for the substructures, or rely on mutation along 
> these lines:
> 
> val mapping = XContentFactory.jsonBuilder()
>   .startObject
>     .startObject("properties")
> 
> addStringField(mapping, "subject", store = true)
> addStringField(mapping, "content)
> 
> mapping.endObject.endObject
> 
> 
> On Fri, Mar 28, 2014 at 3:45 PM, [email protected] 
> <[email protected]> wrote:
> The DocumentMapper is located at server side or in a plugin when the request 
> of a client is processed. It is not possible to use it by clients to bypass 
> the ES API. The communication to the nodes that receive document mapper 
> requests is very low level and beyond the ES API  - see the transport shard 
> actions. 
> 
> In ES, the XContent universal helper classes wrap all possible formats, like 
> SMILE or YAML, on the ES API and for internal transmissions too. Compressed 
> JSON is used for data transmission. Unless exceptions, no Java object 
> serialization is used.
> 
> In my eyes it is one of the strengths of XContent to construct arbitrary 
> JSON-like object/array streams without a schema. You don't have to care about 
> JSON strings at all. It is a natural fluent API that helps a lot in writing 
> correct code (if your IDE uses code completion).
> 
> The alternative would be a static approach where every action class would 
> carry its own parameterization and serialization scheme. This is one area 
> where ES really shines - it has a dynamic parameterization, XContent can 
> drive new actions and existent actions as well. The price is missing 
> validation at code writing time, but I don't miss such a thing.
> 
> Jörg
> 
> 
> On Fri, Mar 28, 2014 at 10:20 PM, Jacob Stultz <[email protected]> wrote:
> I'm wondering how feasible it is to use some of the Java classes defined by 
> Elasticsearch on the client side, rather than building up JSON strings or 
> XContentBuilder instances manually. Specifically, I'm wondering about 
> creating mappings. It would be really nice if I could create a DocumentMapper 
> instance (which implements ToXContent) to define a mapping, and then use that 
> to create an XContentBuilder to pass to setSource on PutMappingRequestBuilder.
> 
> This would be great, since it would rely on existing types to ensure that 
> valid mappings are created, rather than leaving open the possibility of 
> incorrectly constructing JSON (either via typos or incorrect field names, or 
> just incorrect structure).
> 
> However, I'm having trouble figuring out whether this is possible or 
> intended; it seems to create a DocumentMapper instance, I'd need a 
> DocumentMapper.Builder instance, which requires a DocumentMapperParser 
> instance to build the DocumentMapper, and the DocumentMapperParser instance 
> in turn requires a number of other objects not readily available.
> 
> Am I basically stuck with writing my own code to generate these JSON 
> structures? If so, it'd be really nice in the future if the Java API would 
> leverage the fact that much of the code is already used on the server side, 
> and make those classes easily available for clients to leverage static typing 
> to help ensure correctness.
> 
> Thanks.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "elasticsearch" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> 
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elasticsearch/8cbf0f15-a5d2-4dda-9759-ede3505ca08e%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
> 
> 
> -- 
> You received this message because you are subscribed to a topic in the Google 
> Groups "elasticsearch" group.
> To unsubscribe from this topic, visit 
> https://groups.google.com/d/topic/elasticsearch/k-PoX-iCIeg/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to 
> [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elasticsearch/CAKdsXoFD%3DoSJTL2Uzw%2B5Acwm9Lrdk6VueM-%2BRJj%3DPu2zX9zH0w%40mail.gmail.com.
> 
> For more options, visit https://groups.google.com/d/optout.
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "elasticsearch" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/elasticsearch/CAP3WdZGCzsFxRvnZoe9Q2451%2BdAJD-aJvzVoARs%2BtuhgAh5x%3DQ%40mail.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"elasticsearch" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elasticsearch/E0A23F5C-3DCA-4E71-8878-F8EF4EBECE85%40elasticsearch.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to