KB Article #177221

How to use the String Replace filter with a non string class attribute like http.request.uri (java.net.URI)

Using a non string message attribute in the String Replace filter results in a class cast exception. e.g. with http.request.uri


Nested fault: java.net.URI cannot be cast to java.lang.String:
java.lang.ClassCastException: java.net.URI cannot be cast to java.lang.String
at com.vordel.circuit.string.StringReplaceProcessor.invoke(StringReplaceProcessor.java:56)
at com.vordel.circuit.InvocationEngine.invokeFilter(InvocationEngine.java:150)
at com.vordel.circuit.InvocationEngine.invokeCircuit(InvocationEngine.java:42)
at com.vordel.circuit.InvocationEngine.recordCircuitInvocation(InvocationEngine.java:276)
at com.vordel.circuit.InvocationEngine.processMessage(InvocationEngine.java:239)
at com.vordel.circuit.SyntheticCircuitChainProcessor.invoke(SyntheticCircuitChainProcessor.java:64)
at com.vordel.dwe.http.HTTPPlugin.processRequest(HTTPPlugin.java:350)
at com.vordel.dwe.http.HTTPPlugin.invokeDispose(HTTPPlugin.java:358)
at com.vordel.dwe.http.HTTPPlugin.invoke(HTTPPlugin.java:135)


Resolution

Convert the the message attribute to a string with the Set Attribute Filter and use the new attribute name in the String Replace filter. The selector syntax is used to call the toString() method of java.net.URI So to convert http.request.uri you might use a Set Attribute filter configured like this:


String replace filter with attribute name equal to uri.stringified and attribute value equal to ${http.request.uri.toString()}


Now the String Replace filter can be used on the uri.stringified attribute.


--------------------------------------------------------------------------


If a later filter in your policy requires you to convert the string back to a java.net.URI, then you may see an error like: [java.lang.ClassCastException: java.lang.String cannot be cast to java.net.URI] In that case, you can use a JavaScript scripting language filter to convert the string back to a URI again. The sample code below reads the value from the string in uri.stringified and then it creates a new java.net.URI object which it stores in http.request.uri to make a full circle from the earlier example. There is also some extra boilerplate code to catch exceptions and make things easier to debug when you accidentally feed it a string that cannot be converted to a URI:


//# sorceURL=Cast String to URI Script
var script_name = "Cast String to URI";
var imp = new JavaImporter(com.vordel.trace);
with (imp) {
    function invoke(msg) {
        try {
            var uri_str = msg.get("uri.stringified");
            Trace.debug(script_name + " script URI = " + uri_str);
            msg.put("http.request.uri", new java.net.URI(uri_str));
            return true;
        } catch (e) {
            Trace.error(script_name + " script error: " + e.stack);
            msg.put("circuit.exception", e);
        }
        return false;
    }
};


Note: This sample code uses Nashorn JavaScript engine extensions like the JavaImporter and sourceURL comment. It will not work with the older Rhino JavaScript engine, which is deprecated and which should no longer be used. Nashorn is simply labeled as "JavaScript" in the UI, while Rhino is called "JavaScript (Rhino engine JRE 7 and earlier)".