Hi,
We have a custom Java callout we use to validate an inbound call to a Swagger spec before going anywhere near the backend service. recently we've started seeing a lot of compressed class space errors on our message processors.
The code looks like this:
public ValidationCallout() { this.objectMapper = new ObjectMapper(); ResourceMapper resourceMapper = ValidationCallout.class.getClassLoader().getResource(LINK_RELATION_MAPPING_LOCATION) == null ? DefaultResourceMapper.empty() : DefaultResourceMapper.fromFile(LINK_RELATION_MAPPING_LOCATION); this.validator = new DefaultSwaggerValidator(new SwaggerParserYamlImpl().parse(CONTRACT_LOCATION), resourceMapper); } @Override public ExecutionResult execute(MessageContext messageContext, ExecutionContext executionContext) { if (!executionContext.isErrorFlow()) { if (executionContext.isRequestFlow()) { return handleRequest(messageContext, executionContext); } else { return handleResponse(messageContext, executionContext); } } return ExecutionResult.SUCCESS; }
Apigee is erroring at the part it tries to validate the request. If the policy is disabled, the call makes it to the backend and back.
We're running some additional class trace options now to see if ObjectMapper is the culprit, but does the usage of ObjectMapper look suspicious here? Will a new instance of the enclosing class be created each request?
Many thanks
As an update on this, we are seeing no classes being unloaded whatsoever from our Java policy when looking in edge-message-processor.log with the TraceClassLoading and TraceClassUnloading JVM options on. Is this something to be concerned about?
Seems like you're facing a standard effort at diagnosing Java memory usage. Couple comments for you
I suspect that converting to use a single static ObjectMapper would relieve some memory pressure. Easy to try.
public class ValidationCallout implements Execution { private static final ObjectMapper objectMapper = new ObjectMapper(); static { // configure objectMapper here } public ValidationCallout() { // this.objectMapper = new ObjectMapper(); ResourceMapper resourceMapper = ValidationCallout.class.getClassLoader().getResource(LINK_RELATION_MAPPING_LOCATION) == null ? DefaultResourceMapper.empty() : DefaultResourceMapper.fromFile(LINK_RELATION_MAPPING_LOCATION); this.validator = new DefaultSwaggerValidator(new SwaggerParserYamlImpl().parse(CONTRACT_LOCATION), resourceMapper); } ... }
I don't know about the DefaultSwaggerValidator class - whether that is thread-safe - apparently so, since you are seeing no errors. Also don't know whether it can be safely declared as static or not. I'll let you do that research.
User | Count |
---|---|
1 | |
1 | |
1 | |
1 | |
1 |