Commit 1c4db22c by Spencer Gibb

Angel metadata.instanceId works with Brixton

Fixes gh-642
parent bdc5b915
/*
* Copyright 2013-2015 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.cloud.netflix.eureka;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.UniqueIdentifier;
/**
* @author Spencer Gibb
*/
public class InstanceIdDataCenterInfo implements DataCenterInfo,
UniqueIdentifier {
private String instanceId;
public InstanceIdDataCenterInfo(String instanceId) {
this.instanceId = instanceId;
}
@Override
public Name getName() {
return Name.MyOwn;
}
@Override
public String getId() {
return this.instanceId;
}
}
package org.springframework.cloud.netflix.eureka.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import org.springframework.util.ReflectionUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.LeaseInfo;
import com.netflix.discovery.converters.EurekaJacksonCodec;
import com.netflix.discovery.converters.EurekaJacksonCodec.InstanceInfoDeserializer;
import com.netflix.discovery.converters.EurekaJacksonCodec.InstanceInfoSerializer;
import com.netflix.discovery.converters.wrappers.CodecWrappers.LegacyJacksonJson;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import static com.netflix.discovery.converters.wrappers.CodecWrappers.getCodecName;
/**
* @author Spencer Gibb
*/
public class CloudJacksonJson extends LegacyJacksonJson {
protected final CloudJacksonCodec codec = new CloudJacksonCodec();
@Override
public String codecName() {
return getCodecName(this.getClass());
}
@Override
public <T> String encode(T object) throws IOException {
return codec.writeToString(object);
}
@Override
public <T> void encode(T object, OutputStream outputStream) throws IOException {
codec.writeTo(object, outputStream);
}
@Override
public <T> T decode(String textValue, Class<T> type) throws IOException {
return codec.readValue(type, textValue);
}
@Override
public <T> T decode(InputStream inputStream, Class<T> type) throws IOException {
return codec.readValue(type, inputStream);
}
static class CloudJacksonCodec extends EurekaJacksonCodec {
private static final Version VERSION = new Version(1, 1, 0, null);
@SuppressWarnings("deprecation")
public CloudJacksonCodec() {
super();
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
SimpleModule module = new SimpleModule("eureka1.x", VERSION);
module.addSerializer(DataCenterInfo.class, new DataCenterInfoSerializer());
module.addSerializer(InstanceInfo.class, new CloudInstanceInfoSerializer());
module.addSerializer(Application.class, new ApplicationSerializer());
module.addSerializer(Applications.class, new ApplicationsSerializer(this.getVersionDeltaKey(), this.getAppHashCodeKey()));
module.addDeserializer(DataCenterInfo.class, new DataCenterInfoDeserializer());
module.addDeserializer(LeaseInfo.class, new LeaseInfoDeserializer());
module.addDeserializer(InstanceInfo.class, new CloudInstanceInfoDeserializer(mapper));
module.addDeserializer(Application.class, new ApplicationDeserializer(mapper));
module.addDeserializer(Applications.class, new ApplicationsDeserializer(mapper, this.getVersionDeltaKey(), this.getAppHashCodeKey()));
mapper.registerModule(module);
HashMap<Class<?>, ObjectReader> readers = new HashMap<>();
readers.put(InstanceInfo.class, mapper.reader().withType(InstanceInfo.class).withRootName("instance"));
readers.put(Application.class, mapper.reader().withType(Application.class).withRootName("application"));
readers.put(Applications.class, mapper.reader().withType(Applications.class).withRootName("applications"));
setField("objectReaderByClass", readers);
HashMap<Class<?>, ObjectWriter> writers = new HashMap<>();
writers.put(InstanceInfo.class, mapper.writer().withType(InstanceInfo.class).withRootName("instance"));
writers.put(Application.class, mapper.writer().withType(Application.class).withRootName("application"));
writers.put(Applications.class, mapper.writer().withType(Applications.class).withRootName("applications"));
setField("objectWriterByClass", writers);
setField("mapper", mapper);
}
void setField(String name, Object value) {
Field field = ReflectionUtils.findField(EurekaJacksonCodec.class, name);
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, this, value);
}
}
static class CloudInstanceInfoSerializer extends InstanceInfoSerializer {
@Override
public void serialize(InstanceInfo info, JsonGenerator jgen, SerializerProvider provider) throws IOException {
if (info.getInstanceId() == null && info.getMetadata() != null) {
String instanceId = info.getMetadata().get("instanceId");
info = new InstanceInfo.Builder(info).setInstanceId(instanceId).build();
}
super.serialize(info, jgen, provider);
}
}
static class CloudInstanceInfoDeserializer extends InstanceInfoDeserializer {
protected CloudInstanceInfoDeserializer(ObjectMapper mapper) {
super(mapper);
}
}
}
......@@ -52,6 +52,8 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import com.netflix.discovery.converters.wrappers.CodecWrapper;
import com.netflix.discovery.converters.wrappers.CodecWrappers;
import com.netflix.eureka.DefaultEurekaServerContext;
import com.netflix.eureka.EurekaServerConfig;
import com.netflix.eureka.EurekaServerContext;
......@@ -135,7 +137,28 @@ public class EurekaServerConfiguration extends WebMvcConfigurerAdapter {
@Bean
public ServerCodecs serverCodecs() {
return new DefaultServerCodecs(this.eurekaServerConfig);
CodecWrappers.registerWrapper(new CloudJacksonJson());
return new CloudServerCodecs(this.eurekaServerConfig);
}
private static CodecWrapper getFullJson(EurekaServerConfig serverConfig) {
CodecWrapper codec = CodecWrappers.getCodec(serverConfig.getJsonCodecName());
return codec == null ? CodecWrappers.getCodec(CloudJacksonJson.class) : codec;
}
private static CodecWrapper getFullXml(EurekaServerConfig serverConfig) {
CodecWrapper codec = CodecWrappers.getCodec(serverConfig.getXmlCodecName());
return codec == null ? CodecWrappers.getCodec(CodecWrappers.XStreamXml.class) : codec;
}
class CloudServerCodecs extends DefaultServerCodecs {
public CloudServerCodecs(EurekaServerConfig serverConfig) {
super(getFullJson(serverConfig),
CodecWrappers.getCodec(CodecWrappers.JacksonJsonMini.class),
getFullXml(serverConfig),
CodecWrappers.getCodec(CodecWrappers.JacksonXmlMini.class));
}
}
@Bean
......
......@@ -21,6 +21,7 @@ import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
......@@ -38,9 +39,16 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.converters.wrappers.CodecWrapper;
import com.netflix.eureka.resources.ServerCodecs;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class)
......@@ -52,15 +60,8 @@ public class ApplicationTests {
@Value("${local.server.port}")
private int port = 0;
@Configuration
@EnableAutoConfiguration
@EnableEurekaServer
protected static class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=eureka").run(args);
}
}
@Autowired
private ServerCodecs serverCodecs;
@Test
public void catalogLoads() {
......@@ -103,4 +104,30 @@ public class ApplicationTests {
assertNotNull(body);
assertTrue("css wasn't preprocessed", body.contains("spring-logo"));
}
@Test
public void customCodecWorks() throws Exception {
assertThat("serverCodecs is wrong type", this.serverCodecs, is(instanceOf(EurekaServerConfiguration.CloudServerCodecs.class)));
CodecWrapper codec = this.serverCodecs.getFullJsonCodec();
assertThat("codec is wrong type", codec, is(instanceOf(CloudJacksonJson.class)));
InstanceInfo instanceInfo = InstanceInfo.Builder.newBuilder()
.setAppName("fooapp")
.add("instanceId", "foo")
.build();
String encoded = codec.encode(instanceInfo);
InstanceInfo decoded = codec.decode(encoded, InstanceInfo.class);
assertThat("instanceId was wrong", decoded.getInstanceId(), is("foo"));
}
@Configuration
@EnableAutoConfiguration
@EnableEurekaServer
protected static class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).properties(
"spring.application.name=eureka").run(args);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment