IllegalArgumentException reading property set

Documentation states that "Property set files support the same syntax as Java properties files":

- https://cloud.google.com/apigee/docs/api-platform/cache/property-sets#property-set-files

But Apigee X fails (IllegalArgumentException) when the key contains curly braces (example: "/users/{id}").

Properties file (config.properties):

 /users=a
 /users/{id}=b

AssignMessage policy, set the config-key flow variable to "/users/{id}":

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-set-config-key">
    <DisplayName>AM-set-config-key</DisplayName>
    <AssignVariable>
        <Name>config-key</Name>
        <Value>/users/{id}</Value>
    </AssignVariable>
</AssignMessage>

AssignMessage policy, read the value from the property set using config-key as key:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage continueOnError="false" enabled="true" name="AM-get-config-value">
    <DisplayName>AM-get-config-value</DisplayName>
    <AssignVariable>
        <Name>config-value</Name>
        <PropertySetRef>config.{config-key}</PropertySetRef>
    </AssignVariable>
</AssignMessage>

Error:

{"fault":{"faultstring":"Illegal propertyset key {} [config.\/users\/{id}]","detail":{"errorcode":"Bad Request"}}}
error.class: java.lang.IllegalArgumentException

Also tried with a JavaScript policy, same error:

print(context.getVariable('propertyset.config./users/{id}'));

Also tried with a standalone Java 8 application (outside Apigee). It worked fine as far curly braces in keys are valid in Java:

Reader reader = new FileReader("config.properties");
Properties properties = new Properties();
properties.load(reader);
System.out.println(properties.getProperty("/users/{id}")); // output: "b"

Is it a bug? Any workaround?

test-rev5-2021-03-25.zip

0 8 445
8 REPLIES 8

workaround.... hmmm..

What is the reason you want to use curlies in the KEY value in a property set?

Why is this not acceptable:

/users=a
/users/id=b

?

The properties file is automatically generated from an OpenAPI specification. The keys are the paths of the specification. And, in this context, "/users/id" is very different from "/users/{id}".

Of course, curly braces could be replaced with others characters, but I would prefer to keep original paths instead of creating new ones.

I tried to encode them in different ways, but no luck.

I see.

It feels like this is possibly a bug, or possibly just a limitation and the Eng/PM team may just change the documentation to state "you can't use curlies in key names". If I had to wager, I'd favor the latter alternative. After all, properties values are accessible as variables, and I think curlies are not valid characters for variable names in Apigee. Aside from my own predictions, if the Eng/PM team do decide to solve this with a fix, the solution won't be available for a while.

So we are left to consider the workaround options.

What if you just attached the specification itself to the API proxy as a .json file? Then you could read and parse the file and do whatever you like with it.

or modify your properties file generator in the way you would prefer not to modify it.

Agree, it feels like a bug. IllegalArgumentException is an unexpected runtime error. I'll file an issue.

IMHO "property key names" should not be treated as "flow variable names". They are just plain strings. In fact, in the example, the key name is declared using the Value element:

The value is always interpreted as a literal string; you cannot use a flow variable as the value, even if you wrap the value in brackets ("{}").

And regarding suggested workaround. To extract the required information from the specification for each request could a bit expensive. But of course, the JSON file could store "cooked" values, and a JavaScript policy could be used to read them.

Anyway, thanks for your time!

Sure, glad to help.

I'm not clear on the following statement, or where you get the second statement .

IMHO "property key names" should not be treated as "flow variable names". They are just plain strings. In fact, in the example, the key name is declared using the Value element:

The value is always interpreted as a literal string; you cannot use a flow variable as the value, even if you wrap the value in brackets ("{}").

It seems you are citing an excerpt from the Apigee documentation, probably for AssignMessage / AssignVariable. And you are correct, that when you assign a variable using the Value element, THAT VALUE gets places into the variable. But I think that is not what is failing here. The value is successfully stored into the variable (in your case, the variable named config-key).

The failure is occurring when you try to refer to a property value with that key, in either of your two examples. That generates a runtime error.

As regards your IMHO, The problem is that propertyset values in fact can be retrieved as variables, as with

context.getVariable('propertyset.PROPSETNAME.KEYNAME'));

...and also in other ways as well. In Condition statements, and so on. I understand that you expressed an opinion that it should not be that way. But it is that way. So the values are available via variables, and the names of those variables depend on the key names. Agree?

Therefore they are not "flow variable names" but rather, segments of flow variable names, and must conform to the legal/valid values for those names. I suppose that is related to the runtime error you observed.

Yes, agree, I don't see them as variable names, just as key names in a properties file.

I also noticed that a key name cannot include a `.`, for example this is an illegal entry

target.basepath=config/path/for/target/dot

It returns an error:

curl https://napi-test.kurtkanaskie.net//property-set-proxy-test

{"fault":{"faultstring":"Illegal propertyset key {} [config.target.basepath]","detail":{"errorcode":"Bad Request"}}}

Some characters (".", "=") may be included in the key by escaping them with a preceding backslash character:

- https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#load-java.io.Reader-