diff --git a/agama/transpiler/src/main/java/io/jans/agama/dsl/Transpiler.java b/agama/transpiler/src/main/java/io/jans/agama/dsl/Transpiler.java index 948a91ae20c..fc8638c8764 100644 --- a/agama/transpiler/src/main/java/io/jans/agama/dsl/Transpiler.java +++ b/agama/transpiler/src/main/java/io/jans/agama/dsl/Transpiler.java @@ -79,7 +79,7 @@ public class Transpiler { throw new RuntimeException("Unable to read utility script", e); } - FM_CONFIG = new Configuration(Configuration.VERSION_2_3_31); + FM_CONFIG = new Configuration(Configuration.VERSION_2_3_32); FM_CONFIG.setClassLoaderForTemplateLoading(CLS_LOADER, "/"); FM_CONFIG.setDefaultEncoding(UTF_8.toString()); FM_CONFIG.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); diff --git a/docs/admin/developer/agama/engine-bridge-config.md b/docs/admin/developer/agama/engine-bridge-config.md index ad6893b18b9..e2dcac3f50f 100644 --- a/docs/admin/developer/agama/engine-bridge-config.md +++ b/docs/admin/developer/agama/engine-bridge-config.md @@ -28,8 +28,6 @@ The properties of Agama engine configuration are described in the following: - `scriptsPath`: A path relative to `/opt/jans/jetty/jans-auth/server/agama` that serves as the root of the hierarchy of (Java/Groovy) classes added on the fly. Default value is `/scripts` -- `serializerType`: A low-level property related to [continuations](./advanced-usages.md#other-engine-characteristics) serialization. Set this to `null` if your flows present crashes due to issues with Java serialization. Default value is `KRYO` - - `maxItemsLoggedInCollections`: When a list or map is [logged](../../../agama/language-reference.md#logging) in a flow, only the first few items are included in the output. You can use this property to increase that limit. Default value is `9` @@ -44,10 +42,41 @@ The properties of Agama engine configuration are described in the following: - `bridgeScriptPage`: This is a facelets (JSF) page the bridge needs for proper operation. This page resides in the authentication server WAR file and will rarely need modifications. Default value is `agama.xhtml` +- `serializeRules`: A JSON object specifying the serialization rules, see below. It is not recommended to remove items from the out-of-the-box rules. Adding items is fine + + }--> + +### Serialization rules + +At certain points in the course of a flow, serialization of all its variables is required. The engine employs two mechanisms for this purpose: standard Java serialization and [KRYO](https://github.com/EsotericSoftware/kryo) serialization. Depending on the type of (Java) object to be serialized, administrators can specify when a mechanism is preferred over the other through a set of simple rules. + +This can be better explained with an example. Suppose the following configuration: + +``` +"serializeRules": { + "JAVA": ["ice", "com.acme"], + "KRYO": [ "com.acme.bike" ] +} +``` + +- If the object to serialize belongs to class `com.acme.bike.SuperSonic`, both lists are traversed for the best package match. Here KRYO wins because it has a perfect match with respect to the package of the class + +- If the class were `com.acme.bike.mega.SuperSonic`, KRYO still wins because it has the closest match to the package of the class + +- In case of `ice.cream.Salty`, JAVA is chosen (best match) + +- In case of `org.buskers.Singer`, no matches are found, however, KRYO is chosen - it's the **fallback** method + +- In case of `com.acmeMan`, no matches are found. KRYO is picked as in the previous case + +Please account additional behaviors: + +- If the object's class is in the default package (unnamed package), KRYO is used +- If the exact class name is found in one of the lists, the method represented by such list is employed +- If the object is a (Java) exception, JAVA is used unless the full class name appears listed in the KRYO rules ## Bridge configuration diff --git a/docs/admin/developer/agama/faq.md b/docs/admin/developer/agama/faq.md index 9ef79ce318c..a9691b5a279 100644 --- a/docs/admin/developer/agama/faq.md +++ b/docs/admin/developer/agama/faq.md @@ -23,14 +23,19 @@ This occurs when no `Finish` statement has been found in the execution of a flow ### Serialization errors -Agama engine saves the state of a flow every time an [RRF](../../../agama/language-reference.md#rrf) or [RFAC](../../../agama/language-reference.md#rfac) instruction is reached. For this purpose the [KRYO](https://github.com/EsotericSoftware/kryo) library is employed. If kryo is unable to serialize a variable in use by your flow, a serialization error will appear in the screen or in the logs. Normally the problematic (Java) class is logged and this helps reveal the variable that is causing the issue. Note variables that hold "native" Agama values like strings or maps are never troublesome; the problems may originate from values obtained via [Call](../../../agama/language-reference.md#foreign-routines). +Agama engine saves the state of a flow every time an [RRF](../../../agama/language-reference.md#rrf) or [RFAC](../../../agama/language-reference.md#rfac) instruction is reached. The _State_ can be understood as the set of all variables defined in a flow and their associated values up to certain point. -To fix a serialization problem, try some of the following: +Most of times, variables hold basic Agama [values](../../../agama/language-reference.md#data-types) like strings, booleans, numbers, lists or maps, however, more complex values may appear due to Java `Call`s. The engine does its best to properly serialize these Java objects, nonetheless, this is not always feasible. In these cases, the flow crashes and errors will appear on screen as well as in the server logs. -- Check if the value held by the variable is needed for RRF/RFAC or some upcoming statement. If that's not the case, simply set it to `null` before RRF/RFAC occurs -- Adjust the given class so it is "serialization" friendlier. With kryo, classes are not required to implement the `java.io.Serializable` interface -- Find a replacement for the problematic class -- As a last resort, set `serializerType` property of the [engine](./engine-bridge-config.md#engine-configuration) to `null`. Note this will switch to standard Java serialization. This setting applies globally for all your flows +Use the information in the logs to detect the problematic Java class. This would normally allow you to identify the variable that is causing the issue. Now you have several options to proceed: + +- Check if the value held by the variable is needed for the given RRF/RFAC or some upcoming statement. If that's not the case, simply set it to `null` before RRF/RFAC occurs +- Extract only the necessary pieces from the variable, that is, grab only the fields from the object which are of use for the rest of the flow. If they are simple values like strings or numbers, serialization will succeed. Ensure to nullify or overwrite the original variable +- Adjust the given class so it is "serialization" friendlier. Sometimes, adding a no-args constructor fixes the problem. In other cases, making the class implement the `java.io.Serializable` interface will make it work. The error in the log should provide a hint +- Tweak the engine serialization [rules](./engine-bridge-config.md#serialization-rules) so an alternative type of serialization can be used for this particular object +- Modify your Java code so an alternative class is used instead + +In general, a good practice is to avoid handling complex variables in flows. Letting big object graphs live in the state has a negative impact on performance and also increases the risk of serialization issues. ## Libraries and classes added on the fly diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/exception/FlowCrashException.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/exception/FlowCrashException.java index eec7fa32b64..d4edf3bc7a4 100644 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/exception/FlowCrashException.java +++ b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/exception/FlowCrashException.java @@ -2,8 +2,6 @@ public class FlowCrashException extends Exception { - public FlowCrashException() {} - public FlowCrashException(String message) { super(message); } diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/script/ScriptUtils.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/script/ScriptUtils.java index 06c8c0ebcd5..98a4541e22a 100644 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/script/ScriptUtils.java +++ b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/script/ScriptUtils.java @@ -123,7 +123,8 @@ public static Pair callAction(Object instance, String actionC try { result = CdiUtil.bean(ActionService.class).callAction(instance, actionClassName, methodName, params); } catch (Exception e) { - LOG.warn("Exception raised when executing Call - class: {}, method: {}", actionClassName, methodName); + LOG.warn("Exception raised when executing Call - class: {}, method: {}", + actionClassName == null ? instance.getClass().getName() : actionClassName, methodName); ex = e; } return new Pair<>(result, ex); //See jans#6530 diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/ContinuationSerializer.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/ContinuationSerializer.java index c536186074c..3f82c3af7f8 100644 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/ContinuationSerializer.java +++ b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/ContinuationSerializer.java @@ -49,7 +49,7 @@ class CustomObjectOutputStream extends ObjectOutputStream { try ( ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream sos = new CustomObjectOutputStream(baos)) { - //Pair is not java-serializable, use a 2-length array + //Pair is not serialization-friendly, use a 2-length array sos.writeObject(new Object[] { scope, continuation }); return baos.toByteArray(); } diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/FstSerializer.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/FstSerializer.java deleted file mode 100644 index 5bcfcf97080..00000000000 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/FstSerializer.java +++ /dev/null @@ -1,41 +0,0 @@ -package io.jans.agama.engine.serialize; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import jakarta.annotation.PostConstruct; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import io.jans.agama.model.serialize.Type; -import org.slf4j.Logger; - -/** - * Warning: This serialization strategy is not implemented yet - */ -@ApplicationScoped -public class FstSerializer implements ObjectSerializer { - - @Inject - private Logger logger; - - @Override - public Object deserialize(InputStream in) throws IOException { - return null; - } - - @Override - public void serialize(Object data, OutputStream out) throws IOException { - } - - @Override - public Type getType() { - return Type.FST; - } - - @PostConstruct - private void init() { - - } - -} diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/KryoSerializer.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/KryoSerializer.java index 2c50429797f..1d5a0380e4f 100644 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/KryoSerializer.java +++ b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/KryoSerializer.java @@ -12,13 +12,12 @@ import java.io.InputStream; import java.io.OutputStream; -import io.jans.agama.model.serialize.Type; import io.jans.agama.engine.service.ActionService; import org.slf4j.Logger; @ApplicationScoped -public class KryoSerializer implements ObjectSerializer { +public class KryoSerializer { @Inject private Logger logger; @@ -27,34 +26,31 @@ public class KryoSerializer implements ObjectSerializer { private ActionService actionService; private ThreadLocal kryos; - - @Override - public Object deserialize(InputStream in) throws IOException { + + public Object deserialize(InputStream in) { + logger.trace("Kryodeserializing"); Input input = new Input(in); //If input is closed, the input's InputStream is closed return kryos.get().readClassAndObject(input); + } - - @Override + public void serialize(Object data, OutputStream out) throws IOException { + logger.trace("Kryoserializing"); Output output = new Output(out); kryos.get().writeClassAndObject(output, data); output.flush(); + } - - @Override - public Type getType() { - return Type.KRYO; - } - + @PostConstruct private void init() { Log.DEBUG(); kryos = new ThreadLocal() { - + @Override protected Kryo initialValue() { Kryo kryo = new Kryo(); diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/NativeJavaBox.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/NativeJavaBox.java index ff191a09e59..55cf9a1b0b0 100644 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/NativeJavaBox.java +++ b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/NativeJavaBox.java @@ -28,7 +28,7 @@ public class NativeJavaBox implements Serializable { private static final Logger logger = LoggerFactory.getLogger(NativeJavaBox.class); private static final ManagedBeanService MBSRV = CdiUtil.bean(ManagedBeanService.class); - private static final SerializerFactory SERFACT = CdiUtil.bean(SerializerFactory.class); + private static final SerializationUtil INUTIL = CdiUtil.bean(SerializationUtil.class); private static final ActionService ACTSRV = CdiUtil.bean(ActionService.class); private NativeJavaObject raw; @@ -71,18 +71,7 @@ private void writeObject(ObjectOutputStream out) throws IOException { out.writeUTF(realClassName); out.writeObject(qualies); //kryo fails deserializing Annotations :( } else { - - //The object serializer instance may change at runtime. It has to be looked up every time - ObjectSerializer serializer = SERFACT.get(); - boolean useJavaOnlySerialization = serializer == null; - - out.writeObject(useJavaOnlySerialization ? null : serializer.getType()); - //unwrapped is not a managed object - if (useJavaOnlySerialization) { - out.writeObject(unwrapped); - } else { - serializer.serialize(unwrapped, out); - } + INUTIL.write(unwrapped, out); } } @@ -103,10 +92,7 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE logger.trace("Managed bean class {}", realClassName); unwrapped = ManagedBeanService.instance(ACTSRV.classFromName(realClassName), qualies); } else { - - Type type = (Type) in.readObject(); - ObjectSerializer serializer = SERFACT.get(type); - unwrapped = serializer == null ? in.readObject() : serializer.deserialize(in); + unwrapped = INUTIL.read(in); } logger.trace("Underlying object is an instance of {}", unwrapped.getClass().getName()); diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/ObjectSerializer.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/ObjectSerializer.java deleted file mode 100644 index 4138ea31e5e..00000000000 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/ObjectSerializer.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.jans.agama.engine.serialize; - -import io.jans.agama.model.serialize.Type; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public interface ObjectSerializer { - - Object deserialize(InputStream in) throws IOException; - void serialize(Object data, OutputStream out) throws IOException; - Type getType(); - -} diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/SerializationUtil.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/SerializationUtil.java new file mode 100644 index 00000000000..0696020e26d --- /dev/null +++ b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/SerializationUtil.java @@ -0,0 +1,122 @@ +package io.jans.agama.engine.serialize; + +import io.jans.agama.model.EngineConfig; +import io.jans.agama.model.serialize.Type; +import io.jans.util.StringHelper; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.*; + +import org.slf4j.Logger; + +import static io.jans.agama.model.serialize.Type.*; + +@ApplicationScoped +public class SerializationUtil { + + @Inject + private KryoSerializer criolina; + + @Inject + private EngineConfig econfig; + + @Inject + private Logger logger; + + public void write(Object obj, ObjectOutputStream out) throws IOException { + + Type type = typeFor(obj); + logger.trace("Serialization strategy chosen was {}", type); + boolean useKryo = type.equals(KRYO); + out.writeBoolean(useKryo); + + if (useKryo) { + criolina.serialize(obj, out); + } else { + out.writeObject(obj); + } + + } + + public Object read(ObjectInputStream in) throws IOException, ClassNotFoundException { + return in.readBoolean() ? criolina.deserialize(in) : in.readObject(); + } + + // For a given object, it determines the serializer to use given the following hints: + // - If the object's class is in the default package (unnamed package), use kryo + // - If the object is an exception use java unless the class name appears in the kryo rules of agama config + // - Use kryo or java based on the largest package match found in the rules. When in a tie, use kryo + // The below are examples of package matches against hypothetical class ab.ur.ri.do + // a) ab.ur.ri + // b) ab + // Here, match (a) is better (larger). The below are NOT matches against the mentioned class: + // a) ab.ur.ri.do.s + // b) ab.ur.ri.dor + private Type typeFor(Object budget) { + + Map> rules = econfig.getSerializeRules(); + if (rules == null) return KRYO; + + String clsName = budget.getClass().getName(); + List jules = aList(rules, JAVA); + List kules = aList(rules, KRYO); + + int kryoScore = score(clsName, kules); + if (kryoScore == -1) return KRYO; + + if (Exception.class.isInstance(budget)) { + //Use Java for serializing exceptions except when the full classname is found in the kryo rules + return kryoScore == 0 ? KRYO : JAVA; + } else { + int jScore = score(clsName, jules); + return kryoScore <= jScore ? KRYO : JAVA; + } + + } + + private static int score(String clsName, List prefixes) { + + int parts = dotCount(clsName); + if (parts == 0) return -1; //this class is in the default package! + + parts++; + int sc = 0; //holds the largest match against a package + + for (String pack : prefixes) { + if (StringHelper.isNotEmptyString(pack)) { + int packageParts = dotCount(pack) + 1; + + if (parts > packageParts) { + if (clsName.startsWith(pack + ".") && sc < packageParts) + sc = packageParts; + } else if (parts == packageParts) { //clsName does not belong to package pack + if (pack.equals(clsName)) return 0; //perfect match (pack is actually a classname) + } + } + } + return parts - sc; + + } + + private static int dotCount(String str) { + + int s = -1, i = -1; + do { + i++; + s++; + i = str.indexOf('.', i); + } while (i != -1); + return s; + + } + + private static List aList(Map> map, Type type) { + return map.getOrDefault(type.toString(), Collections.emptyList()); + } + +} diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/SerializerFactory.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/SerializerFactory.java deleted file mode 100644 index e63bd5789be..00000000000 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/serialize/SerializerFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -package io.jans.agama.engine.serialize; - -import io.jans.agama.model.EngineConfig; -import io.jans.agama.model.serialize.Type; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Any; -import jakarta.enterprise.inject.Instance; -import jakarta.inject.Inject; - -@ApplicationScoped -public class SerializerFactory { - - @Inject - private EngineConfig engineConf; - - @Inject @Any - private Instance services; - - private ObjectSerializer serializer; - - public ObjectSerializer get() { - return serializer; - } - - public ObjectSerializer get(Type type) { - return services.stream().filter(s -> s.getType().equals(type)) - .findFirst().orElse(null); - } - - public void refresh() { - serializer = get(engineConf.getSerializerType()); - } - -} diff --git a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/service/ServicesFactory.java b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/service/ServicesFactory.java index 62cfc9bc711..bbab85edcf1 100644 --- a/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/service/ServicesFactory.java +++ b/jans-auth-server/agama/engine/src/main/java/io/jans/agama/engine/service/ServicesFactory.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; -import io.jans.agama.engine.serialize.SerializerFactory; import io.jans.agama.model.EngineConfig; import io.jans.as.model.configuration.AppConfiguration; import io.jans.service.cdi.event.ConfigurationUpdate; @@ -22,9 +21,6 @@ public class ServicesFactory { @Inject private Logger logger; - @Inject - private SerializerFactory serializerFactory; - private ObjectMapper mapper; private EngineConfig econfig; @@ -51,7 +47,6 @@ public void updateConfiguration(@Observes @ConfigurationUpdate AppConfiguration } else { logger.info("Refreshing Agama configuration..."); BeanUtils.copyProperties(econfig, newConfig); - serializerFactory.refresh(); } } catch (Exception e) { logger.error(e.getMessage(), e); diff --git a/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/EngineConfig.java b/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/EngineConfig.java index e9979e9ed2d..f66f8ece215 100644 --- a/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/EngineConfig.java +++ b/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/EngineConfig.java @@ -3,10 +3,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import io.jans.agama.model.serialize.Type; -import io.jans.util.Pair; - import jakarta.ws.rs.core.HttpHeaders; + +import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -20,8 +19,6 @@ public class EngineConfig { private String templatesPath = "/ftl"; private String scriptsPath = "/scripts"; - private Type serializerType = Type.KRYO; - private int maxItemsLoggedInCollections = 3; //transpiled code hash verification. Boolean preferred over boolean because it helps to keep the property "hidden" @@ -35,9 +32,10 @@ public class EngineConfig { //relative to https://.../jans-auth private String bridgeScriptPage = "agama.xhtml"; - private Map defaultResponseHeaders = Stream.of( - new Pair<>(HttpHeaders.CACHE_CONTROL, "max-age=0, no-store") - ).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)); + private Map> serializeRules; + + private Map defaultResponseHeaders = Map.of( + HttpHeaders.CACHE_CONTROL, "max-age=0, no-store"); public String getJsonErrorPage(String page) { return "json_"+ page; @@ -80,14 +78,6 @@ public void setScriptsPath(String scriptsPath) { this.scriptsPath = scriptsPath; } - public Type getSerializerType() { - return serializerType; - } - - public void setSerializerType(Type serializerType) { - this.serializerType = serializerType; - } - public String getInterruptionErrorPage() { return interruptionErrorPage; } @@ -152,4 +142,12 @@ public void setDefaultResponseHeaders(Map defaultResponseHeaders this.defaultResponseHeaders = defaultResponseHeaders; } + public Map> getSerializeRules() { + return serializeRules; + } + + public void setSerializeRules(Map> serializeRules) { + this.serializeRules = serializeRules; + } + } diff --git a/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/serialize/Type.java b/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/serialize/Type.java index f67c07bcf0f..73c075cce17 100644 --- a/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/serialize/Type.java +++ b/jans-auth-server/agama/model/src/main/java/io/jans/agama/model/serialize/Type.java @@ -1,4 +1,3 @@ package io.jans.agama.model.serialize; -public enum Type { KRYO, FST } - +public enum Type { KRYO, JAVA } diff --git a/jans-auth-server/server/conf/jans-config.json b/jans-auth-server/server/conf/jans-config.json index 7fbcd740d85..78e91862de8 100644 --- a/jans-auth-server/server/conf/jans-config.json +++ b/jans-auth-server/server/conf/jans-config.json @@ -459,12 +459,11 @@ "deviceAuthzTokenPollInterval": 5, "deviceAuthzResponseTypeToProcessAuthz": "code", "agamaConfiguration": { - "enabled": false, + "enabled": true, "rootDir": "/opt/jans/jetty/jans-auth/agama", "templatesPath": "/ftl", "scriptsPath": "/scripts", - "serializerType": "KRYO", - "maxItemsLoggedInCollections": 7, + "maxItemsLoggedInCollections": 9, "pageMismatchErrorPage": "mismatch.ftlh", "interruptionErrorPage": "timeout.ftlh", "crashErrorPage": "crash.ftlh", @@ -472,6 +471,10 @@ "bridgeScriptPage": "agama.xhtml", "defaultResponseHeaders": { "Cache-Control": "max-age=0, no-store" + }, + "serializeRules": { + "JAVA": ["java", "sun", "com.sun", "jdk"], + "KRYO": [] } }, "blockWebviewAuthorizationEnabled": false, diff --git a/jans-bom/pom.xml b/jans-bom/pom.xml index f8f518aa9a7..cf1a255c559 100644 --- a/jans-bom/pom.xml +++ b/jans-bom/pom.xml @@ -302,7 +302,7 @@ com.nimbusds nimbus-jose-jwt - 9.30.2 + 9.37.1 com.nimbusds diff --git a/jans-config-api/docs/jans-config-api-swagger.yaml b/jans-config-api/docs/jans-config-api-swagger.yaml index e0864c74e15..0e6083b9440 100644 --- a/jans-config-api/docs/jans-config-api-swagger.yaml +++ b/jans-config-api/docs/jans-config-api-swagger.yaml @@ -8547,11 +8547,6 @@ components: type: string scriptsPath: type: string - serializerType: - type: string - enum: - - KRYO - - FST maxItemsLoggedInCollections: type: integer format: int32 @@ -8571,6 +8566,12 @@ components: type: object additionalProperties: type: string + serializeRules: + type: object + additionalProperties: + type: array + items: + type: string JsonNode: type: object SsaConfiguration: diff --git a/jans-linux-setup/jans_setup/templates/jans-auth/jans-auth-config.json b/jans-linux-setup/jans_setup/templates/jans-auth/jans-auth-config.json index 3a31963c8aa..96d780229e0 100644 --- a/jans-linux-setup/jans_setup/templates/jans-auth/jans-auth-config.json +++ b/jans-linux-setup/jans_setup/templates/jans-auth/jans-auth-config.json @@ -511,7 +511,6 @@ "rootDir": "/opt/jans/jetty/jans-auth/agama", "templatesPath": "/ftl", "scriptsPath": "/scripts", - "serializerType": "KRYO", "maxItemsLoggedInCollections": 9, "pageMismatchErrorPage": "mismatch.ftlh", "interruptionErrorPage": "timeout.ftlh", @@ -520,6 +519,10 @@ "bridgeScriptPage": "agama.xhtml", "defaultResponseHeaders": { "Cache-Control": "max-age=0, no-store" + }, + "serializeRules": { + "JAVA": ["java", "sun", "com.sun", "jdk"], + "KRYO": [] } }, "blockWebviewAuthorizationEnabled": false, diff --git a/jans-linux-setup/jans_setup/templates/jetty/jans-auth b/jans-linux-setup/jans_setup/templates/jetty/jans-auth index 2013e278b7b..dbd17a1d924 100644 --- a/jans-linux-setup/jans_setup/templates/jetty/jans-auth +++ b/jans-linux-setup/jans_setup/templates/jetty/jans-auth @@ -1,6 +1,6 @@ JAVA_HOME=%(jre_home)s JAVA=$JAVA_HOME/bin/java -JAVA_OPTIONS="--add-opens java.base/java.lang=ALL-UNNAMED -server -Xms%(jans-auth_min_heap_mem)sm -Xmx%(jans-auth_max_heap_mem)sm -XX:+DisableExplicitGC -Djans.base=%(jansBaseFolder)s -Dserver.base=%(jetty_base)s/jans-auth -Dlog.base=%(jetty_base)s/jans-auth -Dpython.home=%(jython_home)s" +JAVA_OPTIONS="-server -Xms%(jans-auth_min_heap_mem)sm -Xmx%(jans-auth_max_heap_mem)sm -XX:+DisableExplicitGC -Djans.base=%(jansBaseFolder)s -Dserver.base=%(jetty_base)s/jans-auth -Dlog.base=%(jetty_base)s/jans-auth -Dpython.home=%(jython_home)s" JETTY_HOME=%(jetty_home)s JETTY_BASE=%(jetty_base)s/jans-auth