You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by dg...@apache.org on 2021/03/31 10:32:56 UTC
[unomi] 01/01: UNOMI-449 : forward existing endpoints to jax-rs
endpoints
This is an automated email from the ASF dual-hosted git repository.
dgriffon pushed a commit to branch UNOMI-449-forward-public-endpoints
in repository https://gitbox.apache.org/repos/asf/unomi.git
commit 794176bad4faa54eab1a30d58937aeee9f40c19b
Author: David Griffon <dg...@jahia.com>
AuthorDate: Wed Mar 31 12:32:32 2021 +0200
UNOMI-449 : forward existing endpoints to jax-rs endpoints
---
.../java/org/apache/unomi/rest/ClientEndpoint.java | 50 +++++++-----
.../org/apache/unomi/rest/ContextJsonEndpoint.java | 91 +++++++++-------------
.../apache/unomi/rest/EventsCollectorEndpoint.java | 56 ++++++-------
3 files changed, 88 insertions(+), 109 deletions(-)
diff --git a/rest/src/main/java/org/apache/unomi/rest/ClientEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/ClientEndpoint.java
index fb7f046..6d0f689 100644
--- a/rest/src/main/java/org/apache/unomi/rest/ClientEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/ClientEndpoint.java
@@ -25,7 +25,6 @@ import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
import org.apache.unomi.api.Profile;
import org.apache.unomi.api.services.ConfigSharingService;
import org.apache.unomi.api.services.ProfileService;
-import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
@@ -37,9 +36,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import java.io.OutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
@@ -51,8 +48,6 @@ import java.util.Set;
* A servlet filter to serve a context-specific Javascript containing the current request context object.
*/
@WebService
-@Produces
-@Consumes(MediaType.TEXT_PLAIN)
@CrossOriginResourceSharing(
allowAllOrigins = true,
allowCredentials = true
@@ -62,30 +57,40 @@ import java.util.Set;
public class ClientEndpoint {
private static final Logger logger = LoggerFactory.getLogger(ClientEndpoint.class.getName());
- private static final long serialVersionUID = 2928875960103325238L;
+ private static final String CONTENT_DISPOSITION_HEADER_KEY = "Content-Disposition";
+
+ private static final String FILE_NAME_WO_EXT = "my-profile";
+
+ private static String getContentDispostionHeader(String extension) {
+ return String.format("attachment; filename=\"%s.%s\"", FILE_NAME_WO_EXT, extension);
+ }
@Reference
private ProfileService profileService;
@Reference
private ConfigSharingService configSharingService;
- private final String FILE_NAME_WO_EXT = "my-profile";
@Context
HttpServletRequest request;
@Context
HttpServletResponse response;
+ @OPTIONS
+ @Path("/client/{operation}/{param}")
+ public Response options() {
+ return Response.status(Response.Status.NO_CONTENT).build();
+ }
+
@GET
@Path("/client/{operation}/{param}")
public Response getClient(@PathParam("operation") String operation, @PathParam("param") String param) throws JsonProcessingException {
- switch (operation) {
- case "myprofile":
- if (((String) configSharingService.getProperty("allowedProfileDownloadFormats")).contains(param)) {
- return donwloadCurrentProfile(param);
- } else {
- throw new InternalServerErrorException(String.format("%s is not an allowed param", param));
- }
+ if ("myprofile".equals(operation)) {
+ if (((String) configSharingService.getProperty("allowedProfileDownloadFormats")).contains(param)) {
+ return donwloadCurrentProfile(param);
+ } else {
+ throw new InternalServerErrorException(String.format("%s is not an allowed param", param));
+ }
}
throw new NotFoundException();
}
@@ -112,8 +117,9 @@ public class ClientEndpoint {
return prepareCsvFileToDownload(currentProfile, request.getParameter("vertical") != null);
case "text":
return prepareYamlFileToDownload(currentProfile, true);
+ default:
+ throw new NotFoundException();
}
-
}
}
throw new NotFoundException();
@@ -121,7 +127,8 @@ public class ClientEndpoint {
private Response prepareCsvFileToDownload(Profile currentProfile, boolean vertical) {
response.setContentType("text/csv");
- response.setHeader("Content-Disposition", "attachment; filename=\"" + FILE_NAME_WO_EXT + ".csv\"");
+
+ response.setHeader(CONTENT_DISPOSITION_HEADER_KEY, getContentDispostionHeader("csv"));
StringWriter writer = new StringWriter();
//using custom delimiter and quote character
CSVWriter csvWriter = new CSVWriter(writer);
@@ -132,12 +139,12 @@ public class ClientEndpoint {
}
} else {
Set<String> keySet = currentProfile.getProperties().keySet();
- List<String> values = new ArrayList();
+ List<String> values = new ArrayList<>();
for (Object value : currentProfile.getProperties().values()) {
values.add(value.toString().trim().replace("\n", ""));
}
- csvWriter.writeNext(keySet.toArray(new String[keySet.size()]));
- csvWriter.writeNext(values.toArray(new String[values.size()]));
+ csvWriter.writeNext(keySet.toArray(new String[0]));
+ csvWriter.writeNext(values.toArray(new String[0]));
}
Response.ResponseBuilder responseBuilder = Response.ok(writer.toString());
return responseBuilder.build();
@@ -145,7 +152,8 @@ public class ClientEndpoint {
private Response prepareJsonFileToDownload(Profile currentProfile) throws JsonProcessingException {
response.setContentType("text/json");
- response.setHeader("Content-Disposition", "attachment; filename=\"" + FILE_NAME_WO_EXT + ".json\"");
+ response.setHeader(CONTENT_DISPOSITION_HEADER_KEY, getContentDispostionHeader("json"));
+
ObjectMapper mapper = new ObjectMapper();
String jsonContent = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(currentProfile.getProperties());
return Response.ok(jsonContent).build();
@@ -153,7 +161,7 @@ public class ClientEndpoint {
private Response prepareYamlFileToDownload(Profile currentProfile, boolean asTextFile) throws JsonProcessingException {
response.setContentType("text/" + (asTextFile ? "plain" : "yaml"));
- response.setHeader("Content-Disposition", "attachment; filename=\"" + FILE_NAME_WO_EXT + (asTextFile ? ".txt" : ".yml") + "\"");
+ response.setHeader(CONTENT_DISPOSITION_HEADER_KEY, getContentDispostionHeader((asTextFile ? "txt" : "yml")));
YAMLFactory yf = new YAMLFactory();
ObjectMapper mapper = new ObjectMapper(yf);
String yamlContent = mapper.writeValueAsString(currentProfile.getProperties());
diff --git a/rest/src/main/java/org/apache/unomi/rest/ContextJsonEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/ContextJsonEndpoint.java
index 9a205ca..26e787c 100644
--- a/rest/src/main/java/org/apache/unomi/rest/ContextJsonEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/ContextJsonEndpoint.java
@@ -17,15 +17,11 @@
package org.apache.unomi.rest;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
-import org.apache.cxf.jaxrs.utils.ExceptionUtils;
import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
import org.apache.unomi.api.*;
import org.apache.unomi.api.conditions.Condition;
import org.apache.unomi.api.services.*;
-import org.apache.unomi.persistence.spi.CustomObjectMapper;
import org.apache.unomi.utils.Changes;
import org.apache.unomi.utils.HttpUtils;
import org.apache.unomi.utils.ServletCommon;
@@ -48,7 +44,7 @@ import java.util.*;
@WebService
@Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
-@Consumes(MediaType.TEXT_PLAIN)
+@Consumes(MediaType.APPLICATION_JSON)
@CrossOriginResourceSharing(
allowAllOrigins = true,
allowCredentials = true
@@ -82,9 +78,22 @@ public class ContextJsonEndpoint {
@Reference
private ConfigSharingService configSharingService;
+ @OPTIONS
+ @Path("/context.json")
+ public Response options() {
+ return Response.status(Response.Status.NO_CONTENT).header("Access-Control-Allow-Origin", "*").build();
+ }
+
@POST
@Path("/context.json")
- public ContextResponse getContextJSON(String contextRequestAsString, @QueryParam("timestamp") Long timestampAsLong, @CookieParam("context-profile-id") String cookieProfileId) {
+ public ContextResponse getContextJSON(
+ ContextRequest contextRequest,
+ @QueryParam("personaId") String personaId,
+ @QueryParam("sessionId") String sessionId,
+ @QueryParam("timestamp") Long timestampAsLong,
+ @QueryParam("invalidateProfile") boolean invalidateProfile,
+ @QueryParam("invalidateSession") boolean invalidateSession
+ ) {
Date timestamp = new Date();
if (timestampAsLong != null) {
timestamp = new Date(timestampAsLong);
@@ -93,7 +102,6 @@ public class ContextJsonEndpoint {
// Handle persona
Profile profile = null;
Session session = null;
- String personaId = request.getParameter("personaId");
if (personaId != null) {
PersonaWithSessions personaWithSessions = profileService.loadPersonaWithSessions(personaId);
if (personaWithSessions == null) {
@@ -105,32 +113,16 @@ public class ContextJsonEndpoint {
}
}
- // Extract payload
- ContextRequest contextRequest = null;
String scope = null;
- String sessionId = null;
- String profileId = null;
- ObjectMapper mapper = CustomObjectMapper.getObjectMapper();
- JsonFactory factory = mapper.getFactory();
- try {
- contextRequest = mapper.readValue(factory.createParser(contextRequestAsString), ContextRequest.class);
- } catch (Exception e) {
- logger.error("Cannot deserialize the context request payload. See debug level for more information");
- if (logger.isDebugEnabled()) {
- logger.debug("Cannot deserialize the context request payload because of {}", e.getMessage(), e);
- }
- throw ExceptionUtils.toHttpException(e, null);
- }
if (contextRequest.getSource() != null) {
scope = contextRequest.getSource().getScope();
}
- sessionId = contextRequest.getSessionId();
- profileId = contextRequest.getProfileId();
- if (sessionId == null) {
- sessionId = request.getParameter("sessionId");
+ if (contextRequest.getSessionId() != null) {
+ sessionId = contextRequest.getSessionId();
}
+ String profileId = contextRequest.getProfileId();
if (profileId == null) {
// Get profile id from the cookie
profileId = ServletCommon.getProfileIdCookieValue(request, (String) configSharingService.getProperty("profileIdCookieName"));
@@ -149,18 +141,16 @@ public class ContextJsonEndpoint {
// Not a persona, resolve profile now
boolean profileCreated = false;
- boolean invalidateProfile = request.getParameter("invalidateProfile") != null ?
- new Boolean(request.getParameter("invalidateProfile")) : false;
if (profileId == null || invalidateProfile) {
// no profileId cookie was found or the profile has to be invalidated, we generate a new one and create the profile in the profile service
- profile = createNewProfile(null, response, timestamp);
+ profile = createNewProfile(null, timestamp);
profileCreated = true;
} else {
profile = profileService.load(profileId);
if (profile == null) {
// this can happen if we have an old cookie but have reset the server,
// or if we merged the profiles and somehow this cookie didn't get updated.
- profile = createNewProfile(profileId, response, timestamp);
+ profile = createNewProfile(profileId, timestamp);
profileCreated = true;
} else {
Changes changesObject = checkMergedProfile(profile, session);
@@ -170,8 +160,6 @@ public class ContextJsonEndpoint {
}
Profile sessionProfile;
- boolean invalidateSession = request.getParameter("invalidateSession") != null ?
- new Boolean(request.getParameter("invalidateSession")) : false;
if (StringUtils.isNotBlank(sessionId) && !invalidateSession) {
session = profileService.loadSession(sessionId, timestamp);
if (session != null) {
@@ -256,11 +244,9 @@ public class ContextJsonEndpoint {
contextResponse.setSessionId(sessionId);
}
- if (contextRequest != null) {
- Changes changesObject = handleRequest(contextRequest, session, profile, contextResponse, request, response, timestamp);
- changes |= changesObject.getChangeType();
- profile = changesObject.getProfile();
- }
+ Changes changesObject = handleRequest(contextRequest, session, profile, contextResponse, request, response, timestamp);
+ changes |= changesObject.getChangeType();
+ profile = changesObject.getProfile();
if ((changes & EventService.PROFILE_UPDATED) == EventService.PROFILE_UPDATED) {
profileService.save(profile);
@@ -296,7 +282,6 @@ public class ContextJsonEndpoint {
}
} else {
logger.warn("Couldn't find merged profile {}, falling back to profile {}", masterProfileId, currentProfile.getItemId());
- profile = currentProfile;
profile.setMergedWith(null);
changes = EventService.PROFILE_UPDATED;
}
@@ -379,25 +364,23 @@ public class ContextJsonEndpoint {
* @param session
*/
private void processOverrides(ContextRequest contextRequest, Profile profile, Session session) {
- if (profile instanceof Persona) {
- if (contextRequest.getProfileOverrides() != null) {
- if (contextRequest.getProfileOverrides().getScores() != null) {
- profile.setScores(contextRequest.getProfileOverrides().getScores());
- }
- if (contextRequest.getProfileOverrides().getSegments() != null) {
- profile.setSegments(contextRequest.getProfileOverrides().getSegments());
- }
- if (contextRequest.getProfileOverrides().getProperties() != null) {
- profile.setProperties(contextRequest.getProfileOverrides().getProperties());
- }
- if (contextRequest.getSessionPropertiesOverrides() != null && session != null) {
- session.setProperties(contextRequest.getSessionPropertiesOverrides());
- }
+ if (profile instanceof Persona && contextRequest.getProfileOverrides() != null) {
+ if (contextRequest.getProfileOverrides().getScores() != null) {
+ profile.setScores(contextRequest.getProfileOverrides().getScores());
+ }
+ if (contextRequest.getProfileOverrides().getSegments() != null) {
+ profile.setSegments(contextRequest.getProfileOverrides().getSegments());
+ }
+ if (contextRequest.getProfileOverrides().getProperties() != null) {
+ profile.setProperties(contextRequest.getProfileOverrides().getProperties());
+ }
+ if (contextRequest.getSessionPropertiesOverrides() != null && session != null) {
+ session.setProperties(contextRequest.getSessionPropertiesOverrides());
}
}
}
- private Profile createNewProfile(String existingProfileId, ServletResponse response, Date timestamp) {
+ private Profile createNewProfile(String existingProfileId, Date timestamp) {
Profile profile;
String profileId = existingProfileId;
if (profileId == null) {
@@ -443,7 +426,7 @@ public class ContextJsonEndpoint {
List<PersonalizationService.PersonalizationRequest> result = new ArrayList<>();
for (PersonalizationService.PersonalizationRequest personalizationRequest : personalizations) {
List<PersonalizationService.PersonalizedContent> personalizedContents = sanitizePersonalizedContentObjects(personalizationRequest.getContents());
- if (personalizedContents != null && personalizedContents.size() > 0) {
+ if (personalizedContents != null && !personalizedContents.isEmpty()) {
result.add(personalizationRequest);
}
}
diff --git a/rest/src/main/java/org/apache/unomi/rest/EventsCollectorEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/EventsCollectorEndpoint.java
index a673fd3..e0e603a 100644
--- a/rest/src/main/java/org/apache/unomi/rest/EventsCollectorEndpoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/EventsCollectorEndpoint.java
@@ -17,43 +17,33 @@
package org.apache.unomi.rest;
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
-import org.apache.unomi.api.Event;
-import org.apache.unomi.api.EventsCollectorRequest;
-import org.apache.unomi.api.Persona;
-import org.apache.unomi.api.Profile;
-import org.apache.unomi.api.Session;
+import org.apache.unomi.api.*;
import org.apache.unomi.api.services.ConfigSharingService;
import org.apache.unomi.api.services.EventService;
import org.apache.unomi.api.services.PrivacyService;
import org.apache.unomi.api.services.ProfileService;
-import org.apache.unomi.persistence.spi.CustomObjectMapper;
import org.apache.unomi.utils.Changes;
import org.apache.unomi.utils.ServletCommon;
-import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jws.WebService;
-import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
-import java.io.IOException;
-import java.rmi.RemoteException;
+import javax.ws.rs.core.Response;
import java.util.Date;
import java.util.UUID;
@WebService
@Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
-@Consumes(MediaType.TEXT_PLAIN)
+@Consumes(MediaType.APPLICATION_JSON)
@CrossOriginResourceSharing(
allowAllOrigins = true,
allowCredentials = true
@@ -77,36 +67,30 @@ public class EventsCollectorEndpoint {
@Context
HttpServletResponse response;
+ @OPTIONS
+ @Path("/eventcollector")
+ public Response options() {
+ return Response.status(Response.Status.NO_CONTENT).build();
+ }
+
@GET
@Path("/eventcollector")
- public EventCollectorResponse get(String eventsCollectorRequestAsString, @QueryParam("timestamp") Long timestampAsString) throws IOException {
- return doEvent(eventsCollectorRequestAsString, timestampAsString);
+ public EventCollectorResponse collectAsGet(EventsCollectorRequest eventsCollectorRequest, @QueryParam("timestamp") Long timestampAsString) {
+ return doEvent(eventsCollectorRequest, timestampAsString);
}
@POST
@Path("/eventcollector")
- public EventCollectorResponse post(String eventsCollectorRequestAsString, @QueryParam("timestamp") Long timestampAsLong) throws IOException {
- return doEvent(eventsCollectorRequestAsString, timestampAsLong);
+ public EventCollectorResponse collectAsPost(EventsCollectorRequest eventsCollectorRequest, @QueryParam("timestamp") Long timestampAsLong) {
+ return doEvent(eventsCollectorRequest, timestampAsLong);
}
- private EventCollectorResponse doEvent(String eventsCollectorRequestAsString, Long timestampAsLong) throws IOException {
+ private EventCollectorResponse doEvent(EventsCollectorRequest eventsCollectorRequest, Long timestampAsLong) {
Date timestamp = new Date();
if (timestampAsLong != null) {
timestamp = new Date(timestampAsLong);
}
-
- ObjectMapper mapper = CustomObjectMapper.getObjectMapper();
- JsonFactory factory = mapper.getFactory();
- EventsCollectorRequest eventsCollectorRequest;
- try {
- eventsCollectorRequest = mapper.readValue(factory.createParser(eventsCollectorRequestAsString), EventsCollectorRequest.class);
- } catch (Exception e) {
- if (logger.isDebugEnabled()) {
- logger.debug("Cannot parse eventsCollectorRequest: {}", eventsCollectorRequestAsString, e);
- }
- throw new RemoteException("Cannot read payload. See debug level for more information");
- }
if (eventsCollectorRequest == null || eventsCollectorRequest.getEvents() == null) {
throw new InternalServerErrorException("No events found");
}
@@ -125,8 +109,8 @@ public class EventsCollectorEndpoint {
// Get the first available scope that is not equal to systemscope to create the session otherwise systemscope will be used
for (Event event : eventsCollectorRequest.getEvents()) {
if (StringUtils.isNotBlank(event.getEventType())) {
- if (StringUtils.isNotBlank(event.getScope()) && !event.getScope().equals("systemscope")) {
- scope = event.getScope();
+ if (StringUtils.isNotBlank(event.getSourceId()) && !event.getSourceId().equals("systemscope")) {
+ scope = event.getSourceId();
break;
} else if (event.getSource() != null && StringUtils.isNotBlank(event.getSource().getScope()) && !event.getSource().getScope().equals("systemscope")) {
scope = event.getSource().getScope();
@@ -134,6 +118,7 @@ public class EventsCollectorEndpoint {
}
}
}
+ logger.debug("scope is now {}", scope);
String cookieProfileId = ServletCommon.getProfileIdCookieValue(request, (String) configSharingService.getProperty("profileIdCookieName"));
if (StringUtils.isNotBlank(cookieProfileId)) {
profile = profileService.load(cookieProfileId);
@@ -154,11 +139,13 @@ public class EventsCollectorEndpoint {
*/
} else {
Profile sessionProfile = session.getProfile();
+ final String errorMessage = String.format("No valid profile found or persona found for profileId=%s, aborting request !", session.getProfileId());
if (sessionProfile.getItemId() != null) {
// Reload up-to-date profile
profile = profileService.load(sessionProfile.getItemId());
if (profile == null || profile instanceof Persona) {
- throw new InternalServerErrorException(String.format("No valid profile found or persona found for profileId=%s, aborting request !", session.getProfileId()));
+ logger.error(errorMessage);
+ throw new InternalServerErrorException(errorMessage);
}
} else {
// Session uses anonymous profile, try to find profile from cookie
@@ -168,7 +155,8 @@ public class EventsCollectorEndpoint {
}
if (profile == null) {
- throw new InternalServerErrorException(String.format("No valid profile found or persona found for profileId=%s, aborting request !", session.getProfileId()));
+ logger.error(errorMessage);
+ throw new InternalServerErrorException(errorMessage);
}
}
}