Spencer Gibb,
@spencerbgibb,
sgibb@pivotal.io
Dave Syer,
@david_syer,
dsyer@pivotal.io
With thanks to @littleidea
Your app won’t always work first time. How to diagnose the problem?
cf logs)spring-cloud-commons: useful abstractions DiscoveryClient, LoadBalancer, @EnableServiceDiscoveryspring-cloud-netflix: Eureka and Ribbonspring-cloud-consul: Hashicorp Consulspring-cloud-zookeeper: Zookeeperspring-cloud-cloudfoundry: cloud controller APIspring-cloud-lattice: receptor (diego controller) APIConnectors (using service name)
IRule: Load-balancing algorithm (round-robin, random, etc…)
ServerList: Where to get the list of servers to load-balance.
ConfigurationBasedServerList:
ribbon.<clientname>.listOfServers propertyDiscoveryEnabledNIWSServerList: via eurekaConsulServerList: via hashicorp consulZookeeperServerList: …ServerListFilter: filters list of servers.
@RibbonClients
@RibbonClient annotations.@RibbonClient: allows configuration for a named ribbon client.@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyTests.Application.class)
@WebIntegrationTest(randomPort = true)
public class MyTests { /*...*/
@Configuration
@RibbonClient(name = "localapp",
configuration = LocalRibbonClientConfig.class)
protected static class Application { /*...*/ }
@Configuration
static class LocalRibbonClientConfig {
@Value("${local.server.port}")
private int port = 0;
@Bean
public ServerList<Server> ribbonServerList() {
return new StaticServerList<>(new Server("localhost", this.port));
}
}
}
High level:
Example tools/approaches:
Create Wiremock stubs using tests or dsl
Generates a MockMVC test and a Wiremock stub
import io.codearte.accurest.dsl.GroovyDsl
GroovyDsl groovyDsl = GroovyDsl.make {
request {
method 'GET'
url '/foo'
}
response {
status 200
headers {
header 'Content-Type' : 'application/json;charset=UTF-8'
}
body '''{ "value" : 42 }'''
}
}
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration()
.snippets().withDefaults(curlRequest(),
httpRequest(),
httpResponse(),
new WiremockStubSnippet()))
.build();
}
@Test
public void foo() {
this.mockMvc.perform(get("/foo")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("foo"));
}
{
"request": {
"method": "GET",
"url": "/foo"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json;charset=UTF-8"
},
"body": "{\"value\":42}"
}
}
@Controller
public class StubFleetLocationServiceApplication {
@RequestMapping("/locations")
public String home() {
return "forward:/stubs/locations.json";
}
...
}
Nice side effect: mock MVC and restdocs for tests and docs can be used to verify real service contract
application.ymlStubrunner uses list of dependencies
App monitors its classpath and restarts when changes detected:
Browser plugin automatically refreshes views:
Hot reloading of “local” application code deployed on Cloud Foundry / Lattice
How does new code enter a build pipeline and get promoted to production?
How to wire up your application code to required middleware, and make the same code run in all environments?
/