FAQ: OpenAM Java SDK and policy decision cache

Last updated Jan 5, 2021

The purpose of this FAQ is to provide answers to commonly asked questions regarding OpenAM Java® SDK and the policy decision cache, including how to optimize policy decision requests. The OpenAM Java SDK is also referred to as the Client SDK.

2 readers recommend this article


This article has been archived and is no longer maintained by ForgeRock.

Frequently asked questions

Q. What APIs are involved in policy decisions?

A. The APIs used depend on whether you are requesting a policy decision or a XACML policy decision with the OpenAM Java SDK:

  • Policy decisions use the PolicyEvaluator class: PolicyDecision pd = pe.getPolicyDecision(ssoToken, resourceName, actions, env);
  • XACML policy decisions use the XACMLRequestProcessor class: Response xacmlResponse = XACMLRequestProcessor.getInstance() .processRequest(xacmlRequest, pdpEntityId, pepEntityId);

XACML policy decisions were introduced in OpenAM 12.0.0 but they do not use the policy decision cache.

Q. Why is the OpenAM Java SDK used for policy decisions?

A. The main advantage of using the OpenAM Java SDK for evaluating policies instead of the REST API is the cache used for storing policy decisions. This policy decision cache reduces traffic between your application and OpenAM, and makes requesting policy decisions quicker when they can be retrieved from the cache.

You may notice that you still have a lot of traffic to OpenAM even though you are using the OpenAM Java SDK; this typically happens when you're not using the policy decision cache enough. Once you understand how the cache is implemented and entries are stored, you can make changes to improve this.

Q. How are entries stored in the cache?

A. The PolicyEvaluator stores policy decisions in the cache as follows: (serviceName, resourceName, sessionId, scope) -> policyDecisionResult


  • serviceName - the service defined in the policy decision request.
  • resourceName - the resource being evaluated.
  • sessionId - the user session associated with the token presented in the request.
  • scope - subtree or self mode. The differences are discussed in the Q. Should I use subtree or self mode for the cache?
  • policyDecisionResult - the policy decision result includes the following additional information:
    • resourceResults - the result returned by OpenAM, which is stored in XML. For example, the result is shown as follows when the policy decision is allow: <Value>allow</Value>
    • env - the environment map used to obtain the resource results.       
    • ttl - Time to Live (TTL) - the number of minutes that the policy decision is stored in the cache. The default is 3 minutes, but this can be changed as detailed in Q. How long is a policy decision kept in the cache?
    • actions - the list of action names specified in the request, for example, POST or GET.         

Q. How are policy decisions retrieved from the cache?

A. When you make a request, you use the following parameters:

PolicyEvaluator pe = PolicyEvaluatorFactory.getInstance().getPolicyEvaluator(serviceName); PolicyDecision pd = pe.getPolicyDecision(ssoToken, resourceName, actions, env);

These inputs are translated for the cache (serviceName, resourceName, sessionId, scope) as follows:

  • serviceName is obtained directly from the request.
  • resourceName is obtained directly from the request.
  • sessionId is retrieved from the token string.
  • scope is loaded from the AMConfig.properties file.

The PolicyEvaluator then uses these translated inputs to check the cache to see if the resource already exists.

If it finds an existing policy decision, it will check that it is valid by verifying the additional information stored in the policyDecisionResult:

  1. The env values must match.
  2. The TTL must still be valid.
  3. The action names must be contained in the action names set stored in the cache.
} else if ((results[3] !=null) &&!((Set)results[3]).containsAll(actionNames)) {

Providing these three conditions are met, it will return the policy decision value in the cache. Otherwise, it will make a request to OpenAM to refresh the cache with the new policy decision request.

In summary, the two important things to be aware of when a policy decision is retrieved from the cache are:

  • An existing policy decision is located in the cache using the following inputs: serviceName, resourceName, sessionId and scope.
  • The cached entry is then verified to ensure it is appropriate to the request.

Q. How can I tell if a policy decision has been retrieved from the cache?

A. You can check the amRemotePolicy log, which is an OpenAM Java SDK log file.

If the policy decision has been retrieved from the cache, you will see messages such as:

amRemotePolicy:03/10/2015 11:10:08:053 AM GMT: Thread[http-bio-8080-exec-10,5,main] ResourceResultCache.getResourceResults()::serviceName=iPlanetAMWebAgentService:token=id=jdoe,ou=user,o=example.com,ou=services,dc=openam,dc=forgerock,dc=org:resourceName=http://openam.example.com:actionNames=[POST]:env:useCache=true:useRESTProtocol()=false:entering amRemotePolicy:03/10/2015 11:10:08:053 AM GMT: Thread[http-bio-8080-exec-10,5,main] ResourceResultCache.getResourceResults():would not contact server, would use results from cache

If the policy decision cannot be found in the cache (meaning increased traffic to OpenAM), you will see messages such as:

amRemotePolicy:03/10/2015 11:10:12:071 AM GMT: Thread[http-bio-8080-exec-3,5,main] ResourceResultCache.getResourceResults()::serviceName=iPlanetAMWebAgentService:token=id=jdoe,ou=user,o=example.com,ou=services,dc=openam,dc=forgerock,dc=org:resourceName=http://openam.example.com:actionNames=[GET]:env:useCache=true:useRESTProtocol()=false:entering amRemotePolicy:03/10/2015 11:10:12:071 AM GMT: Thread[http-bio-8080-exec-3,5,main] ResourceResultCache.getResourceResults():would contact server since cached action names do not cover request action names

Q. Does the Apache policy agent share the policy evaluation cache between processes?

A. The Apache policy agent does not currently share the policy evaluation cache between processes; it is maintained per process. This means it can appear that the policy agent is not using the cache and instead opens a new connection to OpenAM to send a policy evaluation request for every URL request. However, if the same URL request lands on a process that has a cache for that particular URL, then the cache is utilized. This is a known issue: OPENAM-4424 (Apache Agent does not appear to use cached policy results) and can impact performance if your Apache instance uses multiple processes.

Q. Why isn't the action names set included the cache key set?

A. Contrary to the other keys in the cache, the action names is a set which makes it more difficult to manage. If we consider the possible action names: POST, GET, PUT, DELETE, it means there are a total of 16 possibilities. Including all these action names in the cache would result in memory overuse. Therefore, having the action names in the policyDecisionResult is a compromise between memory usage and performance.

This is an important point to be aware of as you may notice that a lot of policy decisions are not retrieved due to a mismatch in action names.

Q. How can I improve caching if there are lots of different action names involved?

A. You can preload some requests to reduce the number of requests made to OpenAM as illustrated by the following examples.


These examples use a syntax similar to Java to make them simpler to understand.

Unused Cache Example (this approach should be avoided)

(The cache is empty for ssoToken, serviceName, resourceName) for(int i=0; i < 1000; i++) { getPolicyDecision(ssoToken, serviceName, resourceName, "POST"); getPolicyDecision(ssoToken, serviceName, resourceName, "GET"); }

This example never uses the cache because the action name is not part of the cache key set; even if you were to request the same policy decision but with a different action name, the policy decision would never be retrieved from the cache and you would make 2000 requests to OpenAM.

Let's investigate the first iteration to understand what is happening behind the getPolicyDecision API:

  • When the first POST call is made, the cache is empty and the OpenAM Java SDK makes a request to the OpenAM server. Upon receiving the response, the OpenAM Java SDK stores the response in the cache as normal.
  • When the second GET call is made, OpenAM checks the cache. Since the action name is not part of the key but part of the policyDecisionResult, OpenAM will find an entry in the cache. It will then check that this entry contains the action name required. In our case, the previous policyDecisionResult will be a POST action only, so the OpenAM Java SDK will call the OpenAM instance, and replace the POST policyDecisionResult value with the new GET policyDecisionResult. 

At the next iteration, the OpenAM Java SDK will come back to the same POST decision. It will hit the cache but unfortunately, the policyDecisionResult in it will be associated with a GET action name. The OpenAM Java SDK will then call the OpenAM instance again and replace the GET policyDecisionResult with the POST policyDecisionResult.

Therefore, the cache is not useful in this example and this approach should be avoided. The following example shows a much better approach.

Useful Cache Example (recommended approach)

(The cache is empty for ssoToken, serviceName, resourceName) getPolicyDecision(ssoToken, serviceName, resourceName, ["POST", GET"]); for(int i=0; i < 1000; i++) { getPolicyDecision(ssoToken, serviceName, resourceName, "POST"); getPolicyDecision(ssoToken, serviceName, resourceName, "GET"); }

The first policy decision for ["POST", GET"] won't be retrieved from the cache and will make a request to OpenAM. However, the subsequent requests for POST and GET will always be retrieved from the cache, meaning you are only making one request to OpenAM instead of 2000 requests.

Q. How long is a policy decision kept in the cache?

A. By default, a policy decision is stored in the cache for 3 minutes. You can change this by updating the com.sun.identity.agents.polling.interval property in the AMConfig.properties file.


Increasing this value can lead to a memory crash, depending on the amount of memory allocated to your application. You should adjust this value and then performance test your application to see what impact it has to ensure you have a cache size appropriate to the number of users and policies you have.

This caching time is also called the Time to Live (TTL) and is used when checking if a policy decision is still valid.

Q. Should I use subtree or self mode for the cache?

A. It is generally recommended that you use self mode as subtree mode has a number of known issues. Additionally, self mode scales better for large numbers of policy rules.


If you choose to use subtree mode, we recommend you test it thoroughly in your development environment to ensure you get the results you expect.

You can change the mode used by the cache by setting the com.sun.identity.policy.client.cacheMode property in the AMConfig.properties file.

Q. How can I monitor the cache performance?

A. You could use a third-party tool such as JProfiler™ to monitor the cache. You would need to monitor the resultCache attribute of the ResourceResultCache class.


This is a third-party tool that we suggest can be used for troubleshooting but is not supported by ForgeRock.

Q. Where are OpenAM Java SDK logs located for debugging?

A. OpenAM Java SDK logs, including the amRemotePolicy log, are kept in the directory specified in the com.iplanet.services.debug.directory property in the AMConfig.properties file.

See How do I enable message level debugging for the Java SDK in OpenAM 13.x? for further information on enabling debug logging.

See Also

Unreliable policy evaluation results when using root or subtree mode in OpenAM 13.x

Trailing forward slash removed from policy rules in OpenAM 11.0.0 and Policy Agents 3.3.0 which causes access denied error

OpenAM Developer's Guide › Developing Client Applications › Using the OpenAM Java SDK

OpenAM Developer's Guide › Developing Client Applications › Requesting Policy Decisions Using OpenAM Java SDK

OpenAM Developer's Guide › Developing Client Applications › Requesting a XACML Policy Decision Using OpenAM Java SDK

OpenAM API Docs - PolicyEvaluator class

OpenAM API Docs - XACMLRequestProcessor class

Related Issue Tracker IDs

OPENAM-2085 (Unreliable policy evaluation results with com.sun.identity.agents.config.fetch.from.root.resource enabled)

OPENAM-2554 (Policy Wildcard not matching nothing in context URI or URL Parameters)

OPENAM-3509 (PolicyEvaluation strips off trailing '/' from resource resulting in wrong enforcement on agent side)

OPENAM-5163 (Policy Self mode and Subtree mode behaves differently)

Copyright and Trademarks Copyright © 2021 ForgeRock, all rights reserved.