Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

INTEXT-19: Push Notification adapters for Android devices #11

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ logs
nohup.out
out
target
spring-integration-aws/src/test/resources/awscredentials.properties
spring-integration-aws/src/test/resources/awscredentials.properties
spring-integration-pushnotify/src/test/resources/services.properties
354 changes: 354 additions & 0 deletions spring-integration-pushnotify/README.md

Large diffs are not rendered by default.

Binary file added spring-integration-pushnotify/images/GcmFlow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 91 additions & 0 deletions spring-integration-pushnotify/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-pushnotify</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<description>
The project has components that enable java applications to send push notifications to
hand held devices running on Android platform. The Google Cloud Messaging (GCM) service is
used to send out notifications to the hand held devices running on Android platform.
</description>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>

<prerequisites>
<maven>2.2.1</maven>
</prerequisites>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Tests.java</include>
</includes>
<excludes>
<exclude>**/*Abstract*.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>springsource-libs-milestone</id>
<name>Spring Framework Maven Milestone Repository</name>
<url>https://repo.springsource.org/libs-milestone</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>2.2.0.M3</version>
</dependency>

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.9</version>
</dependency>

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>

<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-test</artifactId>
<version>2.2.0.M3</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.pushnotify;

import java.io.IOException;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;

/**
* The Common superclass implementing the common validations and other functionalities
* for the {@link PushNotifyService} implementations
*
* @author Amol Nayak
*
* @since 1.0
*
*/
public abstract class AbstractPushNotifyService implements PushNotifyService {

protected final Log logger = LogFactory.getLog(getClass());

/**
* Flag to enable the service to retry the requests that were unsuccessful either due to
* network issues or some recoverable error from the server. If set to true, exponential
* backoff and retry is used. Enabled by default.
*/
private volatile boolean retryRequests = true;

private static final long INITIAL_RETRY_DELAY = 1000L;

private volatile long maxRetryDelay = 10000L; //Defaults to 10 seconds.


/**
* The implemented version does some basic validation and delegates to
* the {@link #doPush(Map, String...)
*
* @param message
* @param attributes
* @param receiverId
* @return
*/
@Override
public final PushResponse push(Map<String, Object> message, Map<String, String> attributes, String... receiverIds)
throws IOException {
Assert.notNull(message, "provided message is 'null'");
Assert.isTrue(message.size() > 0,"provided message is an empty map");
Assert.notNull(receiverIds,"provided receiver id is 'null'");
Assert.isTrue(receiverIds.length > 0, "Must provide at least on receiver id");
boolean retryRequest = retryRequests;
PushResponse response;
int base = 1;
int retryAttempt = 1; //for logging
//logic to exponentially retry the request
long delta = (long)(Math.random() * 1000);
while(true) {
response = doPush(message, attributes, receiverIds);
if(response == null && retryRequest) {
long delay = INITIAL_RETRY_DELAY * (2 * base - 1)/2;
long totalDelay = delay + delta;
if(totalDelay <= maxRetryDelay) {
String logMessage = String.format("Retry attempt %d, retrying after %d ms", retryAttempt++, totalDelay);
logger.info(logMessage);
base *= 2;
try {
Thread.sleep(totalDelay);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
else {
break;
}
}
else {
break;
}
}
return response;
}

/**
* The sub classes need to implement the method that will push the given messages to the provided
* receiver ids
*
* @param message
* @param attributes
* @param receiverIds
* @return
*/
protected abstract PushResponse doPush(Map<String, Object> message, Map<String, String> attributes, String... receiverIds) throws IOException;

/**
* Checks if requests are to be retried using exponential backoff or not.
* @return
*/
public boolean shouldRetryRequests() {
return retryRequests;
}

/**
* Set to true if requests are to be retried using exponential backoff.
* @param retryRequests
*/
public void setRetryRequests(boolean retryRequests) {
this.retryRequests = retryRequests;
}

/**
* Gets the max interval for which the request thread would sleep to retry a request
* to the service
*
*/
public long getMaxRetryDelay() {
return maxRetryDelay;
}

/**
* Sets the max interval in milli seconds for which the thread will sleep before retrying
* the request again with the push services
*
* @param maxRetryInterval
*/
public void setMaxRetryDelay(long maxRetryDelay) {
this.maxRetryDelay = maxRetryDelay;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.pushnotify;

import java.io.IOException;
import java.util.Map;

/**
* The core service that would be performing the push operations to the hand held
* devices from the java applications
*
* @author Amol Nayak
*
* @since 1.0
*
*/
public interface PushNotifyService {

/**
* Push the message to multiple receivers identified by these multiple
* receiver ids.
*
* @param message The map that represents the key value pair of the message to be sent.
* @param attributes The map of attributes apart from the message that might be needed to be
* sent along with the request. These could be the service specific configuration parameters
* that would be used to change the behavior of the message sent. The values of the attributes
* if defined by the implementation.
* @param receiverId The unique identifiers that identifies the target devices to which the
* notification is to be sent.
* @return
*/
PushResponse push(Map<String, Object> message, Map<String, String> attributes, String... receiverIds) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.pushnotify;

/**
* The response for the invocation of push to a single device using the {@link PushNotifyService}
*
* @author Amol Nayak
*
* @since 1.0
*
*/
public interface PushResponse {

/**
* True if the response is a multicast response, that is the response is for a request to
* push to multiple devices in one request
*
* @return
*/
boolean isMulticast();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.pushnotify.config.xml;

import org.springframework.integration.config.xml.IntegrationNamespaceHandler;

/**
* The namespace handler for the Integration push notify adapters
*
* @author Amol Nayak
*
* @since 1.0
*
*/
public class IntegrationPushNotifyNamespaceHandler extends IntegrationNamespaceHandler {

@Override
public void init() {
this.registerBeanDefinitionParser("outbound-gateway", new OutboundGatewayParser());
}
}
Loading