Whether you're using Nuxeo as an ECM or DAM in your organization, there's almost always a need to integrate with external systems.
Sometimes, those systems need to call a publicly accessible endpoint on your Nuxeo server-like to notify you when a job is done or to push data back into the platform.
Let me show you how easy it is to create such an endpoint using Nuxeo WebEngine with JAX-RS.
Use Case
In this example, I was working on an integration with an external archiving system. We submit restore requests from Nuxeo, and when the restore is completed on their end, their system needs to call an open URL on the Nuxeo side to let us know that the job is finished.
The endpoint must support:
- Unauthenticated access
- A POST request
- A custom JSON payload
Objective
We want to add an open, unauthenticated endpoint that accepts a POST request like this:
POST http://localhost:8080/nuxeo/site/syncstatus/update
With the payload:
{
"jobId": "3da5bea3-4a09-3180-8c72-ad290b80f08c",
"eventClass": "JOB",
"status": "COMPLETE"
}
Step 1: Contribute the Open URL
Nuxeo supports JAX-RS via WebEngine, which is exactly what we'll use to expose this API: ๐ https://doc.nuxeo.com/nxdoc/webengine-jax-rs/
In your XML contribution, register the open URL:
<extension point="openUrl"
target="org.nuxeo.ecm.platform.ui.web.auth.service.PluggableAuthenticationService">
<openUrl name="syncstatus">
<grantPattern>${org.nuxeo.ecm.contextPath}/site/syncstatus</grantPattern>
</openUrl>
</extension>
Step 2: Create the Endpoint Class
Create a new class extending ModuleRoot, mapped to /syncstatus. ๐ Reference: ModuleRoot.java
@Path("/syncstatus")
@Produces("text/html;charset=UTF-8")
@WebObject(type = "syncstatus")
/**
* Open endpoint to receive callback
*/
public class SyncStatus extends ModuleRoot {
public static final Log log = LogFactory.getLog(SyncStatus.class);
@Context
private HttpServletRequest request;
@POST
@Path("update")
@Produces(MediaType.APPLICATION_JSON)
public Response syncJob(JobPayload request) {
return syncJob(request.getJobId(), request.getEventClass());
}
}
Step 3: Create the Payload Class
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class JobPayload {
private String jobId;
private String eventClass;
private String status;
public JobPayload() {}
public String getJobId() { return jobId; }
public void setJobId(String jobId) { this.jobId = jobId; }
public String getEventClass() { return eventClass; }
public void setEventClass(String eventClass) { this.eventClass = eventClass; }
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
}
Step 4: Register the Custom JSON Reader
@Provider
@Consumes(MediaType.APPLICATION_JSON)
public class JobPayloadReader implements MessageBodyReader<JobPayload> {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return JobPayload.class.isAssignableFrom(type)
&& MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType);
}
@Override
public JobPayload readFrom(Class<JobPayload> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException {
return objectMapper.readValue(entityStream, JobPayload.class);
}
}
Result
That's it! You now have an open Nuxeo endpoint that accepts POST requests with a custom JSON payload.
Access considerations
- Only use unauthenticated endpoints when absolutely necessary.
- If the endpoint should be private, simply don't contribute it via
openUrl.
Test the endpoint
curl -X POST http://localhost:8080/nuxeo/site/syncstatus/update \
-H "Content-Type: application/json" \
-d '{
"jobId": "3da5bea3-4a09-3180-8c72-ad290b80f08c",
"eventClass": "JOB",
"status": "COMPLETE"
}'
Let me know if you've built similar integrations or want to explore more advanced patterns like token auth or validation.
Work with Maretha
Working through a content platform challenge?
Bring your platform, constraints and questions. Let us help you work through the approach.
Discuss your project โ