From 7acd5847f71a6f65d1303cce9dce61f2f91aa5b6 Mon Sep 17 00:00:00 2001 From: sammefford Date: Tue, 18 Nov 2014 13:59:43 -0700 Subject: [PATCH 1/6] updating version --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 03b11392f..b8c083da7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,11 +4,11 @@ com.marklogic client-api-java jar - 3.0-SNAPSHOT + 3.0.0-EA3 client-api-java http://developer.marklogic.com - ${project.name} 2.0 ${maven.build.timestamp} + ${project.name} 3.0.0 yyyy-MM-dd UTF-8 github From 6b938ae1afd376cf09f71810942394bff1c73b10 Mon Sep 17 00:00:00 2001 From: sammefford Date: Fri, 21 Nov 2014 11:09:14 -0700 Subject: [PATCH 2/6] more javadocs --- .../com/marklogic/client/eval/EvalResult.java | 45 ++++ .../client/eval/EvalResultIterator.java | 3 + .../client/eval/ServerEvaluationCall.java | 170 +++++++++++- .../marklogic/client/pojo/PojoRepository.java | 244 ++++++++++++++++-- 4 files changed, 434 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/marklogic/client/eval/EvalResult.java b/src/main/java/com/marklogic/client/eval/EvalResult.java index 509c1d7d4..dc78221bf 100644 --- a/src/main/java/com/marklogic/client/eval/EvalResult.java +++ b/src/main/java/com/marklogic/client/eval/EvalResult.java @@ -18,7 +18,18 @@ import com.marklogic.client.io.Format; import com.marklogic.client.io.marker.AbstractReadHandle; +/** Represents the content and metadata of a result from a call to + * {@link ServerEvaluationCall#eval() eval}. + * Also includes some convenience methods for deserializing the result + * as a String, Number, Boolean, AbstractReadHandle, or an object of + * any Class which is registered by a ContentHandle. + */ public interface EvalResult { + /** Convenience enum useful for strongly-typed comparison to ensure + * the result is of the type expected. This list captures most of + * the types expected from the X-Primitive header. + * @see REST GUIDE -> eval endpoint + */ enum Type { XML, JSON, STRING, BOOLEAN, NULL, OTHER, @@ -26,11 +37,45 @@ enum Type { FLOAT, GDAY, GMONTH, GMONTHDAY, GYEAR, GYEARMONTH, HEXBINARY, INTEGER, QNAME, TIME, ATTRIBUTE, BINARY, COMMENT, PROCESSINGINSTRUCTION, TEXTNODE }; + /** The {@link Type} of this result from the X-Primitive header + * provided by the REST API eval endpoint. + * @see REST GUIDE -> eval endpoint + * @return the type of this result + */ public Type getType(); + + /** The format of this result from the Content-Type header + * provided by the REST API eval endpoint. + * @see REST GUIDE -> eval endpoint + * @return the format of this result + */ public Format getFormat(); + + /** Use a handle to retrieve the contents of this result. + * @param handle the handle to populate with the contents of this result + * @return the handle populated with the contents of this result + */ public H get(H handle); + + /** An io shortcut method to get the contents as an object + * of the specified type, which must be a registered type. + * @param clazz the Class (type). This type must be registered by an io handle. + * @return an instance of the requested type populated with the contents of this result + */ public T getAs(Class clazz); + + /** This result directly as a string. + * @return this result as a string + */ public String getString(); + + /** This result parsed to a Number. + * @return this result as a number + */ public Number getNumber(); + + /** This result parsed to a Boolean. + * @return a boolean as generated by new Boolean({@link #getString getString()}) + */ public Boolean getBoolean(); } diff --git a/src/main/java/com/marklogic/client/eval/EvalResultIterator.java b/src/main/java/com/marklogic/client/eval/EvalResultIterator.java index ac058d050..761bc53b0 100644 --- a/src/main/java/com/marklogic/client/eval/EvalResultIterator.java +++ b/src/main/java/com/marklogic/client/eval/EvalResultIterator.java @@ -17,6 +17,9 @@ import java.util.Iterator; +/** An Iterator to walk through all results returned from calls to + * {@link ServerEvaluationCall#eval()}. + */ public interface EvalResultIterator extends Iterable, Iterator { public Iterator iterator(); public boolean hasNext(); diff --git a/src/main/java/com/marklogic/client/eval/ServerEvaluationCall.java b/src/main/java/com/marklogic/client/eval/ServerEvaluationCall.java index 2747361bf..47539b70f 100644 --- a/src/main/java/com/marklogic/client/eval/ServerEvaluationCall.java +++ b/src/main/java/com/marklogic/client/eval/ServerEvaluationCall.java @@ -15,6 +15,7 @@ */ package com.marklogic.client.eval; +import com.marklogic.client.DatabaseClientFactory; import com.marklogic.client.FailedRequestException; import com.marklogic.client.ForbiddenUserException; import com.marklogic.client.Transaction; @@ -23,26 +24,189 @@ import com.marklogic.client.io.marker.TextWriteHandle; import com.marklogic.client.util.EditableNamespaceContext; +/** + * ServerEvaluationCall uses a fluent builder-style API to collect the parameters + * for a server-side {@link #xquery xquery} or {@link #javascript javascript} eval or + * invoke ({@link #modulePath modulePath}) call. ServerEvaluationCall also + * conveniently has the eval* methods which execute those calls and return the + * results. You must call one and only one of the following methods: xquery, + * javascript, or modulePath. The xquery + * and javascript methods initialize this call for server-side eval and accept + * source code as a String or a TextWriteHandle (in case you are streaming the + * source code from the file system, a URL, or other source that is most easily + * accessed via io handles). The modulePath method initializes this call for server- + * side invoke given the path to a module previously installed on the server. + * + * Here is a simple "hello world" junit example:
{@code
+ *String javascript = "'hello world'";
+ *String response = client.newServerEval()
+ *    .javascript(javascript)
+ *    .evalAs(String.class);
+ *assertEquals("hello world", response);
+ *}
+ * or in xquery:
{@code
+ *String xquery = "'hello world'";
+ *String response = client.newServerEval()
+ *    .xquery(xquery)
+ *    .evalAs(String.class);
+ *assertEquals("hello world", response);
+ *}
+ * + * Variables can be added with the addVariable methods. + * {@link #addVariable(String, AbstractWriteHandle) addVariable(String, AbstractWriteHandle)} + * allows you to pass complex JSON or XML values directly from io handles. + * {@link #addVariableAs(String, Object) addVariableAs(String, Object)} + * follows the + * shortcut pattern which maps objects by type to the appropriate handle. + * For simpler atomic values, convenience addVariable methods are provided for + * String, Number, and Boolean types. + * + * Here is a simple "hello solar system" example with a variable:
{@code
+ *String javascript = "var planet;'hello solar system from ' + planet";
+ *String response = client.newServerEval()
+ *    .javascript(javascript)
+ *    .addVariable("planet", "Mars)
+ *    .evalAs(String.class);
+ *assertEquals( "hello solar system from Mars", response);
+ *}
+ * or in xquery:
{@code
+ *String xquery = "declare variable $planet external;'hello solar system from ' || $planet";
+ *String response = client.newServerEval()
+ *    .xquery(xquery)
+ *    .addVariable("planet", "Mars)
+ *    .evalAs(String.class);
+ *assertEquals( "hello solar system from Mars", response);
+ * }
+ * + * Each call can be executed within a {@link #transaction transaction}, within a + * {@link DatabaseClientFactory#newClient(String, int, String) particular database}, + * and with particular {@link #namespaceContext namespaces} available for expansion + * of prefixed variable names. + * + * Each call can be executed with only one expected response of a particular + * {@link #evalAs type} or {@link #eval(AbstractReadHandle) handle type}. Or calls can be executed + * with {@link #eval() multiple responses expected}. + */ public interface ServerEvaluationCall { + /** Initialize this server-side eval with xquery-syntax source code. + * @param xquery the xquery-syntax source code to eval on the server + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall xquery(String xquery); + + /** Initialize this server-side eval with xquery-syntax source code. + * @param xquery a handle containing the xquery-syntax source code to eval on the server + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall xquery(TextWriteHandle xquery); + + /** Initialize this server-side eval with javascript-syntax source code. + * @param javascript the javascript-syntax source code to eval on the server + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall javascript(String javascript); - public ServerEvaluationCall javascript(TextWriteHandle xquery); + + /** Initialize this server-side eval call with javascript-syntax source code. + * @param javascript a handle containing the javascript-syntax source code to eval on the server + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ + public ServerEvaluationCall javascript(TextWriteHandle javascript); + + /** Initialize this server-side invoke call with a path to the module to invoke. + * @param modulePath a path to a module previously installed in the server + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall modulePath(String modulePath); + + /** Set a variable name-value pair to pass to the code executing server-side. + * @param name the variable name, including a namespace prefix if the prefix is + * mapped to a uri in the {@link #namespaceContext namespace context} + * @param value the atomic variable value + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall addVariable(String name, String value); + + /** Set a variable name-value pair to pass to the code executing server-side. + * @param name the variable name, including a namespace prefix if the prefix is + * mapped to a uri in the {@link #namespaceContext namespace context} + * @param value the atomic variable value + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall addVariable(String name, Number value); + + /** Set a variable name-value pair to pass to the code executing server-side. + * @param name the variable name, including a namespace prefix if the prefix is + * mapped to a uri in the {@link #namespaceContext namespace context} + * @param value the atomic variable value + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall addVariable(String name, Boolean value); + + /** Set a variable name-value pair to pass to the code executing server-side. + * @param name the variable name, including a namespace prefix if the prefix is + * mapped to a uri in the {@link #namespaceContext namespace context} + * @param value the handle containing the variable value, most likely XML or JSON + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall addVariable(String name, AbstractWriteHandle value); - /** Like other *As convenience methods throughout the API, the Object value - * is managed by the Handle registered for that Class. */ + + /** Convenience method to set a variable of a type mapped to an io handle. Like other + * + * *As convenience methods throughout the API, the Object value + * is provided by the handle registered for that Class. + * + * @param name the variable name, including a namespace prefix if the prefix is + * mapped to a uri in the {@link #namespaceContext namespace context} + * @param value the handle containing the variable value + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall addVariableAs(String name, Object value); + + /** Initialize this call with a transaction under which server-side execution should occur. + * @param transaction the open transaction under which to run this call in the server + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall transaction(Transaction transaction); + + /** Add a single namespace prefix-to-uri mapping to the namespace context. + * @param prefix the prefix for this mapping + * @param namespaceURI the uri for this mapping + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall addNamespace(String prefix, String namespaceURI); + + /** Initialize this call with namespaces so variables with prefixes can be sent with + * their prefixes translated to uris that will match the uris in the code to be + * executed on the server. + * @param namespaces a namespace context specifying the mapping from prefixes to namespaces + * @return a reference to this ServerEvaluationCall instance for use as a fluent-style builder + */ public ServerEvaluationCall namespaceContext(EditableNamespaceContext namespaces); + + /** Conveneince method to get the response serialized to a particular type by an io handle. + * Like other + * *As convenience methods throughout the API, the return value + * is provided by the handle registered for the provided responseType. + * + * @param responseType the type desired for the response. Must be a Class regiestered + * to a handle. + * @return the result deserialized by the implicit handle mapped to this responseType + */ public T evalAs(Class responseType) throws ForbiddenUserException, FailedRequestException; + + /** Provides the single result of the server-side eval or invoke call, wrapped in an io + * handle. + * @param responseHandle the type of handle appropriate for the expected single result + * @return the handle which wraps the response + */ public H eval(H responseHandle) throws ForbiddenUserException, FailedRequestException; + + /** Provides all results returned by the server-side eval or invoke call. + * @return an EvalResultIterator which provides access to all the results returned by + * the server-side eval or invoke call. + */ public EvalResultIterator eval() throws ForbiddenUserException, FailedRequestException; } diff --git a/src/main/java/com/marklogic/client/pojo/PojoRepository.java b/src/main/java/com/marklogic/client/pojo/PojoRepository.java index 3233f7bb6..89ab5be08 100644 --- a/src/main/java/com/marklogic/client/pojo/PojoRepository.java +++ b/src/main/java/com/marklogic/client/pojo/PojoRepository.java @@ -20,6 +20,8 @@ import com.marklogic.client.ResourceNotFoundException; import com.marklogic.client.Transaction; import com.marklogic.client.io.marker.SearchReadHandle; +import com.marklogic.client.pojo.annotation.Id; +import com.marklogic.client.query.QueryManager; import java.io.Serializable; @@ -43,7 +45,7 @@ * * Where MyClass is your custom pojo type, and myId is the bean property of type Integer * marked with the - * {@literal @}{@link com.marklogic.client.pojo.annotation.Id Id annotation}. The + * {@literal @}{@link Id Id annotation}. The * {@literal @}Id annotaiton can be attached to a public field or a public getter or a * public setter. The bean property marked with {@literal @}Id must be a native type or * {@link java.io.Serializable} class and must contain an @@ -78,66 +80,117 @@ public interface PojoRepository { /** Write this instance to the database. Uses the field marked with {@literal @}Id * annotation to generate a unique uri for the document. Adds a collection with the * fully qualified class name. Uses a particular configuration of - * {@link com.fasterxml.jackson.databind.ObjectMapper ObjectMapper} to generate the - * serialized JSON format. + * {@link com.fasterxml.jackson.databind.ObjectMapper ObjectMapper} to generate the + * serialized JSON format. + * @param entity your pojo instance of the type managed by this PojoRepository */ public void write(T entity) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; /** Does everything in {@link #write(Object) write(T)} but also adds your collections to the * persisted instance. + * @param entity your pojo instance of the type managed by this PojoRepository + * @param collections the collections to add to this instance in the database */ public void write(T entity, String... collections) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; /** Does everything in {@link #write(Object) write(T)} but in your * * multi-statement transaction context. + * @param entity your pojo instance of the type managed by this PojoRepository + * @param transaction the open transaction in which to write this instance */ public void write(T entity, Transaction transaction) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; - /** Does everything in {@link #write(Object) write(T)} but also adds your collections to the - * persisted instance and performs the write in your + /** Does everything in {@link #write(Object) write(T)} but also adds your + * collections to the persisted instance and performs the write in your * * multi-statement transaction context. * . + * @param entity your pojo instance of the type managed by this PojoRepository + * @param transaction the open transaction in which to write this instance + * @param collections the collections to add to this instance in the database */ public void write(T entity, Transaction transaction, String... collections) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; - /** @return true if a document exists in the database with the id */ + /** True if a document exists in the database with the specified id + * @param id the unique identifier of the pojo (the value of the field annotated with + * {@literal @}{@link Id Id}) + * @return true if a document exists in the database with the specified id + */ public boolean exists(ID id) throws ForbiddenUserException, FailedRequestException; - /** @return in the context of transaction, true if a document exists in the database with - * the id */ + /** True if in the context of transaction, a document exists in the database with + * the specified id + * @param id the unique identifier of the pojo (the value of the field annotated with + * {@literal @}{@link Id Id}) + * @param transaction the transaction in which this exists check is participating + * (Will open a read lock on the document. The read lock is released when the + * transaction is committed or rolled back.) + * @return true if in the context of transaction, a document exists in the database + * with the specified id + */ public boolean exists(ID id, Transaction transaction) throws ForbiddenUserException, FailedRequestException; - /** @return the number of documents of type T persisted in the database */ + /** The number of documents of the type managed by this PojoRepository persisted + * in the database + * @return The number of documents of the type + * managed by this PojoRepository persisted in the database + */ public long count() throws ForbiddenUserException, FailedRequestException; - /** @return in the context of transaction, the number of documents of type T persisted in - * the database */ + /** In the context of transaction, the number of documents of the type managed by + * this PojoRepository persisted in the database + * @param transaction the transaction in which this count is participating + * (Will open a read lock on all matched documents. The read lock is released when the + * transaction is committed or rolled back.) + * @return in the context of transaction, the number of documents of the type managed + * by this PojoRepository persisted in the database + */ public long count(Transaction transaction) throws ForbiddenUserException, FailedRequestException; - /** @return the number of documents of type T persisted in the database with at least - * one of the criteria collections*/ - public long count(String... collection) + /** The number of documents of the type managed by this PojoRepository persisted in + * the database with at least one of the criteria collections + * @param collections matches must belong to at least one of the specified collections + * @return the number of documents of the type managed + * by this PojoRepository persisted in the database with at least one of the + * criteria collections + */ + public long count(String... collections) throws ForbiddenUserException, FailedRequestException; - /** @return in the context of transaction, the number of documents of type T persisted in - * the database with at least one of the criteria collections*/ + /** In the context of transaction, the number of documents of the type managed by + * this PojoRepository persisted in the database with at least one of the criteria + * collections + * @param collections matches must belong to at least one of the specified collections + * @param transaction the transaction in which this count is participating + * (Will open a read lock on all matched documents. The read lock is released when the + * transaction is committed or rolled back.) + * @return in the context of transaction, the number of documents of the type managed + * by this PojoRepository persisted in the database with at least one of the + * criteria collections + */ public long count(String[] collections, Transaction transaction) throws ForbiddenUserException, FailedRequestException; - /** @return the number of documents of type T persisted in the database which match + /** @return the number of documents of the type managed by this PojoRepository persisted in the database which match * the query */ public long count(PojoQueryDefinition query) throws ForbiddenUserException, FailedRequestException; - /** @return in the context of transaction, the number of documents of type T persisted in the - * database which match the query */ + /** In the context of transaction, the number of documents of the type managed by + * this PojoRepository persisted in the database which match the query + * @param query the query which results much match (queries are run unfiltered by default) + * @param transaction the transaction in which this count is participating + * (Will open a read lock on all matched documents. The read lock is released when the + * transaction is committed or rolled back.) + * @return in the context of transaction, the number of documents of the type managed + * by this PojoRepository persisted in the database which match the query + */ public long count(PojoQueryDefinition query, Transaction transaction) throws ForbiddenUserException, FailedRequestException; @@ -149,11 +202,11 @@ public void delete(ID... ids) public void delete(ID[] ids, Transaction transaction) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; - /** Deletes from the database all documents of type T persisted by the pojo facade */ + /** Deletes from the database all documents of the type managed by this PojoRepositoryof type T persisted by the pojo facade */ public void deleteAll() throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; - /** As part of transaction, deletes from the database all documents of type T persisted by + /** As part of transaction, deletes from the database all documents of the type managed by this PojoRepositoryof type T persisted by * the pojo facade */ public void deleteAll(Transaction transaction) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; @@ -162,35 +215,176 @@ public void deleteAll(Transaction transaction) public void deleteAll(String... collections) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; */ - + + /** Read one persisted pojo by id and unmarshall its data into a new pojo instance. + * @param id the unique identifier of the pojo (the value of the field annotated with + * {@literal @}{@link Id Id}) + * @return an instance of the correct type populated with the persisted data + * from the database + */ public T read(ID id) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; + /** Within an open transaction, read one persisted pojo by id and unmarshall its data + * into a new pojo instance. + * @param id the unique identifier of the pojo (the value of the field annotated with + * {@literal @}{@link Id Id}) + * @param transaction the transaction in which this read is participating + * (will open a read lock on each document matched that is released when the + * transaction is committed or rolled back) + * @return an instance of the correct type populated with the persisted data + * from the database + */ public T read(ID id, Transaction transaction) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; + /** Read multiple persisted pojos by id and unmarshall their data into new pojo instances. + * If at least one instance is found but others are not, ignores the instances not found. + * While this returns a PojoPage, the PageSize will match the number of instances found, + * and will ignore getPageLength(). To paginate, send a smaller set of ids at a time. + * @param ids the unique identifiers of the pojos (the values of the field annotated with + * {@literal @}{@link Id Id}) + * @return a set of instances of the correct type populated with the persisted data. + * Since this call produces a finite set, only one page is returned and therefore + * PojoPage pagination methods will not be helpful as they would be from calls to search. + */ public PojoPage read(ID[] ids) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; + /** Within an open transaction, + * read one page of persisted pojos and unmarshall their data into new pojo instances. + * If at least one instance is found but others are not, ignores the instances not found. + * While this returns a PojoPage, the PageSize will match the number of instances found, + * and will ignore getPageLength(). To paginate, send a smaller set of ids at a time. + * @param ids the unique identifiers of the pojos (the values of the field annotated with + * {@literal @}{@link Id Id}) + * @param transaction the transaction in which this read is participating + * (will open a read lock on each document matched that is released when the + * transaction is committed or rolled back) + * @return a page of instances of the correct type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned just like calls to {@link #search(PojoQueryDefinition, long) search} + */ public PojoPage read(ID[] ids, Transaction transaction) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; - public PojoPage readAll(long start) + /** Read one page of persisted pojos of the type managed by this + * PojoRepository and unmarshall their data into new pojo instances. + * @param start the offset of the first document in the page (where 1 is the first result) + * @return a page with a maximum of {@link #getPageLength()} instances of the correct + * type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned just like calls to {@link #search(PojoQueryDefinition, long) search}. + */ public PojoPage readAll(long start) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; + /** Within an open transaction, read one page of persisted pojos of the type managed by this + * PojoRepository and unmarshall their data into new pojo instances. + * @param start the offset of the first document in the page (where 1 is the first result) + * @param transaction the transaction in which this read is participating + * (Will open a read lock on each document matched. The read lock is released when the + * transaction is committed or rolled back.) + * @return a page with a maximum of {@link #getPageLength()} instances of the correct + * type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned just like calls to {@link #search(PojoQueryDefinition, long) search}. + */ public PojoPage readAll(long start, Transaction transaction) throws ResourceNotFoundException, ForbiddenUserException, FailedRequestException; - + + /** Find all persisted pojos of the type managed by this + * PojoRepository also in one of the specified collections and unmarshall their data + * into new pojo instances. + * @param start the offset of the first document in the page (where 1 is the first result) + * @param collections matches must belong to at least one of the specified collections + * @return a page with a maximum of {@link #getPageLength()} instances of the correct + * type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned and the total estimated number of results is available from + * {@link PojoPage#getTotalSize() PojoPage.getTotalSize()}. + */ public PojoPage search(long start, String... collections) throws ForbiddenUserException, FailedRequestException; + /** Within an open transaction, find all persisted pojos of the type managed by this + * PojoRepository also in one of the specified collections and unmarshall their data + * into new pojo instances. + * @param start the offset of the first document in the page (where 1 is the first result) + * @param transaction the transaction in which this search is participating + * (Will open a read lock on each document matched. The read lock is released when the + * transaction is committed or rolled back.) + * @param collections matches must belong to at least one of the specified collections + * @return a page with a maximum of {@link #getPageLength()} instances of the correct + * type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned and the total estimated number of results is available from + * {@link PojoPage#getTotalSize() PojoPage.getTotalSize()}. + */ public PojoPage search(long start, Transaction transaction, String... collections) throws ForbiddenUserException, FailedRequestException; + /** Within an open transaction, search persisted pojos of the type managed by this + * PojoRepository for matches to this query and unmarshall their data into new pojo instances. + * If matches are returned which do not meet all the criteria, you may need to create + * appropriate indexes in the server to run your query unfiltered or run your query filtered by + * wrapping your query with {@link PojoQueryBuilder#filteredQuery filteredQuery}. + * @param query the query which results much match (queries are run unfiltered by default) + * @param start the offset of the first document in the page (where 1 is the first result) + * @return a page with a maximum of {@link #getPageLength()} instances of the correct + * type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned and the total estimated number of results is available from + * {@link PojoPage#getTotalSize() PojoPage.getTotalSize()}. + */ public PojoPage search(PojoQueryDefinition query, long start) throws ForbiddenUserException, FailedRequestException; + /** Within an open transaction, search persisted pojos of the type managed by this + * PojoRepository for matches to this query and unmarshall their data into new pojo instances. + * If matches are returned which do not meet all the criteria, you may need to create + * appropriate indexes in the server to run your query unfiltered or run your query filtered by + * wrapping your query with {@link PojoQueryBuilder#filteredQuery filteredQuery}. + * @param query the query which results much match (queries are run unfiltered by default) + * @param start the offset of the first document in the page (where 1 is the first result) + * @param transaction the transaction in which this search is participating + * (Will open a read lock on each document matched. The read lock is released when the + * transaction is committed or rolled back.) + * @return a page with a maximum of {@link #getPageLength()} instances of the correct + * type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned and the total estimated number of results is available from + * {@link PojoPage#getTotalSize() PojoPage.getTotalSize()}. + */ public PojoPage search(PojoQueryDefinition query, long start, Transaction transaction) throws ForbiddenUserException, FailedRequestException; public PojoPage search(PojoQueryDefinition query, long start, SearchReadHandle searchHandle) throws ForbiddenUserException, FailedRequestException; + /** Within an open transaction, search persisted pojos of the type managed by this + * PojoRepository for matches to this query and unmarshall their data into new pojo instances. + * If matches are returned which do not meet all the criteria, you may need to create + * appropriate indexes in the server to run your query unfiltered or run your query filtered by + * wrapping your query with {@link PojoQueryBuilder#filteredQuery filteredQuery}. + * @param query the query which results much match (queries are run unfiltered by default) + * @param start the offset of the first document in the page (where 1 is the first result) + * @param searchHandle the handle to populate with a search results payload equivalent to + * one returned by + * {@link QueryManager#search(QueryDefinition, SearchReadHandle, long, Transaction) + * QueryManager.search} + * @param transaction the transaction in which this search is participating + * (Will open a read lock on each document matched. The read lock is released when the + * transaction is committed or rolled back.) + * @return a page with a maximum of {@link #getPageLength()} instances of the correct + * type populated with the persisted data. + * Since this call may match a large set, only one page of {@link #getPageLength()} + * is returned and the total estimated number of results is available from + * {@link PojoPage#getTotalSize() PojoPage.getTotalSize()}. + */ public PojoPage search(PojoQueryDefinition query, long start, SearchReadHandle searchHandle, Transaction transaction) throws ForbiddenUserException, FailedRequestException; + /** Get a PojoQueryBuilder for the type managed by this PojoRepository. + * @return a PojoQueryBuilder for the type managed by this PojoRepository + */ public PojoQueryBuilder getQueryBuilder(); - public long getPageLength(); // default: 50 + /** The number of instances per page returned when calling {@link #readAll readAll} or + * {@link #search search} (Default: 50). + */ + public long getPageLength(); + /** Set the number of instances per page returned when calling {@link #readAll readAll} or + * {@link #search search}. + */ public void setPageLength(long length); } From 12ecdfd4f4c8206965aeb39c8416ea2dd5ec2843 Mon Sep 17 00:00:00 2001 From: sammefford Date: Fri, 21 Nov 2014 15:59:10 -0700 Subject: [PATCH 3/6] revert 7644654ca9011c67079517187abaabe18e225f3d because the server has decided to stop adding the trailing newline --- src/test/java/com/marklogic/client/test/AlertingTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/marklogic/client/test/AlertingTest.java b/src/test/java/com/marklogic/client/test/AlertingTest.java index a95781a02..5d1de3df7 100644 --- a/src/test/java/com/marklogic/client/test/AlertingTest.java +++ b/src/test/java/com/marklogic/client/test/AlertingTest.java @@ -309,7 +309,7 @@ public void testJSONRuleDefinitions() BytesHandle bHandle = ruleManager.readRule("javatestrule", new BytesHandle().withFormat(Format.JSON)); assertEquals( - "{\"rule\":{\"name\":\"javatestrule\", \"description\":\"rule to demonstrate REST alerting\", \"search\":{\"qtext\":[\"favorited:true\"], \"options\":{\"constraint\":[{\"name\":\"favorited\", \"value\":{\"element\":{\"ns\":\"\", \"name\":\"favorited\"}}}]}}, \"rule-metadata\":null}}\n", + "{\"rule\":{\"name\":\"javatestrule\", \"description\":\"rule to demonstrate REST alerting\", \"search\":{\"qtext\":[\"favorited:true\"], \"options\":{\"constraint\":[{\"name\":\"favorited\", \"value\":{\"element\":{\"ns\":\"\", \"name\":\"favorited\"}}}]}}, \"rule-metadata\":null}}", new String(bHandle.get())); ruleManager.delete("javatestrule"); From 65591dc8adaabde0f440bef136602c8d8fb9e8ed Mon Sep 17 00:00:00 2001 From: sammefford Date: Wed, 19 Nov 2014 12:03:20 -0700 Subject: [PATCH 4/6] fix #202--test was failing with maven (though not with eclipse). The problem is the test needed to be explicit about charset. --- .../java/com/marklogic/client/test/HandleAccessorTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/marklogic/client/test/HandleAccessorTest.java b/src/test/java/com/marklogic/client/test/HandleAccessorTest.java index 497b3cdfb..5971e3ed3 100644 --- a/src/test/java/com/marklogic/client/test/HandleAccessorTest.java +++ b/src/test/java/com/marklogic/client/test/HandleAccessorTest.java @@ -22,6 +22,7 @@ import java.io.StringReader; import java.net.URISyntaxException; import java.net.URL; +import java.nio.charset.Charset; import org.junit.Test; @@ -37,10 +38,11 @@ public void testContentAsString() throws URISyntaxException, IOException { // I'm purposely using a string with a non-ascii character to test // charset issues String hola = "¡Hola!"; + System.out.println("Default Java Charset: " + Charset.defaultCharset()); assertEquals("String content mismatch", hola, HandleAccessor.contentAsString(new StringHandle(hola))); assertEquals("byte[] content mismatch", hola, - HandleAccessor.contentAsString(new BytesHandle(hola.getBytes()))); + HandleAccessor.contentAsString(new BytesHandle(hola.getBytes("UTF-8")))); URL filePath = this.getClass().getClassLoader().getResource("hola.txt"); assertEquals("Reader content mismatch", hola, HandleAccessor.contentAsString(new ReaderHandle(new StringReader(hola)))); From d6e2c7e633a793860609b201b4a2d68c15924181 Mon Sep 17 00:00:00 2001 From: Sravan Kottam Date: Tue, 25 Nov 2014 14:44:31 -0800 Subject: [PATCH 5/6] updated git plugin version to 0.10 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b8c083da7..b38f1c1ac 100644 --- a/pom.xml +++ b/pom.xml @@ -138,7 +138,7 @@ com.github.github site-maven-plugin - 0.9 + 0.10 Maven artifacts for ${project.version} true From cb116ca9c74e51e9c692b34be8d1f95d3009deda Mon Sep 17 00:00:00 2001 From: Sam Mefford Date: Fri, 6 Feb 2015 16:57:49 -0700 Subject: [PATCH 6/6] finish #147 by adding info about verifying maven central jars using gpg; do #253 by adding maven and gradle examples; do #254 by adding what's new section --- README.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8384f6cdd..9cb2a84dc 100644 --- a/README.md +++ b/README.md @@ -14,25 +14,46 @@ The Java API supports the following core features of the MarkLogic database: * Execute ACID modifications so the change either succeeds or throws an exception. * Execute multi-statement transactions so changes to multiple documents succeed or fail together. +### What's New in Java Client API 3.0.1 + +* Pojo Façade - persist POJOs as JSON objects and use a simple API to query them with all the power + of MarkLogic's search engine +* Eval (and Invoke) - directly access MarkLogic's powerful server-side XQuery or JavaScript +* Bulk Read & Write - send and retrieve documents and metadata in batches for significant performance + improvements +* JSON - JacksonHandle, JacksonDatabindHandle, and JacksonParserHandle make wrangling JSON a pleasure +* JavaScript Extensions - develop production-ready server-side extensions using ready-to-go scaffolding + +For more details, please read this [deeper dive](http://developer.marklogic.com/features/java-client-api-2) + ### QuickStart -For people working with MarkLogic 8 EA +To use the API in your maven project, include the following in your pom.xml: - $ mvn test-compile - $ sh src/test/resources/boot-test.sh - $ mvn test + + com.marklogic + java-client-api + 3.0.1 + + +For gradle projects, include the following: + + dependencies { + compile group: 'com.marklogic', name: 'java-client-api', version: '3.0.1' + } + +Read [The Java API in Five Minutes](http://developer.marklogic.com/try/java/index) ### Learning More -The following resources introduce and document the Java API: +The following resources document the Java API: -* [The Java API in Five Minutes](http://developer.marklogic.com/try/java/index) * [Java Application Developer's Guide](http://docs.marklogic.com/guide/java) * [JavaDoc](http://docs.marklogic.com/javadoc/client/index.html) ### Installing -To use the Java API, either add a Maven dependency or download the jar and its dependencies: +To use the Java API, either add Maven or Gradle dependency as explained above or download the jar and its dependencies: http://developer.marklogic.com/products/java @@ -41,7 +62,19 @@ the developer license: https://developer.marklogic.com/free-developer -### Building +To obtain verified downloads signed with MarkLogic's PGP key, use maven tools or directly download +the .jar and .asc files from +[maven central](http://repo1.maven.org/maven2/com/marklogic/java-client-api/3.0.1/). MarkLogic's +pgp key ID is 48D4B86E and it is available from pgp.mit.edu by installing gnupg and running the command: + + $ gpg --keyserver pgp.mit.edu --recv-key 48D4B86E + +Files can be verified with the command: + + $ gpg java-client-api-3.0.1.jar.asc + + +### Building and Contributing You can build the API in the same way as any Maven project on git: @@ -52,5 +85,13 @@ You might want to skip the tests until you have configured a test database and R $ mvn package -Dmaven.test.skip=true +See [Contributing.md](Contributing.md) for more on contributing to this github project. + +### Running JUnit Tests + + $ mvn test-compile + $ sh src/test/resources/boot-test.sh + $ mvn test + ## Support The MarkLogic Java Client API is maintained by MarkLogic Engineering and distributed under the [Apache 2.0 license](https://github.com/marklogic/java-client-api/blob/master/LICENSE). It is designed for use in production applications with MarkLogic Server. Everyone is encouraged to file bug reports, feature requests, and pull requests through GitHub. This input is critical and will be carefully considered, but we can’t promise a specific resolution or timeframe for any request. In addition, MarkLogic provides technical support for [release tags](https://github.com/marklogic/java-client-api/releases) of the Java Client API to licensed customers under the terms outlined in the [Support Handbook](http://www.marklogic.com/files/Mark_Logic_Support_Handbook.pdf). For more information or to sign up for support, visit [help.marklogic.com](http://help.marklogic.com).