Class RPCManager

java.lang.Object
com.isomorphic.rpc.RPCManager
All Implemented Interfaces:
com.isomorphic.datasource.DSCacheManager

public class RPCManager extends Object implements com.isomorphic.datasource.DSCacheManager
Provides the ability to decode 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.

Special notes on queueing

While processing a queue, the RPCManager will not abort the queue if one of the requests fail, it will instead carry on until the last request has been executed and then issue a callback to the datasources involved. The reason for this is that the code in a DMI might already handle the error condition, and that any DataSource operations performed in the context of the failed transaction might likewise be trying to compensate for the error or gather information to send back in an error message. If a request failed, the 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 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.
See Also:
  • Constructor Summary

    Constructors
    Constructor
    Description
    RPCManager(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response)
    RPCManager constructor for use in Servlets or Filters.
    RPCManager(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Writer out)
    RPCManager constructor for use in JSPs.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    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.
    findFirstResponse(String dsName, 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).
    findLastResponse(String dsName, 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.
    Returns an Object that has previously been stored in this RPCManager's attribute map.
    Returns true if we have an authenticated user for this request.
    Convenience method for getting the data of a single RPCRequest.
    Returns an instance of the DataSource named in the "dsName" parameter.
    Convenience method for getting a single DSRequest when you know this request only contains one DSRequest.
    Convenience method for getting a single RPCRequest when you know this HTTP request only contains one RPCRequest.
    Returns a list of RPC requests sent in this HTTP transaction.
    Returns the tenant ID associated with the queue of requests being managed by this RPCManager.
    int
    Returns this RPCManager's transaction policy.
    Returns the user ID associated with the queue of requests being managed by this RPCManager.
    Returns a list of the roles associated with the user who is authenticated for this request.
    boolean
    Returns whether a tenant ID has been associated with the queue of requests being managed by this RPCManager.
    static boolean
    isRPC(jakarta.servlet.http.HttpServletRequest request)
     
    static boolean
    isXmlHttp(jakarta.servlet.http.HttpServletRequest request)
     
    static void
    processRequest(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response)
    Instantiates an RPCManager and processes any RPCRequest or DSRequest from the provided HttpServletRequest.
    boolean
    Returns true if any request in the current queue failed.
    void
    Register an implementation of RPCManagerCompletionCallback with this RPCManager.
    void
    Removes an Object that has previously been stored in this RPCManager's attribute map.
    int
    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, 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(RPCRequest rpcRequest, Object data)
    Convenience method.
    void
    send(RPCResponse rpcResponse)
    Convenience method for sending some data back in response to a single RPCRequest.
    void
    send(Object data)
    Convenience method for sending some data back in response to a single RPCRequest.
    void
    sendFailure(Object request, 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
    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, String xml)
    Convenience method.
    void
    sendXMLString(RPCRequest rpcRequest, String xml)
    Convenience method.
    void
    setAttribute(String key, 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
    Sets the charset of the response.
    setTenantId(String tenantId)
    Set the tenant ID to associate with the queue of requests being managed by this RPCManager.
    void
    Set this RPCManager's transaction policy.
    void
    setUserId(String userId)
    Set the user ID associated with the queue of requests being managed by this RPCManager.
    void
    setUserRoles(String rolesString)
    Accepts a comma-separated String representing the list of roles associated with the user who is authenticated for this request.
    void
    setUserRoles(String... roles)
    Accepts a List of roles associated with the user who is authenticated for this request.
    void
    setUserRoles(List rolesList)
    Accepts a List of roles associated with the user who is authenticated for this request.
    void
    Calling this tells the DSTransaction that all the remaining requests in the queue should be skipped.
    Starts the SQL transaction that will be used for all SQL DSRequests belonging to this RPCManager.
  • Constructor Details

    • RPCManager

      public RPCManager(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) throws Exception
      RPCManager constructor for use in Servlets or Filters.
      Parameters:
      request - The 'request' variable provided in the context of the JSP
      response - The 'response' variable provided in the context of the JSP
      Throws:
      ClientMustResubmitException - if the client must resubmit the request.
      Exception - if the request is malformed.
    • RPCManager

      public RPCManager(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, Writer out) throws Exception
      RPCManager constructor for use in JSPs. The RPC requires control of the output stream to send responses to the client. Since JSPs automatically call response.getOutputStream() to provide the 'out' variable in the context of the JSP and since it's further illegal to call getOutputStream() more than once, so you'll need to use this form of the RPCManager constructor when processing RPC requests in a JSP.
      Parameters:
      request - The 'request' variable provided in the context of the JSP
      response - The 'response' variable provided in the context of the JSP
      out - The 'out' variable provided in the context of the JSP
      Throws:
      ClientMustResubmitException - if the client must resubmit the request.
      Exception - if the request is malformed.
  • Method Details

    • isRPC

      public static boolean isRPC(jakarta.servlet.http.HttpServletRequest request)
      Returns:
      true if the passed HttpServletRequest contains a SmartClient RPC request, false otherwise.
    • isXmlHttp

      public static boolean isXmlHttp(jakarta.servlet.http.HttpServletRequest request)
      Returns:
      true if the current RPC request was made using the xmlHttpRequest transport, false otherwise.
    • doCustomResponse

      public 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.

      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().

    • setResponseCharset

      public void setResponseCharset(String charset)
      Sets the charset of the response. Must be called before any send() methods are called.
    • getData

      public Object getData()
      Convenience method for getting the data of a single RPCRequest. Calling this method is equivalent to calling getRequest.getData()
    • getDSRequest

      public DSRequest getDSRequest()
      Convenience method for getting a single DSRequest when you know this request only contains one DSRequest. If more than one DSRequest was actually sent by the client, this method returns the first one and logs a warning.
      Returns:
      DSRequest. Returns null if request is not instance of DSRequest.
    • getRequest

      public RPCRequest getRequest()
      Convenience method for getting a single RPCRequest when you know this HTTP request only contains one RPCRequest. If more than one RPC request was actually sent by the client, this method returns the first one and logs a warning.
    • getRequests

      public List<BaseRequest> getRequests()
      Returns a list of RPC requests sent in this HTTP transaction. The request objects in this list will be either of type RPCRequest (if you used RPCManager.send() on the client) or of type DSRequest if the request was generated by a databound component or datasource on the client or a mix of RPCRequest and DSRequest objects.
    • requestCount

      public int requestCount()
      Returns the number of RPC requests contained in the current HTTP request.
      Returns:
      number of RPC requests contained in the current HTTP request.
    • send

      public void send(Object data) throws Exception
      Convenience method for sending some data back in response to a single RPCRequest. Calling this method is equivalent to calling send(new RPCResponse(data))/
      Parameters:
      data - to send back
      Throws:
      Exception - if there is an error sending the response
    • send

      public void send(RPCResponse rpcResponse) throws Exception
      Convenience method for sending some data back in response to a single RPCRequest. If you're processing multiple RPC request sent as part of one HTTP request, you need to pair the responses to the requests by calling send(rpcRequest, rpcResponse) instead.
      Parameters:
      rpcResponse - containing the data to send back
      Throws:
      Exception - if there is an error sending the response
    • send

      public void send(RPCRequest rpcRequest, RPCResponse rpcResponse) throws Exception
      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.
      Parameters:
      rpcRequest - the request you're responding to
      rpcResponse - your response
      Throws:
      Exception - if there is an error sending the response
    • send

      public void send(RPCRequest rpcRequest, Object data) throws Exception
      Convenience method. This method does the following:
       RPCResponse rpcResponse = new RPCResponse();
       rpcResponse.setData(data);
       rpcResponse.setStatus(RPCResponse.STATUS_SUCCESS);
       send(rpcRequest, rpcResponse);
       
      Parameters:
      rpcRequest - the request you're responding to
      data - to send as the payload of the response
      Throws:
      Exception - if there is an error sending the response
    • sendXMLString

      public void sendXMLString(RPCRequest rpcRequest, String xml) throws Exception
      Convenience method. Transforms the provided XML in a manner equivalent to the isomorphic:XML JSP tag (custom Isomorphic tag) and sets that as the payload of a new RPCResponse. Calling this method is equivalent to parsing the XML and passing the resulting top-level org.w3c.dom.Element object to RPCResponse.setData().
      Throws:
      Exception - if there is an error sending the response
    • send

      public void send(DSRequest dsRequest, DSResponse dsResponse) throws Exception
      When responding to DataSource requests sent by the client, use this method.
      Parameters:
      dsRequest - the request you're responding to
      dsResponse - your response
      Throws:
      Exception - if there is an error sending the response
    • send

      public void send(DSRequest dsRequest, Object data) throws Exception
      Convenience method. This method does the following:
       DSResponse dsResponse = new DSResponse();
       dsResponse.setData(data);
       dsResponse.setStatus(DSResponse.STATUS_SUCCESS);
       send(dsRequest, dsResponse);
       
      Parameters:
      dsRequest - the request you're responding to
      data - to send as the payload of the response
      Throws:
      Exception - if there is an error sending the response
    • sendXMLString

      public void sendXMLString(DSRequest dsRequest, String xml) throws Exception
      Convenience method. Transforms the provided XML in a manner equivalent to the isomorphic:XML JSP tag (custom Isomorphic tag) and sets that as the payload of a new DSResponse. Calling this method is equivalent to parsing the XML and passing the resulting top-level an org.w3c.dom.Element object to DSResponse.setData().
      Throws:
      Exception - if there is an error sending the response
    • sendSuccess

      public void sendSuccess(RPCRequest rpcRequest) throws Exception
      Every RPC request requires a response. If your application does not require a response to a particular request, use this method to ack the successful completion of the request on the server.
      Parameters:
      rpcRequest - the request that completed successfully
      Throws:
      Exception - if there is an error sending the response
    • sendFailure

      public void sendFailure(Object request, String error) throws Exception
      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.
      Parameters:
      request - the request that failed
      error - the error string to send to the client
      Throws:
      Exception - if there is an error sending the response
    • sendFailure

      public void sendFailure(Object request, Throwable t) throws Exception
      Takes a Throwable, formats the stack trace and calls sendFailure(rpcRequst, error).
      Parameters:
      request - the request that failed
      t - the exception you wish to report to the client
      Throws:
      Exception - if there is an error sending the response
    • queueHasFailures

      public boolean queueHasFailures()
      Returns true if any request in the current queue failed. This method can be used by user code in a DMI or custom DataSource execute method to avoid processing later operations if earlier ones have failed.
    • skipRemainingQueue

      public void skipRemainingQueue()
      Calling this tells the 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 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.

    • findLastResponse

      public DSResponse findLastResponse(String dsName, 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. 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.

      Parameters:
      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)
      Returns:
      the DSResponse matching the search criteria
    • findFirstResponse

      public DSResponse findFirstResponse(String dsName, 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). 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.

      Parameters:
      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)
      Returns:
      the DSResponse matching the search criteria
    • processRequest

      public static void processRequest(jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response) throws jakarta.servlet.ServletException, IOException
      Instantiates an RPCManager and processes any 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 queueHasFailures() to determine if the next request should be processed.

      Parameters:
      request - The HttpServletRequest
      response - The HttpServletResponse
      Throws:
      jakarta.servlet.ServletException - As per HttpServlet.service()
      IOException - As per HttpServlet.service()
      See Also:
    • getDataSource

      public DataSource getDataSource(String dsName) throws Exception
      Returns an instance of the DataSource named in the "dsName" parameter. This method borrows an object from the framework's DataSource pool, and ensures that it is freed at the end of the request cycle. It is the recommended way to obtain an arbitrary DataSource object in your own server-side code. Note that this method is intended for use if you need to obtain some arbitrary DataSource. If what you want is the DataSource associated with the current DSRequest (a common use case), use 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.
      Parameters:
      dsName - The name of the DataSource to return
      Throws:
      Exception
      See Also:
    • setUserId

      public void setUserId(String userId)
      Set the user ID associated with the queue of requests being managed by this RPCManager. This value will be used by the framework to populate fields of types "creator" and "modifier". This API is intended for use when you are a using some custom authentication scheme - it is unnecessary if you are using the Servlet API for authentication, because we will default to using the value returned by 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.

      Parameters:
      userId - The user ID to associate with the queue of requests being managed by this RPCManager
      See Also:
    • getUserId

      public String getUserId()
      Returns the user ID associated with the queue of requests being managed by this RPCManager. This value can be set by the 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.
      Returns:
      The user ID associated with the queue of requests being managed by this RPCManager, or null if there is no authenticated user
      See Also:
    • setTenantId

      public RPCManager setTenantId(String tenantId)
      Set the tenant ID to associate with the queue of requests being managed by this RPCManager. Can be set in an override of IDACall.prepareRPCTransaction().

      See the client-side Multi-Tenacy documentation for major concepts and how to implement authorization.

      Returns:
      the RPC manager
      See Also:
    • getTenantId

      public String getTenantId()
      Returns the tenant ID associated with the queue of requests being managed by this RPCManager.
      See Also:
    • hasTenantId

      public boolean hasTenantId()
      Returns whether a tenant ID has been associated with the queue of requests being managed by this RPCManager.
      Returns:
      Whether a tenant ID has been associated with the queue of requests being managed by this RPCManager
      See Also:
    • getAuthenticated

      public Boolean getAuthenticated()
      Returns true if we have an authenticated user for this request. Please see the client-side documentation for DataSource.requiresAuthentication/ for details of how the authentication system works
      Returns:
      true if we have an authenticated user, otherwise false
      See Also:
    • setAuthenticated

      public void setAuthenticated(boolean authenticated)
      Pass true to this method to indicate that every request in the queue is associated with an authenticated user. You will need to do this if you wish to implement an authentication that is not based on the scheme built in to the servlet API. Please see the client-side documentation for DataSource.requiresAuthentication for details of how the authentication system works
      Parameters:
      authenticated - if true we have an authenticated user
      See Also:
    • getUserRoles

      public List getUserRoles()
      Returns a list of the roles associated with the user who is authenticated for this request. Note that this list must be manually populated by calling setUserRoles(); it is an alternative mechanism, in case you wish to implement a role-based security system other than the one built into the servlet API. Please see the client-side documentation for OperationBinding.requiresRole for details of how the authentication/security system works
      Returns:
      The list of roles associated with the currently authenticated user, or null if no such list has been set up
      See Also:
    • setUserRoles

      public void setUserRoles(String rolesString)
      Accepts a comma-separated String representing the list of roles associated with the user who is authenticated for this request. This method allows you to implement a role-based security system other than the one built in to the servlet API. Please see the client-side documentation for OperationBinding.requiresRole for details of how the authentication/security system works
      Parameters:
      rolesString - A comma-separated String representing the list of roles associated with the user who is authenticated for this reques
      See Also:
    • setUserRoles

      public void setUserRoles(String... roles)
      Accepts a List of roles associated with the user who is authenticated for this request. This method allows you to implement a role-based security system other than the one built in to the servlet API. Please see the client-side documentation for OperationBinding.requiresRole for details of how the authentication/security system works
      Parameters:
      roles - The list of roles associated with the authenticated user
      See Also:
    • setUserRoles

      public void setUserRoles(List rolesList)
      Accepts a List of roles associated with the user who is authenticated for this request. This method allows you to implement a role-based security system other than the one built in to the servlet API. Please see the client-side documentation for OperationBinding.requiresRole for details of how the authentication/security system works
      Parameters:
      rolesList - The list of roles associated with the authenticated user
      See Also:
    • getAttribute

      public Object getAttribute(String key)
      Returns an Object that has previously been stored in this RPCManager's attribute map. This method intentionally mirrors the method of the same name available on HttpServletRequest, and is provided as an alternstive way to add objects to an RPCManager without introducing a dependency on the Servlet API.
      Parameters:
      key - The key of the object in the DSRequest's attribute map
      See Also:
    • setAttribute

      public void setAttribute(String key, Object value)
      Stores an object in this RPCManager's attribute map, associated with the passed key. This method intentionally mirrors the method of the same name available on HttpServletRequest, and is provided as an alternstive way to add objects to an RPCManager without introducing a dependency on the Servlet API.
      Parameters:
      key - The key of the object in the DSRequest's attribute map
      value - The object to store
      See Also:
    • removeAttribute

      public void removeAttribute(String key)
      Removes an Object that has previously been stored in this RPCManager's attribute map. This method intentionally mirrors the method of the same name available on HttpServletRequest. It is provided as an alternstive, to avoid introducing a dependency on the Servlet API.
      Parameters:
      key - The key of the object in the DSRequest's attribute map
      See Also:
    • registerCallback

      public void registerCallback(RPCManagerCompletionCallback callback)
      Register an implementation of 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.
      Parameters:
      callback - An instance of RPCManagerCompletionCallback
    • getTransactionPolicy

      public int getTransactionPolicy()
      Returns this RPCManager's transaction policy. The transaction policy is in force for the entire lifecycle of the queue being managed by the RPCManager; it cannot be changed once queue processing has started. Transaction policy is one of the following TransactionPolicy constants:
      • NOT_SET: No special TransactionPolicy is in force; the system will fall back to settings in server.properties, as described in the client-side documentation. This is the default for RPCManager instances.
      • ANY_CHANGE: Bundle all requests into a transaction, including leading fetches, if there is any change operation in the queue. Since ANY_CHANGE is the default .properties setting, this is effectively the default behavior of an RPCManager where transaction policy has not been set.
      • FROM_FIRST_CHANGE: Start a transaction on the first request in the queue that potentially changes data (in other words, don't include leading fetches in the transaction).
      • ALL: Bundle all requests into a transaction unconditionally.
      • NONE: Switch off transactions for this RPCManager; each request that does not have a DataSource- or OperationBinding-level override to the contrary will be committed independently

      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.

      Returns:
      This RPCManager's transaction policy
    • setTransactionPolicy

      public void setTransactionPolicy(int tp) throws QueueAlreadyStartedException
      Set this RPCManager's transaction policy. The transaction policy is in force for the entire lifecycle of the queue being managed by the RPCManager; it cannot be changed once queue processing has started. Therefore, this method will fail with an exception if you call it after the first request in its queue has started processing.

      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:

      • NOT_SET: No special TransactionPolicy is in force; the system will fall back to settings in server.properties, as described in the client-side documentation. This is the default for RPCManager instances.
      • ANY_CHANGE: Bundle all requests into a transaction, including leading fetches, if there is any change operation in the queue. Since ANY_CHANGE is the default .properties setting, this is effectively the default behavior of an RPCManager where transaction policy has not been set.
      • FROM_FIRST_CHANGE: Start a transaction on the first request in the queue that potentially changes data (in other words, don't include leading fetches in the transaction).
      • ALL: Bundle all requests into a transaction unconditionally.
      • NONE: Switch off transactions for this RPCManager; each request that does not have a DataSource- or OperationBinding-level override to the contrary will be committed independently

      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.

      Throws:
      QueueAlreadyStartedException - if the queue has already started processing
    • startSQLTransaction

      public Connection startSQLTransaction(DSRequest dsReq) throws Exception
      Starts the SQL transaction that will be used for all SQL DSRequests belonging to this RPCManager. Call this method to be handed a 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.

      Returns:
      The Connection to be used for the RPCManager's SQL transaction
      Throws:
      Exception