i'm trying to make my listener work with the ews java API but i can't.. I hope you can help me !
I've done the following steps:
1)Connect to the exchange web service
ExchangeService newService = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
newService.setUrl("https://myurl/ews/Exchange.asmx");
ExchangeCredentials credentials = new WebCredentials("user","password");
newService.setCredentials(credentials);
2) Then subscribe to the push notifications:
@Override
public PushSubscription subscribeToPushNotifications(){
URI callback = null;
PushSubscription pushSubscription = null;
try{
logger.info("Subscribing to push notifications.. Endpoint Listener URI = " + config.getNotificationListenerURI());
callback = new URI(config.getNotificationListenerURI());
pushSubscription = service.subscribeToPushNotifications(
getFoldersForSubscription(), callback , 5, null,
EventType.NewMail, EventType.Created, EventType.Deleted, EventType.Modified, EventType.Moved);
logger.info("Done! --> PushSubscription ID= " + pushSubscription.getId());
}catch(URISyntaxException e){
logger.error("EWS ==> Invalid Notification Listener URL = " + config.getNotificationListenerURI() +". Please, verify <integration-modules>");
Throwables.propagate(e);
}catch (Exception e){
logger.error("EWS ==> Error subscribing to push notifications", e);
Throwables.propagate(e);
}
return pushSubscription;
}
3) Then developed my Listener as a Restful webservice (i've tested with a dummy method and it's working)
First define the servlet:
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
After that, create the Listener class to map the urls defined in the servlet (the one i passed to the ExchangeService)
@Path("/emailnotification")
public class ExchangeNotificationListener {
private static final Log logger = LogFactory.getLog(ExchangeNotificationListener.class);
@Path("/incomingevent")
@POST()
@Produces(MediaType.TEXT_XML)
public Response onNotificationReceived() throws Exception {
logger.info("Received EWS notification !!!");
return Response.ok().build();
}
@GET
@Path("/{param}")
public Response getMsg(@PathParam("param") String msg) {
String output = "Jersey say : " + msg;
return Response.status(200).entity(output).build();
}
}
BUT i set the breakpoint and then send me an email but nothings happens.. What i am doing wrong / missing ??? Please help !
P.S : the dummy method getMsg() works, so the rest service is working
Thanks in advance !!
The problem was the firewall blocking the incoming EWS messages into my dev environment.
Here is the final version of the listener. I hope someone could find it usefull
@Path("/emailnotification")
public class ExchangeNotificationListener {
private static final Log logger = LogFactory.getLog(ExchangeNotificationListener.class);
private static final String OK = "OK";
private static final String UNSUBSCRIBE = "Unsubscribe";
/**
* This method receives a SOAP message from Microsoft Exchange Web Services, parses it into a ExchangeNotification object,
* do some business logic and sends an ACK response to keep the subscription alive.
*
* @param request
* EWS Push Notification request
* @param response
* @throws Exception
*/
@Path("/incomingevent")
@POST()
@Consumes(MediaType.TEXT_XML)
public void onNotificationReceived(@Context HttpServletRequest request, @Context HttpServletResponse response)
throws Exception {
// Establish the start time so we can report total elapsed time to execute the call later.
long startTime = GregorianCalendar.getInstance().getTimeInMillis();
long endTime;
// Retrieve the EWS Notification message as an XML document
Document notificationXML = loadXML(IOUtils.toString(request.getInputStream()));
// Deserialize the document
ExchangeNotification notif = new ExchangeNotification(notificationXML);
// We need the subscription id in order to proceed
String subscriptionId = notif.getSubscriptionId();
if (isBlank(subscriptionId)) {
logger.error("SOAP Envelope MUST contains the subscriptionId");
// If we did not successfully parse the XML document, tell Exchange that we got a bad request.
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
if (!ExchangeSubscriptionMap.getInstance().getSubscriptionsMap().containsKey(subscriptionId)) {
logger.warn("SubscriptionId = " + subscriptionId
+ " was not found in the subscriptions map. Unsubscribing...");
sendResponse(response, UNSUBSCRIBE);
return;
}
// Do some logic here depending on the current EventType
businessLogic(notif, response);
// Flush the buffer and report the total time taken to execute for this notification.
response.flushBuffer();
endTime = GregorianCalendar.getInstance().getTimeInMillis();
logger.debug(String.format("Total execution time: %1$s (ms)", (Long) (endTime - startTime)));
}
/**
* Sends an ACK response to the Exchange Web Service
*
* @param response
* @param msg
* the content of the response message
*/
private void sendResponse(HttpServletResponse response, String msg) {
try {
// Build the HTTP response
String str = ExchangeUtils.getResponseXML(msg);
response.setCharacterEncoding("UTF-8");
response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/xml; charset=UTF-8");
response.setContentLength(str.length());
// Send the response.
PrintWriter w = response.getWriter();
w.print(str);
w.flush();
} catch (IOException e) {
logger.error("Error getting the response writer");
Throwables.propagate(e);
}
}
/**
* Process the incoming notification, do some business logic and send an ACK response to Exchange
*
* @param notification
* to be processed
* @param response
* to be returned
*/
@SuppressWarnings("unchecked")
private void businessLogic(ExchangeNotification notification, HttpServletResponse response) {
try {
// Iterate the notification events
for (SubscriptionEvent event : notification.getEvents()) {
// Only take care of the Modified event
switch (event.getEventType()) {
case MODIFIED:
// logic here
// Get the ExchangeService instance this user use for Subscribing
MSExchangeServiceManager service = ExchangeSubscriptionMap.getInstance().getSubscriptionsMap().get(notification.getSubscriptionId()).getService();
//e.g: service.getUnreadMessages(WellKnownFolderName.Inbox));
break;
default:
logger.debug("Skipping: " + event.getEventType());
break;
}
}
// Finally, send the response.
sendResponse(response, OK);
} catch (Exception e) {
logger.error("EWS ==> Error processing request", e.getCause());
Throwables.propagate(e);
}
}
/**
* Create a XML Document using a raw xml string
*
* @param rawXML
* the raw xml string to be converted
* @return XML EWS Nofitication document
*/
private Document loadXML(String rawXML) {
Document doc = null;
try {
logger.debug("Incoming request input stream : " + rawXML);
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
// turn on this flag in order to resolve manually the namespaces of the document
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
doc = builder.parse(new InputSource(new ByteArrayInputStream(rawXML.getBytes("UTF-8"))));
} catch (ParserConfigurationException e) {
logger.error("Unable to create a new DocumentBuilder");
Throwables.propagate(e);
} catch (UnsupportedEncodingException e) {
logger.error("Unsupported Encoding: UTF-8");
Throwables.propagate(e);
} catch (SAXException e) {
logger.error("Error parsing XML");
Throwables.propagate(e);
} catch (IOException e) {
logger.error("IOException");
Throwables.propagate(e);
}
return doc;
}
}