├── README.md ├── java-project ├── .gitignore ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── yourself │ │ │ ├── Universe.java │ │ │ ├── Application.java │ │ │ ├── Greeting.java │ │ │ └── GreetingController.java │ └── test │ │ └── java │ │ └── com │ │ └── yourself │ │ ├── UniverseTest.java │ │ └── GreetingControllerTest.java └── pom.xml ├── cover.png ├── techio.yml ├── .gitignore └── markdowns └── welcome.md /README.md: -------------------------------------------------------------------------------- 1 | # spring5-template 2 | A template for Spring 5 Java framework 3 | -------------------------------------------------------------------------------- /java-project/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | .settings 3 | .project 4 | .classpath 5 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/loafer/playground-idtx3uar/master/cover.png -------------------------------------------------------------------------------- /techio.yml: -------------------------------------------------------------------------------- 1 | title: Spring 5 Project 2 | plan: 3 | - title: Welcome 4 | statement: markdowns/welcome.md 5 | projects: 6 | java: 7 | root: /java-project 8 | runner: 9 | name: techio/java-maven3-junit4-runner 10 | version: 1.1.4-java-8 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | dependency-reduced-pom.xml 8 | buildNumber.properties 9 | .mvn/timing.properties 10 | 11 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 12 | !/.mvn/wrapper/maven-wrapper.jar 13 | -------------------------------------------------------------------------------- /java-project/src/main/java/com/yourself/Universe.java: -------------------------------------------------------------------------------- 1 | // { autofold 2 | package com.yourself; 3 | 4 | import java.util.Arrays; 5 | 6 | public class Universe { 7 | // } 8 | 9 | public static int countAllStars(int... galaxies) { 10 | int totalStars = 0; 11 | for(int stars : galaxies) { 12 | totalStars = stars; // fix me! 13 | } 14 | return totalStars; 15 | } 16 | 17 | //{ autofold 18 | } 19 | //} -------------------------------------------------------------------------------- /java-project/src/main/java/com/yourself/Application.java: -------------------------------------------------------------------------------- 1 | package com.yourself; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * Created by charlotte on 06/06/17. 8 | */ 9 | @SpringBootApplication 10 | public class Application { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(Application.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /java-project/src/main/java/com/yourself/Greeting.java: -------------------------------------------------------------------------------- 1 | package com.yourself; 2 | 3 | public class Greeting { 4 | 5 | public Greeting() { 6 | } 7 | 8 | public void setId(long id) { 9 | this.id = id; 10 | } 11 | 12 | private long id; 13 | private String content; 14 | 15 | 16 | 17 | 18 | 19 | 20 | public Greeting(long id, String content) { 21 | this.id = id; 22 | this.content = content; 23 | } 24 | 25 | public long getId() { 26 | return id; 27 | } 28 | 29 | public String getContent() { 30 | return content; 31 | } 32 | 33 | 34 | public void setContent(String content) { 35 | this.content=content; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /java-project/src/main/java/com/yourself/GreetingController.java: -------------------------------------------------------------------------------- 1 | // { autofold 2 | package com.yourself; 3 | 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import java.util.concurrent.atomic.AtomicLong; 9 | 10 | 11 | //} 12 | @RestController 13 | public class GreetingController { 14 | 15 | private static final String template = "Hello, %s!"; 16 | private final AtomicLong counter = new AtomicLong(); 17 | 18 | @RequestMapping("/greeting") 19 | public Greeting greeting(@RequestParam(value="name") String name) { 20 | return new Greeting(counter.incrementAndGet(), 21 | "");//FIXME Use the string template to say "Hello, %name%" 22 | } 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /markdowns/welcome.md: -------------------------------------------------------------------------------- 1 | # Welcome! 2 | 3 | This Spring 5 template lets you get started quickly with a simple working example using Maven and JUnit. A first example of rest service is provided. If it is your first contribution then you should have a look at the [Getting Started](https://tech.io/doc/getting-started-create-playground) document. 4 | 5 | 6 | The source code is on [GitHub](https://github.com/TechDotIO/Spring5-template), please feel free to come up with proposals to improve it. 7 | 8 | # Hands-on Demo 9 | 10 | @[Complete the controller to say "Hello, %name%"]({"stubs": ["src/main/java/com/yourself/GreetingController.java", "src/main/java/com/yourself/Greeting.java"], "command": "com.yourself.GreetingControllerTest#greetingsWithName"}) 11 | 12 | Check out the markdown file [`welcome.md`](https://github.com/TechDotIO/Spring5-template/blob/master/markdowns/welcome.md) to see how this exercise is injected into the template. 13 | 14 | # Template Resources 15 | 16 | [`markdowns/welcome.md`](https://github.com/TechDotIO/Spring5-template/blob/master/markdowns/welcome.md) 17 | What you are reading here is generated by this file. Tech.io uses the [Markdown syntax](https://tech.io/doc/reference-markdowns) to render text, media and to inject programming exercises. 18 | 19 | 20 | [`java-project`](https://github.com/TechDotIO/Spring5-template/tree/master/java-project) 21 | A simple Java + Maven + Spring 5 + JUnit project dedicated to run the programming exercise above. A project relies on a Docker image to run. You can find images on the [Docker Hub](https://hub.docker.com/explore/) or you can even [build your own](https://tech.io/doc/reference-runner). 22 | 23 | 24 | [`techio.yml`](https://github.com/TechDotIO/Spring5-template/blob/master/techio.yml) 25 | This *mandatory* file describes both the table of content and the programming project(s). The file path should not be changed. 26 | 27 | 28 | # Visual and Interactive Content 29 | 30 | Tech.io provides all the tools to embed visual and interactive content like a Web app or a Unix terminal within your contribution. Please refer to the [documentation](https://tech.io/doc) to learn more about the viewer integrations. 31 | -------------------------------------------------------------------------------- /java-project/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | whatsNewInSpring5 8 | whatsNewInSpring5 9 | 1.0-SNAPSHOT 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 1.5.4.RELEASE 15 | 16 | 17 | 18 | 19 | UTF-8 20 | 1.8 21 | 1.8 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | 41 | 42 | 43 | 44 | junit 45 | junit 46 | 4.12 47 | test 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-maven-plugin 59 | 1.5.3.RELEASE 60 | 61 | 62 | 63 | repackage 64 | 65 | 66 | exec 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /java-project/src/test/java/com/yourself/UniverseTest.java: -------------------------------------------------------------------------------- 1 | package com.yourself; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.util.Scanner; 6 | 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | public class UniverseTest { 11 | 12 | @Test 13 | public void test() throws FileNotFoundException { 14 | try { 15 | Assert.assertEquals("Running Universe.countAllStars(2, 3)...", 5, Universe.countAllStars(2, 3)); 16 | Assert.assertEquals("Running Universe.countAllStars(9, -3)...", 6, Universe.countAllStars(9, -3)); 17 | success(true); 18 | 19 | if (existsInFile("Arrays.stream(galaxies).sum()", new File("./src/main/java/com/yourself/Universe.java"))) { 20 | msg("My personal Yoda, you are. 🙏", "* ● ¸ . ¸. :° ☾ °  ¸. ● ¸ .  ¸. :. • "); 21 | msg("My personal Yoda, you are. 🙏", "  ★ ° ☆ ¸. ¸  ★  :.  . "); 22 | msg("My personal Yoda, you are. 🙏", "__.-._ ° . .    . ☾ °  . * ¸ ."); 23 | msg("My personal Yoda, you are. 🙏", "'-._\\7' .  ° ☾ °  ¸.☆ ● .   "); 24 | msg("My personal Yoda, you are. 🙏", " /'.-c   * ● ¸.  ° °  ¸. "); 25 | msg("My personal Yoda, you are. 🙏", " | /T   ° °  ¸. ¸ .   "); 26 | msg("My personal Yoda, you are. 🙏", "_)_/LI"); 27 | } else { 28 | msg("Kudos 🌟", "Did you know that since Java8 is out you can use streams? Try it!"); 29 | msg("Kudos 🌟", ""); 30 | msg("Kudos 🌟", "int[] galaxies = {37, 3, 2};"); 31 | msg("Kudos 🌟", "int totalStars = Arrays.stream(galaxies).sum(); // 42"); 32 | } 33 | } catch (AssertionError ae) { 34 | success(false); 35 | msg("Oops! 🐞", ae.getMessage()); 36 | msg("Hint 💡", "Did you properly accumulate all stars into 'totalStars'? 🤔"); 37 | } 38 | } 39 | 40 | private static void msg(String channel, String msg) { 41 | System.out.println(String.format("TECHIO> message --channel \"%s\" \"%s\"", channel, msg)); 42 | } 43 | 44 | private static void success(boolean success) { 45 | System.out.println(String.format("TECHIO> success %s", success)); 46 | } 47 | 48 | // check if a string exists in a text file 49 | private static boolean existsInFile(String str, File file) throws FileNotFoundException { 50 | Scanner scanner = new Scanner(file); 51 | try { 52 | while (scanner.hasNextLine()) { 53 | if (scanner.nextLine().contains(str)) 54 | return true; 55 | } 56 | return false; 57 | } finally { 58 | scanner.close(); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /java-project/src/test/java/com/yourself/GreetingControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.yourself; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.http.converter.HttpMessageConverter; 11 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 12 | import org.springframework.mock.http.MockHttpOutputMessage; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | import org.springframework.test.context.web.WebAppConfiguration; 15 | import org.springframework.test.web.servlet.MockMvc; 16 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 17 | import org.springframework.web.context.WebApplicationContext; 18 | 19 | import java.io.IOException; 20 | import java.nio.charset.Charset; 21 | import java.util.Arrays; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNotNull; 25 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 27 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 28 | 29 | 30 | /** 31 | * Created by charlotte on 06/06/17. 32 | */ 33 | 34 | @RunWith(SpringRunner.class) 35 | @SpringBootTest(classes = Application.class) 36 | @WebAppConfiguration 37 | public class GreetingControllerTest { 38 | 39 | private MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), 40 | MediaType.APPLICATION_JSON.getSubtype(), 41 | Charset.forName("utf8")); 42 | 43 | private HttpMessageConverter mappingJackson2HttpMessageConverter; 44 | 45 | private MockMvc mockMvc; 46 | 47 | 48 | @Autowired 49 | private WebApplicationContext webApplicationContext; 50 | 51 | @Autowired 52 | void setConverters(HttpMessageConverter[] converters) { 53 | 54 | this.mappingJackson2HttpMessageConverter = Arrays.asList(converters).stream() 55 | .filter(hmc -> hmc instanceof MappingJackson2HttpMessageConverter) 56 | .findAny() 57 | .orElse(null); 58 | 59 | assertNotNull("the JSON message converter must not be null", 60 | this.mappingJackson2HttpMessageConverter); 61 | 62 | 63 | } 64 | 65 | @Before 66 | public void setup() throws Exception { 67 | this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 68 | } 69 | 70 | protected String json(Object o) throws IOException { 71 | MockHttpOutputMessage mockHttpOutputMessage = new MockHttpOutputMessage(); 72 | this.mappingJackson2HttpMessageConverter.write( 73 | o, MediaType.APPLICATION_JSON, mockHttpOutputMessage); 74 | return mockHttpOutputMessage.getBodyAsString(); 75 | } 76 | 77 | 78 | 79 | 80 | @Test 81 | public void greetingsWithName() throws Exception { 82 | mockMvc.perform(post("/greeting").param("name","World") 83 | .contentType(contentType)) 84 | .andExpect(status().isOk()) 85 | .andExpect(content().contentType(contentType)) 86 | .andExpect(mvcResult ->{ 87 | String responseJson = mvcResult.getResponse().getContentAsString(); 88 | Greeting greeting = new ObjectMapper().readValue(responseJson,Greeting.class); 89 | //assertEquals("{\"id\":1,\"content\":\"Hello, World!\"}",responseJson ); 90 | assertEquals(1, greeting.getId()); 91 | assertEquals("Hello, World!", greeting.getContent()); 92 | } ); 93 | 94 | 95 | } 96 | 97 | 98 | } 99 | --------------------------------------------------------------------------------