Angel metadata.instanceId works with Brixton
Fixes gh-642
This commit is contained in:
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user