See: Description
Package | Description |
---|---|
com.marklogic.http |
XCC HTTP Support.
|
com.marklogic.io |
XCC IO Support.
|
com.marklogic.xcc |
XCC Core Public Interfaces.
|
com.marklogic.xcc.examples |
XCC Examples.
|
com.marklogic.xcc.exceptions |
XCC Exceptions.
|
com.marklogic.xcc.jndi |
XCC Java Naming and Directory Interface (JNDI)
Support.
|
com.marklogic.xcc.spi |
XCC Service Provider Interface Package.
|
com.marklogic.xcc.types |
XCC Type Definitions.
|
This is XCC, the MarkLogic XML Content Connector API. This interface varies significantly from the original MarkLogic connector solution, XDBC. One of the goals of the new API is to simplify the public interface to make it easier to understand and to use.
The XCC API has been designed so that client code will be easier to write, less error prone and more robust. With those goals in mind, the new public API intentionally doesn't use abstrations like "connection" or "statement". The new model is that of a session, or conversation, between client code and a contentbase.
The session metaphor is not only simpler and more natural, it makes it easier to hide implementation details. It also emphasizes that XCC is not like JDBC. Common JDBC usage patterns, such as pooling connections, are not appropriate with XCC.
The central metaphor used in XCC is the Session
interface. A Session
object is
the facade through which client code performs all interaction with
a contentbase.
Session
instances
encapsulate the location of a particular server, a contentbase on
that server and authentication credentials (user identity) for that
contentbase. A Session
also
holds dynamic state, but it is a lightweight object. It is OK to
create and release Session
objects
as needed. Do not expend effort to pool and reuse them, they are
not expensive to create.
Session
objects
are created by factory methods on a ContentSource
instance. A ContentSource
object statically defines where a content server (an instance of
MarkLogic Server) can be found.
At a minimum, a ContentSource
object identifies a MarkLogic XDBC Server (host and port). It may
also optionally hold default authentication credentials (user and
password) and/or a contentbase (database) identifier on that
server. There are several variations of the ContentSource.newSession()
factory method which take arguments to provide this Session
-specific
information or to override the defaults.
Like J2EE DataSource objects, a ContentSource
instance may be bound to a JNDI naming service. This allows the
runtime environment (a J2EE container for example) to supply a
pre-initialized ContentSource
instance. This allows specification of the connection details at
deployment time. Application code uses a JNDI lookup key to obtain
a ContentSource
instance. A typical JNDI lookup in a J2EE container would look like
this:
private ContentSource findContentSource() throws ServletException { try { Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup ("java:comp/env"); return (ContentSource) envCtx.lookup("marklogic/ContentSource"); } catch (NamingException e) { throw new ServletException ("ContentSource lookup failed: " + e, e); } }
See ContentSourceBeanFactory
for more details about integrating with JNDI.
If using JNDI to externalize ContentSource
configuration is not appropriate, the helper class ContentSourceFactory
may be used to instantiate ContentSource
objects directly.
Several variations of the
ContentSourceFactory.newContentSource(String, int)
method are available:
ContentSource contentSource = ContentSourceFactory.newContentSource ("somehost", 1234);
ContentSource contentSource = ContentSourceFactory.newContentSource ("localhost", 1234, "fred", "secret");
ContentSource contentSource = ContentSourceFactory.newContentSource ("host", 5678, "tony", "hush", "pubsdb");
Of note is the signature which takes a URI argument (ContentSourceFactory.newContentSource(URI)
).
This factory method accepts a URI of the form:
xdbc://user:password@host:port/contentbase
Which encapsulates all the connection information into a single argument. The URL scheme "xdbc" means the connection will be made to an XDBC server port. The scheme "xcc" may also be used, it's an alias for "xdbc". Additional schemes may be added in the future, but these are the only two currently supported.
Passing a single String argument may be more convenient than
passing four or five discreet values. Note that the factory method
takes a URI
object, not a String
.
URI uri = new URI ("xdbc://joe:secret@devhost:8050/techpubsdb"); ContentSource contentSource = ContentSourceFactory.newContentSource (uri);
Following are some sample code snippets that illustrate typical usage scenarios.
This is an example of using
Session.submitRequest(Request)
to run an XQuery
script and then iterating over the result. There is no longer an
explicit connection object. The Session
implementation manages connections automatically as needed. Also,
when a Session
object is
closed, any currently open streaming ResultSequence
objects created from that Session
will automatically be closed. Any cached ResultSequence
s
no longer have any relationship to the Session
that
created them and will not be affected.
Session session = contentSource.newSession ("mydatabase"); Request request = session.newAdhocQuery ("\"Hello World\""); ResultSequence rs = session.submitRequest (request); while (rs.hasNext()) { ResultItem rsItem = rs.next(); XdmItem item = rsItem.getItem(); if (item instanceof XSString) { String strValue = item.asString(); System.out.println ("String: " + strValue); } if (item instanceof XSDateTime) { XSDateTime dateTime = (XSDateTime) item; Date date = dateTime.asDate(); System.out.println ("DateTime: " + date); } ... // Each ResultItem instance will be a concrete Item class } session.close();
In addition to ad-hoc queries,
Session.submitRequest(Request)
can take a ModuleInvoke
or
ModuleSpawn
object as the argument. Rather than literal code to be executed,
these specify the URI of a server-resident module to be evaluated.
In all other respects they are the same.
Session session = contentSource.newSession ("mydatabase"); Request request = session.newModuleInvoke ("mymodule.xqy"); ResultSequence rs = session.submitRequest (request); while (rs.hasNext()) { ResultItem item = rs.next(); ... (same as previous example) } session.close();
Variables may be bound to Request
objects.
When an execution request is issued to the server with
Session.submitRequest(Request)
all the variables
currently bound to the Request
object are sent along and defined as external variables in the
execution context in the server.
XCC lets you create XdmNode
s
and XdmSequence
s,
as well as XdmAtomic
values. However, in the initial XCC release values of this type may
not be bound as external variables because MarkLogic Server cannot
yet accept them. This capability is anticipated for a future
release.
A XdmVariable
object is a named XdmValue
.
XCC defines interfaces that model the XQuery data types. See the
package com.marklogic.xcc.types
(click the Description link) for UML diagrams and details of the
type hierarchies.
The following is a (very) verbose example of creating and setting an external variable using a namespace:
Session session = contentSource.newSession ("mydatabase"); Request request = session.newAdhocQuery ( "xquery version \"1.0-ml\";\n" + "declare namespace xyz=\"http://xyz.com/foo/bar\";\n" + "declare variable $xyz:myvar as xs:string external;\n" + "data ($xyz:myvar)"); // create an unnamed xs:string value XdmValue value = ValueFactory.newXSString ("Some string value"); // create a new XName object referencing the above namespace XName xname = new XName ("http://xyz.com/foo/bar", "myvar"); // Create a Variable (name + value) instance XdmVariable myVariable = ValueFactory.newVariable (xname, value); // bind the Variable to the Request request.setVariable (myVariable); // "$xyz:myvar as xs:string" will be defined at query run time ResultSequence rs = session.submitRequest (request);
See the ValueFactory
helper
class for more details about creating XdmVariable
and XdmValue
instances.
The following is an example of creating and binding a variable in the default namespace.
Session session = contentSource.newSession ("mydatabase"); Request request = session.newAdhocQuery ( "xquery version \"1.0-ml\";\n" + "declare variable $myvar as xs:string external;\n" + "data ($myvar)"); // create an unnamed xs:string value XdmValue value = ValueFactory.newXSString ("Some string value"); // create a new XName object referencing the default namespace XName name = new XName ("myvar"); // create a Variable and bind it to the Request request.setVariable (ValueFactory.newVariable (name, value)); // "$myvar as xs:string" will be defined at query run time ResultSequence rs = session.submitRequest (request);
A conveience method on the Session
object
will create and bind a XdmVariable
instance in one call. The following example creates the same
XdmVariable
as above, binds it to the Request
and
returns the newly created XdmVariable
instance. In this example, the return value is ignored.
Session session = contentSource.newSession ("mydatabase"); Request request = session.newAdhocQuery ( "xquery version \"1.0-ml\";\n" + "declare variable $myvar as xs:string external;\n" + "data ($myvar)"); // create Variable "myvar", bind to Request, ignore return value request.setNewVariable ("myvar", ValueType.XS_STRING, "Some string value"); // "$myvar as xs:string" will be defined at query run time ResultSequence rs = session.submitRequest (request);
The model for inserting content differs in a couple of
significant ways from XDBC. First of all, you no longer ask for an
XDMPDocInsertStream
and push your data into it. You
now create Content
objects
which describe content (a document) to be inserted and XCC pulls
the data from that source.
Secondly, because content uploads can be interrupted and XCC
implements automatic recovery of uploads, instances of Content
should be
rewindable. See the ContentFactory
class for acceptable sources of content.
This example inserts an XML document from a literal
String
, in the "MyNameSpace" namespace and requests
that no automatic document repair be done. The ContentCreateOptions
instance is created with a convenience method that is preset to
select XML format.
ContentCreateOptions options = ContentCreateOptions.newXmlInstance(); options.setNamespace ("MyNameSpace"); options.setRepairLevel (DocumentRepairLevel.NONE); Content content = ContentFactory.newContent ("someUri", "<root attr=\"foo\">blah</root>", options); session.insertContent (content);
This example inserts the content of a file in text format. It
uses a ContentCreateOptions
object to set the namespace and quality.
File file = new File ("/some/file/path"); ContentCreateOptions options = ContentCreateOptions.newTextInstance(); options.setNamespace ("MyNameSpace"); options.setQuality (20); Content content = ContentFactory.newContent ("someUri", file, options); session.insertContent (content);
This example takes a W3C (Document
) Object Model
(DOM) instance (an object representation of an XML tree) and
inserts it via the Session
object.
No ContentCreateOptions
object is provided, so defaults are applied. Because, by
definition, the DOM is a well-formed XML tree, the content format
defaults to XML. If another format (text or binary) is selected by
the options, the serialized String representation of the XML tree
is inserted.
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document dom = builder.parse ("someDocUri"); Content content = ContentFactory.newContent ("someUri", dom, null); session.insertContent (content);
If you're using JDOM, you can use
one of the outputter classes in the org.jdom.output package to
convert the JDOM document to a form that can be handled by a
Session
. For
example, this code translates a JDOM tree to a W3C DOM and inserts
it:
Document dom = new org.jdom.output.DOMOutputter().output (jdomDocument); Content content = ContentFactory.newContent ("someUri", dom, null); session.insertContent (content);
For large JDOM trees, it may be more efficient to serialize them as Strings for insertion.
Multiple documents can be atomically inserted (all or none are
committed as a unit) by passing an array of Content
objects
to
Session.insertContent(Content [])
.
Session session = contentSource.newSession ("mydatabase"); File file = new File ("/some/file/path.xml"); String stringDoc = "<snoop attr=\"bling\">dog</snoop>"; DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document dom = builder.parse ("someDocUri"); Content [] docGroup = { ContentFactory.newContent ("uri1", file, null), ContentFactory.newContent ("uri2", stringDoc, null), ContentFactory.newContent ("uri3", dom, null) }; session.insertContent (docGroup);
Copyright © 2024 MarkLogic
Corporation
Complete online documentation for MarkLogic Server,
XQuery and related components may
be found at
developer.marklogic.com