public class RPCManager
extends java.lang.Object
RPCRequests
and DSRequests
sent by the browser into Java Objects, and send back Java Object as responses. This class has a client-side counterpart that is also called RPCManager. The client-side RPCManager enables you to send one or more RPCRequests to an arbitrary URL. In the Java logic at those URLs, you'll need to instantiate this RPCManager to process and respond to the requests.
Note that a single RPC transaction can contain more than one RPC request. See the discussion on queueing in the documentation for the client-side RPCManager on why this is useful.
All RPC requests require a response. If your application needs nothing more than an ack of the successful completion of a given request, use the sendSuccess()/sendFailure() convenience methods on this class to ack the request. The RPCManager keeps track of request/response pairs and automatically streams all responses to the client as a batch once you've provided a response for each request.
Note that when you call any of the send() methods on this class, no data is actually sent back over the wire until you have responded to all requests.
RPCManagerCompletionCallback.onFailure(com.isomorphic.datasource.DSTransaction, boolean)
would be called and the datasources would either commit or rollback a transaction. If you instead wanted to abort the execution of the rest of the queue upon failure you will have to manually call RPCManager.queueHasFailures()
to see if the queue has any failures before executing the next request. Also note that RPCRequests
issuing DMI calls do not have the concept of commit and rollback and will therefore require you to use this method to abort a queue on failure.RPCRequest
, RPCResponse
, Init
Constructor and Description |
---|
RPCManager(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) RPCManager constructor for use in Servlets or Filters. |
RPCManager(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, java.io.Writer out) RPCManager constructor for use in JSPs. |
Modifier and Type | Method and Description |
---|---|
void | doCustomResponse() If you're using Direct Method Invocation, you can call doCustomResponse() to suppress the normal RPCManager response so that you can send your own custom response via the servletResponse output stream. |
DSResponse | findFirstResponse(java.lang.String dsName, java.lang.String opType) Returns the DSResponse for the first DSRequest where the DataSource and operation type match the parameter values (null parameters match any DataSource / operation type). |
DSResponse | findLastResponse(java.lang.String dsName, java.lang.String opType) Returns the DSResponse for the DSRequest most immediately prior to the current DSRequest, where the DataSource and operation type match the parameter values. |
java.lang.Object | getAttribute(java.lang.String key) Returns an Object that has previously been stored in this RPCManager's attribute map. |
java.lang.Boolean | getAuthenticated() Returns true if we have an authenticated user for this request. |
java.lang.Object | getData() Convenience method for getting the data of a single RPCRequest. |
DataSource | getDataSource(java.lang.String dsName) Returns an instance of the DataSource named in the "dsName" parameter. |
DSRequest | getDSRequest() Convenience method for getting a single DSRequest when you know this request only contains one DSRequest. |
RPCRequest | getRequest() Convenience method for getting a single RPCRequest when you know this HTTP request only contains one RPCRequest. |
java.util.List | getRequests() Returns a list of RPC requests sent in this HTTP transaction. |
java.lang.String | getTenantId() Returns the tenant ID associated with the queue of requests being managed by this RPCManager. |
int | getTransactionPolicy() Returns this RPCManager's transaction policy. |
java.lang.String | getUserId() Returns the user ID associated with the queue of requests being managed by this RPCManager. |
java.util.List | getUserRoles() Returns a list of the roles associated with the user who is authenticated for this request. |
boolean | hasTenantId() Returns whether a tenant ID has been associated with the queue of requests being managed by this RPCManager. |
static boolean | isRPC(javax.servlet.http.HttpServletRequest request) |
static boolean | isXmlHttp(javax.servlet.http.HttpServletRequest request) |
static void | processRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) Instantiates an RPCManager and processes any RPCRequest or DSRequest from the provided HttpServletRequest. |
boolean | queueHasFailures() Returns true if any request in the current queue failed. |
void | registerCallback(RPCManagerCompletionCallback callback) Register an implementation of RPCManagerCompletionCallback with this RPCManager. |
void | removeAttribute(java.lang.String key) Removes an Object that has previously been stored in this RPCManager's attribute map. |
int | requestCount() Returns the number of RPC requests contained in the current HTTP request. |
void | send(DSRequest dsRequest, DSResponse dsResponse) When responding to DataSource requests sent by the client, use this method. |
void | send(DSRequest dsRequest, java.lang.Object data) Convenience method. |
void | send(java.lang.Object data) Convenience method for sending some data back in response to a single RPCRequest. |
void | send(RPCRequest rpcRequest, java.lang.Object data) Convenience method. |
void | send(RPCRequest rpcRequest, RPCResponse rpcResponse) When responding to a set of RPC requests sent as part of one HTTP request (if you used startQueue() sendQueue() on the client) you need to pair the responses to the requests. |
void | send(RPCResponse rpcResponse) Convenience method for sending some data back in response to a single RPCRequest. |
void | sendFailure(java.lang.Object request, java.lang.String error) If the request processing failed for some reason, you can encode your own failure response in a standard response, or use this convenience method to send a failure notification on the client. Unless your client-side request specified the willHandleError flag, whatever message you send back here will be alert()ed on the client. |
void | sendFailure(java.lang.Object request, java.lang.Throwable t) Takes a Throwable , formats the stack trace and calls sendFailure(rpcRequst, error). |
void | sendSuccess(RPCRequest rpcRequest) Every RPC request requires a response. |
void | sendXMLString(DSRequest dsRequest, java.lang.String xml) Convenience method. |
void | sendXMLString(RPCRequest rpcRequest, java.lang.String xml) Convenience method. |
void | setAttribute(java.lang.String key, java.lang.Object value) Stores an object in this RPCManager's attribute map, associated with the passed key. |
void | setAuthenticated(boolean authenticated) Pass true to this method to indicate that every request in the queue is associated with an authenticated user. |
void | setResponseCharset(java.lang.String charset) Sets the charset of the response. |
RPCManager | setTenantId(java.lang.String tenantId) Set the tenant ID to associate with the queue of requests being managed by this RPCManager. |
void | setTransactionPolicy(int tp) Set this RPCManager's transaction policy. |
void | setUserId(java.lang.String userId) Set the user ID associated with the queue of requests being managed by this RPCManager. |
void | setUserRoles(java.util.List rolesList) Accepts a List of roles associated with the user who is authenticated for this request. |
void | setUserRoles(java.lang.String rolesString) Accepts a comma-separated String representing the list of roles associated with the user who is authenticated for this request. |
void | setUserRoles(java.lang.String[] roles) Accepts a List of roles associated with the user who is authenticated for this request. |
void | skipRemainingQueue() Calling this tells the DSTransaction that all the remaining requests in the queue should be skipped. |
java.sql.Connection | startSQLTransaction(DSRequest dsReq) Starts the SQL transaction that will be used for all SQL DSRequests belonging to this RPCManager. |
public RPCManager(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws java.lang.Exception
request
- The 'request' variable provided in the context of the JSPresponse
- The 'response' variable provided in the context of the JSPClientMustResubmitException
- if the client must resubmit the request.java.lang.Exception
- if the request is malformed.public RPCManager(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, java.io.Writer out) throws java.lang.Exception
request
- The 'request' variable provided in the context of the JSPresponse
- The 'response' variable provided in the context of the JSPout
- The 'out' variable provided in the context of the JSPClientMustResubmitException
- if the client must resubmit the request.java.lang.Exception
- if the request is malformed.public static boolean isRPC(javax.servlet.http.HttpServletRequest request)
public static boolean isXmlHttp(javax.servlet.http.HttpServletRequest request)
public void doCustomResponse()
This is useful for implementing file download functionality in response to an RPC request.
Note if you are not using DMI, but simply using the RPCManager, you can avoid the RPCManager response by simply not calling RPCManager.send().
public void setResponseCharset(java.lang.String charset)
public java.lang.Object getData()
public DSRequest getDSRequest()
DSRequest
. Returns null
if request is not instance of DSRequest
.public RPCRequest getRequest()
public java.util.List getRequests()
public int requestCount()
public void send(java.lang.Object data) throws java.lang.Exception
data
- to send backjava.lang.Exception
- if there is an error sending the responsepublic void send(RPCResponse rpcResponse) throws java.lang.Exception
rpcResponse
- containing the data to send backjava.lang.Exception
- if there is an error sending the responsepublic void send(RPCRequest rpcRequest, RPCResponse rpcResponse) throws java.lang.Exception
rpcRequest
- the request you're responding torpcResponse
- your responsejava.lang.Exception
- if there is an error sending the responsepublic void send(RPCRequest rpcRequest, java.lang.Object data) throws java.lang.Exception
RPCResponse rpcResponse = new RPCResponse(); rpcResponse.setData(data); rpcResponse.setStatus(RPCResponse.STATUS_SUCCESS); send(rpcRequest, rpcResponse);
rpcRequest
- the request you're responding todata
- to send as the payload of the responsejava.lang.Exception
- if there is an error sending the responsepublic void sendXMLString(RPCRequest rpcRequest, java.lang.String xml) throws java.lang.Exception
org.w3c.dom.Element
object to RPCResponse.setData().java.lang.Exception
- if there is an error sending the responsepublic void send(DSRequest dsRequest, DSResponse dsResponse) throws java.lang.Exception
dsRequest
- the request you're responding todsResponse
- your responsejava.lang.Exception
- if there is an error sending the responsepublic void send(DSRequest dsRequest, java.lang.Object data) throws java.lang.Exception
DSResponse dsResponse = new DSResponse(); dsResponse.setData(data); dsResponse.setStatus(DSResponse.STATUS_SUCCESS); send(dsRequest, dsResponse);
dsRequest
- the request you're responding todata
- to send as the payload of the responsejava.lang.Exception
- if there is an error sending the responsepublic void sendXMLString(DSRequest dsRequest, java.lang.String xml) throws java.lang.Exception
java.lang.Exception
- if there is an error sending the responsepublic void sendSuccess(RPCRequest rpcRequest) throws java.lang.Exception
rpcRequest
- the request that completed successfullyjava.lang.Exception
- if there is an error sending the responsepublic void sendFailure(java.lang.Object request, java.lang.String error) throws java.lang.Exception
request
- the request that failederror
- the error string to send to the clientjava.lang.Exception
- if there is an error sending the responsepublic void sendFailure(java.lang.Object request, java.lang.Throwable t) throws java.lang.Exception
Throwable
, formats the stack trace and calls sendFailure(rpcRequst, error).request
- the request that failedt
- the exception you wish to report to the clientjava.lang.Exception
- if there is an error sending the responsepublic boolean queueHasFailures()
public void skipRemainingQueue()
DSTransaction
that all the remaining requests in the queue should be skipped. Those requests will instead return a response with a status of BaseResponse.STATUS_PROCESSING_SKIPPED
. This ensures that the remaining requests don't actually do any logic processing. A typical use-case for this is when you manually handle a transaction queue and after executing a request, use RPCManager.queueHasFailures()
to check if there is a failure, you can tell the remaining queue to skip processing, giving you consistent responses for those requests that were skipped.
public DSResponse findLastResponse(java.lang.String dsName, java.lang.String opType)
DSResponse
for the DSRequest most immediately prior to the current DSRequest, where the DataSource and operation type match the parameter values. For example:DSResponse resp = rpcManager.findLastResponse("customer", "update");would return the response to the most recent update request on the "customer" DataSource prior to the request currently being processed (ie, the first one in the queue with no response)
This method is just one way to access the response to a request earlier in the queue - it is a programmatic equivalent of using $responseData.last()
in a Velocity expression. Scan the client-side documentation for "transaction chaining" for a full discussion of the various options available when using the Transaction Chaining approach.
dsName
- The name of the DataSource to find a response for (null means any DataSource)opType
- The operation type to find a response for (null means any operation type)public DSResponse findFirstResponse(java.lang.String dsName, java.lang.String opType)
DSResponse
for the first DSRequest where the DataSource and operation type match the parameter values (null parameters match any DataSource / operation type). For example:DSResponse resp = rpcManager.findFirstResponse("customer", "update"); would return the response to the first update request on the "customer" DataSource.
This method is just one way to access the response to a request earlier in the queue - it is a programmatic equivalent of using
$responseData.first()
in a Velocity expression. Scan the client-side documentation for "transaction chaining" for a full discussion of the various options available when using the Transaction Chaining approach.
dsName
- The name of the DataSource to find a response for (null means any DataSource)opType
- The operation type to find a response for (null means any operation type)public static void processRequest(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException
RPCRequest
or DSRequest
from the provided HttpServletRequest. Depending on the transactionPolicy
specified and the settings for the underlying datasources and the incoming requests, the list of requests can end up as transaction. If this happens and one of the requests fail during execution, the RPCManager will notify underlying datasources with a RPCManagerCompletionCallback
of either success or failure after all requests have been executed. The underlying DataSource
will then either commit or rollback. The queue will not stop during mid processing because the previous request failed and will instead carry on to the end before issuing the callback.
If you want to be able to abort a queue from processing the rest of the requests after a failure you will have to manually implement the queue processing and use RPCManager.queueHasFailures()
to determine if the next request should be processed.
request
- The HttpServletRequestresponse
- The HttpServletResponsejavax.servlet.ServletException
- As per HttpServlet.service()java.io.IOException
- As per HttpServlet.service()RPCManager for special notes on queueing.
public DataSource getDataSource(java.lang.String dsName) throws java.lang.Exception
DSRequest.getDataSource()
instead. Also, if you are trying to access some arbitrary DataSource purely because you need to run a DSRequest on it (another very common use case), consider just creating the DSRequest instead, using one of the constructors that accepts a DataSource name.dsName
- The name of the DataSource to returnjava.lang.Exception
DSRequest.getDataSource()
, DSRequest(String, String, RPCManager)
public void setUserId(java.lang.String userId)
HttpServletRequest.getRemoteUser()
. Calling this API automatically sets the authentication status of the RPCManager. If you pass a non-null value, the authentication status is set to true. If you pass null, the authentication status is also set to null.
userId
- The user ID to associate with the queue of requests being managed by this RPCManagerRPCManager.getUserId()
, RPCManager.setAuthenticated(boolean)
public java.lang.String getUserId()
RPCManager.setUserId(String)
; if that method has not been called and we are running in the context of the servlet API, we call the servlet API's getRemoteUser()
method.RPCManager.setUserId(String)
public RPCManager setTenantId(java.lang.String tenantId)
IDACall.prepareRPCTransaction()
. See the client-side Multi-Tenacy documentation for major concepts and how to implement authorization.
DSTransaction.setTenantId(java.lang.String)
public java.lang.String getTenantId()
DSTransaction.getTenantId()
public boolean hasTenantId()
RPCManager.setTenantId(java.lang.String)
public java.lang.Boolean getAuthenticated()
RPCManager.setAuthenticated(boolean)
public void setAuthenticated(boolean authenticated)
authenticated
- if true we have an authenticated userRPCManager.getAuthenticated()
, RPCManager.setUserRoles(java.lang.String)
public java.util.List getUserRoles()
RPCManager.getAuthenticated()
, RPCManager.setUserRoles(java.lang.String)
public void setUserRoles(java.lang.String rolesString)
rolesString
- A comma-separated String representing the list of roles associated with the user who is authenticated for this requesRPCManager.setAuthenticated(boolean)
, RPCManager.getUserRoles()
public void setUserRoles(java.lang.String[] roles)
roles
- The list of roles associated with the authenticated userRPCManager.setAuthenticated(boolean)
, RPCManager.getUserRoles()
public void setUserRoles(java.util.List rolesList)
rolesList
- The list of roles associated with the authenticated userRPCManager.setAuthenticated(boolean)
, RPCManager.getUserRoles()
public java.lang.Object getAttribute(java.lang.String key)
key
- The key of the object in the DSRequest's attribute mapDSRequest.getAttribute(java.lang.String)
public void setAttribute(java.lang.String key, java.lang.Object value)
key
- The key of the object in the DSRequest's attribute mapvalue
- The object to storeDSRequest.setAttribute(java.lang.String, java.lang.Object)
public void removeAttribute(java.lang.String key)
key
- The key of the object in the DSRequest's attribute mapDSRequest.removeAttribute(java.lang.String)
public void registerCallback(RPCManagerCompletionCallback callback)
RPCManagerCompletionCallback
with this RPCManager. The callback object will have its onSuccess() or onFailure() method called when every request in the RPCManager's queue has completed. Note that the RPCManager is only considered successful - and hence onSuccess() will be called - if every request in the queue is successful; if any one fails, onFailure() will be called.callback
- An instance of RPCManagerCompletionCallback
public int getTransactionPolicy()
TransactionPolicy
constants: server.properties
, as described in the client-side documentation. This is the default for RPCManager instances..properties
setting, this is effectively the default behavior of an RPCManager where transaction policy has not been set.Change operation in listing above is add, update or remove operation. Note that custom operation is not considered a change operation as far as whether a transaction is started.
The default .properties
setting is ANY_CHANGE.
public void setTransactionPolicy(int tp) throws QueueAlreadyStartedException
When you change transaction policy, you effectively override the global setting for autoJoinTransactions, for this request queue only. However, autoJoinTransactions settings specified at the DataSource or OperationBinding level will still be honored. If you need to override these finer-grained settings, you can do so with DSRequest method setJoinTransaction
. For details of configuring autoJoinTransactions, scan the client documentation for that phrase.
Transaction policy is one of the following TransactionPolicy
constants:
server.properties
, as described in the client-side documentation. This is the default for RPCManager instances..properties
setting, this is effectively the default behavior of an RPCManager where transaction policy has not been set.Change operation in listing above is add, update or remove operation. Note that custom operation is not considered a change operation as far as whether a transaction is started.
Note that you can also use transactions without an RPCManager or HttpServletRequest - see DSTransaction
.
QueueAlreadyStartedException
- if the queue has already started processingpublic java.sql.Connection startSQLTransaction(DSRequest dsReq) throws java.lang.Exception
Connection
that you can use for your own, non-DSRequest operations and have them participate in the same SQL transaction as the queue of DSRequests. Note that you are not required to call this method; the SQL subsystem will automatically start a transaction if necessary, in accordance with the transaction policy
in force). Only call this method if you want to insert extra SQL operations into the transaction (using a custom DataSource implementation, DMI method or server scriptlet) before the first DSRequest operation.
Also note that you are not required to close, commit or release the connection. Again, the framework will automatically do this as required. For this reason, do not attempt to cache the connection object and reuse it elsewhere.
java.lang.Exception