Ensure BusJacksonMessageConverter uses auto-configured ObjectMapper

fixes gh-104
This commit is contained in:
Spencer Gibb
2018-02-28 22:32:24 -05:00
parent 940ce37b7e
commit 5f5dcb2cc8
2 changed files with 119 additions and 15 deletions

View File

@@ -0,0 +1,105 @@
package org.springframework.cloud.bus.jackson;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.bus.ServiceMatcher;
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class BusJacksonIntegrationTests {
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate rest;
@Autowired
private BusJacksonMessageConverter converter;
@Test
public void testCustomEventSerializes() {
assertThat(converter.isMapperCreated()).isFalse();
rest.put("http://localhost:"+port+"/names"+"/foo", null);
rest.put("http://localhost:"+port+"/names"+"/bar", null);
ResponseEntity<List> response = rest.getForEntity("http://localhost:" + port + "/names", List.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).contains("foo", "bar");
}
public static class NameEvent extends RemoteApplicationEvent {
private String name;
protected NameEvent() {}
public NameEvent(Object source, String originService, String name) {
super(source, originService);
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@RestController
@EnableAutoConfiguration
@SpringBootConfiguration
@RemoteApplicationEventScan
protected static class Config {
final private Set<String> names = ConcurrentHashMap.newKeySet();
@Autowired
private ServiceMatcher busServiceMatcher;
@Autowired
private ApplicationEventPublisher publisher;
@GetMapping("/names")
public Collection<String> names() {
return this.names;
}
@PutMapping("/names/{name}")
public void sayName(@PathVariable String name) {
this.names.add(name);
publisher.publishEvent(new NameEvent(this, busServiceMatcher.getServiceId(), name));
}
@EventListener
public void handleNameSaid(NameEvent event) {
this.names.add(event.getName());
}
}
}

View File

@@ -22,21 +22,23 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.cloud.bus.BusAutoConfiguration;
import org.springframework.cloud.bus.ConditionalOnBusEnabled;
import org.springframework.cloud.bus.endpoint.RefreshBusEndpoint;
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
import org.springframework.cloud.bus.event.UnknownRemoteApplicationEvent;
import org.springframework.cloud.stream.annotation.StreamMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AssignableTypeFilter;
@@ -45,10 +47,6 @@ import org.springframework.messaging.converter.AbstractMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.util.MimeTypeUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
/**
* @author Spencer Gibb
* @author Dave Syer
@@ -58,16 +56,9 @@ import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
@Configuration
@ConditionalOnBusEnabled
@ConditionalOnClass({ RefreshBusEndpoint.class, ObjectMapper.class })
@AutoConfigureBefore(BusAutoConfiguration.class)
@AutoConfigureBefore({ BusAutoConfiguration.class, JacksonAutoConfiguration.class})
public class BusJacksonAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "busJsonConverter")
@StreamMessageConverter
public AbstractMessageConverter busJsonConverter(@Autowired(required = false) ObjectMapper objectMapper) {
return new BusJacksonMessageConverter(objectMapper);
}
}
class BusJacksonMessageConverter extends AbstractMessageConverter
@@ -79,6 +70,7 @@ class BusJacksonMessageConverter extends AbstractMessageConverter
.getPackageName(RemoteApplicationEvent.class);
private final ObjectMapper mapper;
private final boolean mapperCreated;
private String[] packagesToScan = new String[] { DEFAULT_PACKAGE };
@@ -86,16 +78,23 @@ class BusJacksonMessageConverter extends AbstractMessageConverter
this(null);
}
@Autowired(required = false)
public BusJacksonMessageConverter(ObjectMapper objectMapper) {
super(MimeTypeUtils.APPLICATION_JSON);
if (objectMapper != null) {
this.mapper = objectMapper;
this.mapperCreated = false;
} else {
this.mapper = new ObjectMapper();
this.mapperCreated = true;
}
}
public boolean isMapperCreated() {
return mapperCreated;
}
public void setPackagesToScan(String[] packagesToScan) {
List<String> packages = new ArrayList<>(Arrays.asList(packagesToScan));
if (!packages.contains(DEFAULT_PACKAGE)) {