Permalink
Browse files

Adding GenericDiscoveryContext to ease the effort it takes to impleme…

…nt discovery server custom payloads.

Migrated MapDiscoveryContext to extend GenericDiscoveryContext.

Added corresponding unit tests.
  • Loading branch information...
1 parent b8fe490 commit 1007d943f56572a7017c42acf8566ee11cbffc33 @dougnukem dougnukem committed Nov 22, 2012
View
@@ -45,6 +45,7 @@ Thumbs.db
*/target
/build
*/build
+*/bin
# IntelliJ specific files/directories
out
@@ -62,3 +63,5 @@ atlassian-ide-plugin.xml
# NetBeans specific files/directories
.nbattrs
+
+
@@ -0,0 +1,86 @@
+package com.netflix.curator.x.discovery.server.contexts;
+
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.node.ObjectNode;
+
+import com.netflix.curator.x.discovery.ProviderStrategy;
+import com.netflix.curator.x.discovery.ServiceDiscovery;
+import com.netflix.curator.x.discovery.server.rest.DiscoveryContext;
+
+/**
+ * For convenience, a version of {@link DiscoveryContext} that allows a user to
+ * specify their own custom type as the payload.
+ *
+ */
+@Provider
+public class GenericDiscoveryContext<T> implements DiscoveryContext<T>, ContextResolver<DiscoveryContext<T>>
+{
+ private final ServiceDiscovery<T> serviceDiscovery;
+ private final ProviderStrategy<T> providerStrategy;
+ private final int instanceRefreshMs;
+
+ /**
+ * payloadType is wildcard Class<?> it could be Class<T> except when dealing with situations like
+ * Map<String,String> which cannot be referenced explicitly and instead can only be referenced as Map.class.
+ */
+ private final Class<?> payloadType;
+
+ public GenericDiscoveryContext(ServiceDiscovery<T> serviceDiscovery, ProviderStrategy<T> providerStrategy, int instanceRefreshMs, Class<?> payloadType)
+ {
+ this.serviceDiscovery = serviceDiscovery;
+ this.providerStrategy = providerStrategy;
+ this.instanceRefreshMs = instanceRefreshMs;
+ this.payloadType = payloadType;
+ }
+
+ @Override
+ public ProviderStrategy<T> getProviderStrategy()
+ {
+ return providerStrategy;
+ }
+
+ @Override
+ public int getInstanceRefreshMs()
+ {
+ return instanceRefreshMs;
+ }
+
+ @Override
+ public ServiceDiscovery<T> getServiceDiscovery()
+ {
+ return serviceDiscovery;
+ }
+
+ @SuppressWarnings("unchecked") // because payloadType is Class<?> instead of Class<T> because of generic generics like Map<String,String>
+ @Override
+ public void marshallJson(ObjectNode node, String fieldName, T payload) throws Exception
+ {
+ if ( payload == null )
+ {
+ payload = (T) payloadType.newInstance();
+ }
+
+ node.putPOJO(fieldName, payload);
+
+ }
+
+ @SuppressWarnings("unchecked") //
+ @Override
+ public T unMarshallJson(JsonNode node) throws Exception
+ {
+ T payload;
+ ObjectMapper mapper = new ObjectMapper();
+ payload = (T) mapper.readValue(node, payloadType);
+ return payload;
+ }
+
+ @Override
+ public DiscoveryContext<T> getContext(Class<?> type)
+ {
+ return this;
+ }
+}
@@ -18,83 +18,25 @@
package com.netflix.curator.x.discovery.server.contexts;
-import com.google.common.collect.Maps;
+import java.util.Map;
+
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
import com.netflix.curator.x.discovery.ProviderStrategy;
import com.netflix.curator.x.discovery.ServiceDiscovery;
import com.netflix.curator.x.discovery.server.rest.DiscoveryContext;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.node.ObjectNode;
-import javax.ws.rs.ext.ContextResolver;
-import javax.ws.rs.ext.Provider;
-import java.util.Iterator;
-import java.util.Map;
/**
* For convenience, a version of {@link DiscoveryContext} that uses a String-to-String map as the
* payload
*/
@Provider
-public class MapDiscoveryContext implements DiscoveryContext<Map<String, String>>, ContextResolver<DiscoveryContext<Map<String, String>>>
+public class MapDiscoveryContext extends GenericDiscoveryContext<Map<String, String>> implements DiscoveryContext<Map<String, String>>, ContextResolver<DiscoveryContext<Map<String, String>>>
{
- private final ServiceDiscovery<Map<String, String>> serviceDiscovery;
- private final ProviderStrategy<Map<String, String>> providerStrategy;
- private final int instanceRefreshMs;
-
public MapDiscoveryContext(ServiceDiscovery<Map<String, String>> serviceDiscovery, ProviderStrategy<Map<String, String>> providerStrategy, int instanceRefreshMs)
{
- this.serviceDiscovery = serviceDiscovery;
- this.providerStrategy = providerStrategy;
- this.instanceRefreshMs = instanceRefreshMs;
- }
-
- @Override
- public ProviderStrategy<Map<String, String>> getProviderStrategy()
- {
- return providerStrategy;
- }
-
- @Override
- public int getInstanceRefreshMs()
- {
- return instanceRefreshMs;
- }
-
- @Override
- public ServiceDiscovery<Map<String, String>> getServiceDiscovery()
- {
- return serviceDiscovery;
- }
-
- @Override
- public void marshallJson(ObjectNode node, String fieldName, Map<String, String> map) throws Exception
- {
- if ( map == null )
- {
- map = Maps.newHashMap();
- }
- ObjectNode objectNode = node.putObject(fieldName);
- for ( Map.Entry<String, String> entry : map.entrySet() )
- {
- objectNode.put(entry.getKey(), entry.getValue());
- }
- }
-
- @Override
- public Map<String, String> unMarshallJson(JsonNode node) throws Exception
- {
- Map<String, String> map = Maps.newHashMap();
- Iterator<Map.Entry<String,JsonNode>> fields = node.getFields();
- while ( fields.hasNext() )
- {
- Map.Entry<String, JsonNode> entry = fields.next();
- map.put(entry.getKey(), entry.getValue().asText());
- }
- return map;
- }
-
- @Override
- public DiscoveryContext<Map<String, String>> getContext(Class<?> type)
- {
- return this;
+ super(serviceDiscovery, providerStrategy, instanceRefreshMs, Map.class);
+
}
}
@@ -0,0 +1,73 @@
+package com.netflix.curator.x.discovery.server.jetty_jersey;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.codehaus.jackson.map.annotate.JsonRootName;
+
+/**
+ * Service payload describing details of a service.
+ */
+@JsonRootName("details")
+public class ServiceDetails {
+
+ private Map<String, String> data;
+
+ private String description;
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public ServiceDetails() {
+ this(new HashMap<String, String>());
+ }
+
+ public ServiceDetails(Map<String, String> data) {
+ this.data = data;
+ }
+
+ public void setData(Map<String, String> data) {
+ this.data = data;
+ }
+
+ public Map<String, String> getData() {
+ return data;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((data == null) ? 0 : data.hashCode());
+ result = prime * result
+ + ((description == null) ? 0 : description.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ServiceDetails other = (ServiceDetails) obj;
+ if (data == null) {
+ if (other.data != null)
+ return false;
+ } else if (!data.equals(other.data))
+ return false;
+ if (description == null) {
+ if (other.description != null)
+ return false;
+ } else if (!description.equals(other.description))
+ return false;
+ return true;
+ }
+}
@@ -0,0 +1,40 @@
+/*
+ *
+ * Copyright 2011 Netflix, Inc.
+ *
+ * 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 com.netflix.curator.x.discovery.server.jetty_jersey;
+
+import javax.ws.rs.ext.ContextResolver;
+import javax.ws.rs.ext.Provider;
+
+import com.netflix.curator.x.discovery.ProviderStrategy;
+import com.netflix.curator.x.discovery.ServiceDiscovery;
+import com.netflix.curator.x.discovery.server.contexts.GenericDiscoveryContext;
+import com.netflix.curator.x.discovery.server.rest.DiscoveryContext;
+
+/**
+ * A DiscoveryContext that maps a concrete payload object of ServiceDetails
+ */
+@Provider
+public class ServiceDetailsDiscoveryContext extends GenericDiscoveryContext<ServiceDetails> implements DiscoveryContext<ServiceDetails>, ContextResolver<DiscoveryContext<ServiceDetails>>
+{
+ public ServiceDetailsDiscoveryContext(ServiceDiscovery<ServiceDetails> serviceDiscovery, ProviderStrategy<ServiceDetails> providerStrategy, int instanceRefreshMs)
+ {
+ super(serviceDiscovery, providerStrategy, instanceRefreshMs, ServiceDetails.class);
+
+ }
+}
@@ -0,0 +1,35 @@
+/*
+ *
+ * Copyright 2011 Netflix, Inc.
+ *
+ * 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 com.netflix.curator.x.discovery.server.jetty_jersey;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.ContextResolver;
+
+import com.netflix.curator.x.discovery.server.rest.DiscoveryContext;
+import com.netflix.curator.x.discovery.server.rest.DiscoveryResource;
+
+@Path("/")
+public class ServiceDetailsDiscoveryResource extends DiscoveryResource<ServiceDetails>
+{
+ public ServiceDetailsDiscoveryResource(@Context ContextResolver<DiscoveryContext<ServiceDetails>> resolver)
+ {
+ super(resolver.getContext(DiscoveryContext.class));
+ }
+}
Oops, something went wrong.

0 comments on commit 1007d94

Please sign in to comment.