Have a drink on me – Swagger clients

Time to get our clients involved. What’s the point of brewing our excellent HelloBeerTM crafts when no one’s drinkin’ ’em, right?!

In this post we’ll generate a client for our Swagger API and build a small Spring MVC client on top of it. As always the code is available on GitHub.

Generating clients

This time we’ll skip the manual labor of downloading a client zip from SwaggerHub. We’ll start with the Maven plugin right away. Let’s first take a look at the part of our pom file that will take care of the client generation:

<plugin>
  <groupId>io.swagger</groupId>
  <artifactId>swagger-codegen-maven-plugin</artifactId>
  <version>2.3.0</version>
  <executions>
    <execution>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <inputSpec>
          https://app.swaggerhub.com/apiproxy/schema/file/rphgoossens/hello-beer/1.0/swagger.yaml
        </inputSpec>
        <language>java</language>
        <apiPackage>nl.whitehorses.hellobeer.generated.client.api</apiPackage>
        <modelPackage>nl.whitehorses.hellobeer.generated.client.model</modelPackage>
        <ignoreFileOverride>${project.basedir}/.swagger-codegen-ignore</ignoreFileOverride>
      </configuration>
    </execution>
  </executions>
</plugin>

The inputSpec configuration parameter is pointing again to our Swagger API exposed on SwaggerHub. We’re generating a java client here, so the language parameter is set to java. The ignoreFileOverride is pointing to a file containing a few file patterns.

target/generated-sources/swagger/*
target/generated-sources/swagger/docs/*
target/generated-sources/swagger/gradle/**/*
target/generated-sources/swagger/src/main/AndroidManifest.xml
target/generated-sources/swagger/src/test/**/*

The files adhering to these patterns (files we don’t really need like gradle build files, test packages etc.) won’t be generated thanks to these overrides. You can leave the ignoreFileOverride line out in your first run, to see what it generates. Especially the generated pom file is a big help in getting your own project pom in order. Note that I wont show all the necessary dependencies here, you can check them out on GitHub.
After generation (mvn generate-sources), you can check the target folder. If all went well, all the necessary generated classes will be there.
Screenshot from 2018-02-17 11-20-04Unlike server generation, the supporting files for client generation are necessary or else the generated code won’t compile. The important classes are of course the model class Beer (which also contains the TypeEnum) and the BeerControllerApi, which is the means for communicating with the back-end code.

Service layer

Lets wrap that generated controller code nicely into a service.

@Service
public class BeerService implements IBeerService {

    private BeerControllerApi beerControllerApi;

    @Autowired
    public BeerService(BeerControllerApi beerControllerApi) {
        this.beerControllerApi = beerControllerApi;
    }

    @Override
    public List<Beer> getAllBeers() {
        List<Beer> beers;
        try {
            beers = beerControllerApi.getAllBeersUsingGET(null);
        } catch (ApiException e) {
            throw new RuntimeException(e);
        }
        return beers;
    }

    @Override
    public void save(Beer beer) {
        try {
            beerControllerApi.addToBeerRepositoryUsingPOST(beer);
        } catch (ApiException e) {
            throw new RuntimeException(e);
        }
    }
}

Most of the service code speaks for itself. Some pointers:

  • According to good Spring principles, I’ve also extracted an interface for the Service class. Dependencies can now be expressed via the interface instead of directly to the class;
  • The ApiException that’s being thrown from all api methods has been wrapped into a RuntimeException;
  • The BeerControllerApi I’ve turned into a Spring bean so I can make use of DI.

Perhaps the biggest catch is turning our generated api class into a Spring Bean. As it turns out, that’s like a walk in the park. I’ve put the code in the bootstrap class:

@Bean
public BeerControllerApi addBeerControllerApi() {
return new BeerControllerApi();
}

Controller layer

This is the code that glues the Thymeleaf template to the service code:

@Controller
@RequestMapping({"/beers"})
public class BeersController {
private IBeerService beerService;

@Autowired
public BeersController(IBeerService beerService) {
this.beerService = beerService;
}

@RequestMapping(method = {RequestMethod.GET})
public String getBeers(Model model) {
List beers = beerService.getAllBeers();

if (beers != null) {
model.addAttribute("beers", beers);
}
return "beers";
}

@RequestMapping(method = {RequestMethod.POST})
public String addToBeers(Beer beer) {
beerService.save(beer);

return "redirect:/beers";
}

@ModelAttribute("beerTypes")
public List populateBeerTypes() {
return Arrays.asList(Beer.TypeEnum.values());
}
}

Nothing much going on in here. I’ve injected the beerservice into the controller via its interface and delegated the MVC controller methods to the service. I’ve also added the beerTypes model attribute to get a list of beer types for display in a select input item on the UI page.

Bootstrapping

The bootstrap class is fairly simple. It implements the WebMvcConfigurerAdapter as we’re building a Spring MVC application. I’ve overriden the addViewControllers method to promote the beers.html page into our landing page.

@SpringBootApplication
public class HelloBeerClient extends WebMvcConfigurerAdapter {
....
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/", "/beers");
}
....
}

Testing our beers

Based on the test class that the swagger-code-maven plugin generates, I’ve built a small unit test that tests the generated api. The interesting part is in the @Before code where I override the endpoint of the api with a SwaggerHub endpoint that’s making use of SwaggerHub’s mocking functionality:

@RunWith(SpringRunner.class)
@SpringBootTest
public class BeerControllerApiTest {

@Autowired
private BeerControllerApi beerControllerApi;

@Before
public void setUp() {
beerControllerApi.getApiClient().setBasePath("http://virtserver.swaggerhub.com/rphgoossens/hello-beer/1.1");
}

....
}

Serving our clients

Time to serve up the beers. I’m not gonna show you all the beers.html code here. You can check it out on GitHub. The part I struggled a bit with, was displaying the beer types as plain text instead of the hard-coded values of the Enum. In the end this also proved to be fairly simple.

The select item for one I’ve implemented like this:

<select id="input.type" name="type" class="form-control input-sm">
<option th:each="type : ${beerTypes}"
          th:value="${type}"
          th:text="#{${type}}"></option>
</select>

The list is being fed by the beerTypes model attribute I’ve defined earlier in the controller class. The text being displayed is in the form of #{value}. This is Thymeleaf’s way of saying to Spring to get the value from a i18n property file.

The default file for this is messages_locale.properties. So I’ve added a messages.properties file in src/main/resources with the translations for the Beer.TypeEnum enum.

The client is being served on port 8081 and if you also fire up the hello-beer-server application, you’ll see something like this (after you’ve posted a few beers):

Screenshot-2018-2-16 Hello Beers(1)

Note that the edit and delete buttons aren’t implemented yet (the PUT and DELETE operations aren’t even in the contract yet), but you can POST some beers and they will be displayed nicely in the inventory.

Summary

Again fairly easy stuff here. We’ve seen how we can turn our Swagger api into some nice clean java code for use in the UI of your own choice with the help of the swaggger-code-maven plugin. In this post I’ve built my own Spring MVC client on top of the code.

In the next blog post I’ll exploit the plugin’s capabilities of generating angular code. So happy drinking and stay tuned!

References

Advertisements

Swagger Generation Automation or Creating the Bottling Line

High time we see our HelloBeerTM crafts hitting the shelves and start making a couple of bucks (Hail to capitalism!). Alas our project isn’t ready for that big step yet. We first need to crank up production a notch. So high time to automate our Swagger-to-Spring generation. In this blog post we’ll set up our Maven file to let it automatically generate the server stubs for our HelloBeer REST services.

As alway the complete code can be viewed and downloaded from GitHub.

Maven generation

Wouldn’t it be great if we could skip the manual code generation step performed in our previous blog posts and just have them Swagger Server Stub classes generated as part of our build process. Sure it would! And that’s exactly what the guys from SmartBear must have thought. Luckily they provided us with a Maven plugin – called swagger-codegen – to do the job.

The pom file will be based on the pom files we used in our previous blog posts. The most important addition will be said plugin and its configuration. So here it is:


<plugin>
  <groupId>io.swagger</groupId>
  <artifactId>swagger-codegen-maven-plugin</artifactId>
  <version>2.3.0</version>
  <executions>
    <execution>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <inputSpec>
                https://app.swaggerhub.com/apiproxy/schema/file/rphgoossens/hello-beer/1.0/swagger.yaml
        </inputSpec>
        <language>spring</language>
        <apiPackage>nl.whitehorses.hellobeer.generated.api</apiPackage>
        <modelPackage>nl.whitehorses.hellobeer.generated.model</modelPackage>
          <configOptions>
            <delegatePattern>true</delegatePattern>
          </configOptions>
          <generateSupportingFiles>false</generateSupportingFiles>
      </configuration>
    </execution>
  </executions>
</plugin>

The plugin is coupled to the generate goal. During generation the generated sources will by default be put in the ${project.build.directory}/generated-sources/swagger folder (this can be altered by setting the output parameter in the configuration).
The inputSpec parameter is pointing to the swagger.yaml file available on Swaggerhub. To get the exact location of the yaml file, just go to the “Download YAML (Unresolved)” menu item after selecting your API in SwaggerHub and its exact location will pop up in the bottom left corner.
The generateSupportingFiles has been disabled, so no pom or bootstrap class will be generated, as a matter of fact only the model and api classes will be generated with this setting in place.
The rest of the configuration options mirror the ones we explicitly set in SwaggerHub’s CodeGen Options in our previous blogs.

Upon issuing the mvn generate-sources phase, you’ll see the generated files appear in your target folder:
Screenshot from 2018-02-10 20-43-25

Implementation and tasting

Now that we’ve got our crafts flowing nicely through our production lines, it’s time to write the implementation. For this I just copied all the code I built up for my last non-swagger-server-stub-generation-automated project found here.

Tasting the beers can be done by issuing the same Postman calls like we did in our previous blogs. After startup a GET request will show the default beers we put in our inventory, just like it did in our non-automated version:

Screenshot from 2018-02-10 21-17-05

Summary

In this blog we’ve seen how easy it is to automatically generate the server stub using maven, making contract-first development with Swagger and Spring Boot a more than viable option.

In the next blog posts we’ll introduce some much needed functionality to our beer application: the client application aka the beer drinker. Cheers!

References

On Beer Validation – Controlling the Controller

We at HelloBeerTM value the quality of our craft beers. We don’t want any of ’em shabby Heineken Inferior Lager diluting our Barrel Aged Whiskey Infused crafts now, don’t we?! So we need a way to control the beers that flow through our APIs. Enter Bean Validation aka JSR 303/380.

In our previous blog post we mentioned that Bean Validation didn’t seem to be kicking in though all the proper prerequisites seemed to be in place. In this blog post – in which we’ll continue development on the GitHub code of our previous blog post – we’re gonna fix this. As it will turn out this fix only requires a small alteration of our code.

Bean validation

First off, the useBeanValidation Codegen Option on Swaggerhub which I enabled when generating the code in my previous blog post, don’t seem to have any effect. All the proper Bean Validation annotations are in place after generation whether this setting is flagged or not.

Let’s inspect the generated classes. As we can see the proper @Valid annotation has been added to the beer parameter of the addToBeerRepositoryUsingPOST method of the  HelloBeerApi class and implementing HelloBeerApiController class.

public ResponseEntity addToBeerRepositoryUsingPOST(@ApiParam(value = "beer" ,required=true )  @Valid @RequestBody Beer beer)

The model class Beer also has the proper @Validated annotation at class level and it has the @NotNull annotation on the name property. This should make it impossible to add a nameless beer to our beer collection.

@Validated
@javax.annotation.Generated(value = "io.swagger.codegen.languages.SpringCodegen", date = "2018-01-21T19:48:57.257Z")

public class Beer   {
  ....
  @ApiModelProperty(required = true, value = "")
  @NotNull
  public String getName() {
    return name;
  }
  ....
}

So when we run this code (via IntelliJ’s Run SpringBoot configuration) and try to enter a nameless beer of dubious quality we would expect some sort of validation error to kick in. Unfortunately that’s not the case as this screenshot shows:

Screenshot from 2018-02-04 17-56-42

Something went horribly wrong here and we ended up with an inferior beer added to our inventory. Luckily the fix is pretty simple. SwaggerHub added a provided dependency on the validation-api artifact. This means the api won’t be available at runtime causing the validations to fail. We could remove the provided scope but since the dependency is intrinsically present in the pom file via one of the spring boot starter dependencies, we can remove the dependency as a whole from our pom file.

<dependency>
  <groupId>javax.validation</groupId>
  <artifactId>validation-api</artifactId>
  <version>1.1.0.Final</version>
  <scope>provided</scope>
</dependency>

After getting rid of the validation-api dependency and spinning up our application again, we can see that the Bean Validation annotations do their proper job:

Screenshot from 2018-02-04 18-01-58

One last note here: when running the application via mvn spring-boot:run both versions worked regardless of whether the provided dependency was in the pom or not. Not sure what’s causing the difference. Maybe IntelliJ is using a different Maven plugin, or maybe it’s just totally bypassing Maven.

java8

One further note. The code we developed in our previous blogpost was generated without flagging the java8 Codegen option. But we did use a java 8 lambda in our BeerConverter class. What’s that all about? Well, I changed the java 1.7 settings in the pom file and switched them to 1.8 to get the code to compile.

So why not generate java8 code directly? The simple explanation for that is the the java8 code being generated didn’t compile. Apparently java8 and the delegate pattern don’t play well with each other. The HelloBeerApi.getAllBeersUsingGET method gets generated with a type parameter of type Optional while the HelloBeerApiDelegate,getAllBeersUsingGET method has a type parameter of a plain old String type. Since the type parameter gets passed from api to delegate you get a compiler error.

I tried fixing this by playing along with the useOptional Codegen Option on SwaggerHub but this setting didn’t have any effect on the code being generated.

Summary so far

The code generated by SwaggerHub clearly gets the work done. It’s still a bit buggy though imho. The java8 flag for example doesn’t play well with the delegatePattern flag, some settings like the useBeanValidation and useOptional settings don’t seem to have any effect at all (though it may be that these are only effective when other settings are in place) and some settings are just plain unclear.

In the next blog post we’re gonna look at some more automation. Clearly an improvement on our Swagger-first development would be if we could get maven to pick up the Swagger api file and generate the code as part of the build. Another thing that needs to be taken care of when we switch to Maven generation, is that we want to have full control over our bootstrap class and properties file. We don’t want those files being overwritten by the code generation process.

Stay tuned for my next blog post to find out if I could get this all to work.

References

 

 

Have Beer – Will Swagger

Alright Swaggering onwards. In this blog post we’ll take a look at contract-first development with Swagger and Spring Boot. Again the code developed in this post will be available on GitHub. The Swagger api we’ve used is available on SwaggerHub.

Swaggerhub

There’s more than one way to skin a cat as it comes down to transforming a Swagger API into some workable code. This post will focus on using Swaggerhub to generate the code. For simplicity sake we’ll just use the Swagger api that was exposed in my previous blogpost by the springfox plugin (available at the /swagger-ui.html url). I’ve added the API to Swaggerhub and published it here.

Screenshot from 2018-01-28 14-56-03

Swaggerhub can generate server code from a Swagger API for a lot of different coding frameworks, where each framework on its turn has a plethora of options to tune its generated code.

Code generation

I like to put all generated code into a separate package to clearly distinguish it, from non-generated code. The latter can then be adjusted at will, while the former should only be adjusted by regeneration.

To tweak the settings for the Spring Boot application generation, click the settings icon (second icon on the right) in the top right corner of the Swaggerhub menu and select Edit CodeGen Options. Select Servers, Spring:

Screenshot from 2018-01-28 15-06-50

I’ve tweaked the following settings to get the code in my preferred package hierarchy:

configPackage nl.whitehorses.hellobeer.generated.config
delegatePattern enabled
apiPackage nl.whitehorses.hellobeer.generated.api
invokerPackage nl.whitehorses.hellobeer
modelPackage nl.whitehorses.hellobeer.generated.model

Some pointers here:

  • The delegate pattern – when enabled – enables you to keep the generated code seperated from the actual implementation code, meaning you don’t have to adjust any code available in the config, api and model packages to implement the api;
  • The api package will contain the HelloBeerApiDelegate interface (enabled by setting the aforementioned delegatePattern flag). This is the interface containing the methods we’re going to implement;
  • The model package will contain the Beer model class;
  • Make sure that the generated Spring Boot application (available in the invokerPackage) will be somewhere at the top of the package hierarchy as it will only scan the annotated Spring components deeper in the hierarchy;
  • There’s also an option called useBeanValidation. Flagging it didn’t seem to do much and it definitely didn’t have the desired effect. Omitting the required Beer.name property from a JSON POST request didn’t result in the desired validation error.

Now that the settings are set, we can put on our safety goggles and launch the code generator. Just click on the download icon (third icon on the right), select Server, Spring and you can download the zipfile with all the necessary code.

Screenshot from 2018-01-28 16-15-37

Implementation

The zipfile you downloaded in the previous step, contains a Maven pom file. Import it as a project in IntelliJ and you’re almost ready to go. You can give it your first swing, but on my first try I got an error upon booting. Somewhere in the error stack trace you’ll see the reason why:

java.lang.NoClassDefFoundError: javax/servlet/ServletContext

The solution is to get rid of the spring-boot-starter-tomcat dependency in the generated pom file. After doing that the application will boot.

Implementing the delegate

The model and repository code will be the same as the ones we used in our previous blogpost. The only thing we need to do, is implement the delegate interface. This is the code that will do the trick:

@Service
public class HelloBeerService implements HelloBeerApiDelegate {

    private static final Logger logger = LoggerFactory.getLogger(HelloBeerService.class);

    @Autowired
    private BeerConverter beerConverter;

    @Autowired
    private HelloBeerRepository helloBeerRepository;

    @Override
    public ResponseEntity addToBeerRepositoryUsingPOST(Beer beer) {
        logger.info("POST");

        nl.whitehorses.hellobeer.model.Beer beerEO = helloBeerRepository.save(beerConverter.fromDTOtoEO(beer));
        return ResponseEntity.ok(beerConverter.fromEoToDto(beerEO));
    }

    @Override
    public ResponseEntity<List> getAllBeersUsingGET(String type) {
        logger.info("GET");

        List beerDTOs;
List beerEOs;
        if (type == null) {
            beerEOs = helloBeerRepository.findAll();
        } else {
            beerEOs = helloBeerRepository.findByType(BeerType.valueOf(type));
        }

        beerDTOs = beerEOs.stream().map(beerConverter::fromEoToDto).collect(Collectors.toList());

        return ResponseEntity.ok(beerDTOs);
    }

}

I’ve implemented both methods (POST beer and GET beers) of the HelloBeerApiDelegate interface in the HelloBeerService service. Notice that most of the code reflects the code I’ve used in the previous blogpost.

I’ve had to put some code in place to convert the generated model Beer class (I labeled this one Data Transfer Object) to our Entity annotated model Beer class (the Entity Object) and vice versa though. I put this code in the BeerConverter class which is an annotated Spring Component. Through injection we’ll make the BeerConverter available to the Service.

Building the BeerConverter

@Component
public class BeerConverter {
    private static final Logger logger = LoggerFactory.getLogger(BeerConverter.class);

    public nl.whitehorses.hellobeer.generated.model.Beer fromEoToDto(Beer beerEO) {
        nl.whitehorses.hellobeer.generated.model.Beer beerDTO = new nl.whitehorses.hellobeer.generated.model.Beer();
        BeanUtils.copyProperties(beerEO, beerDTO);
        beerDTO.setType(nl.whitehorses.hellobeer.generated.model.Beer.TypeEnum.valueOf(beerEO.getType().toString()));

        return beerDTO;
    }

    public Beer fromDTOtoEO(nl.whitehorses.hellobeer.generated.model.Beer beerDTO) {
        Beer beerEO = new Beer();
        BeanUtils.copyProperties(beerDTO, beerEO);
        beerEO.setType(BeerType.valueOf(beerDTO.getType().toString()));

        return beerEO;
    }

}

The code speaks for itself. For the simple properties I just use the BeanUtils.copyProperties method that Spring provides. And for converting the beer type I put some custom code in place.

Unit testing the converter

To test if our converter works, I put the following unit test in place:

@RunWith(SpringRunner.class)
@SpringBootTest
public class BeerTest {

    @Autowired
    BeerConverter beerConverter;

    @Test
    public void fromEoToDto() {
        Beer beerEO = new Beer();
        beerEO.setId(1L);
        beerEO.setBrewery("Brand");
        beerEO.setName("Brand Saison");
        beerEO.setType(BeerType.OTHER);

        nl.whitehorses.hellobeer.generated.model.Beer beerDTO = beerConverter.fromEoToDto(beerEO);

        assertEquals("OTHER", beerDTO.getType().toString());

    }

    @Test
    public void fromDtoToEo() {
        nl.whitehorses.hellobeer.generated.model.Beer beerDTO = new nl.whitehorses.hellobeer.generated.model.Beer();
        beerDTO.setId(1L);
        beerDTO.setBrewery("Brand");
        beerDTO.setName("Brand Saison");
        beerDTO.setType(nl.whitehorses.hellobeer.generated.model.Beer.TypeEnum.OTHER);

        Beer beerEO = beerConverter.fromDTOtoEO(beerDTO);

        assertEquals("OTHER", beerEO.getType().toString());
    }

}

Look at how you can nicely inject the BeerConverter into the test class. The SpringBootTest annotation makes this possible.

Adding initial data

To get some initial data in our H2 database I’ve added the following data.sql file in the src/main/resources directory:

INSERT INTO beer (name, type, brewery) VALUES
  ('Brand Saison', 5, 'Brand');
INSERT INTO beer (name, type, brewery) VALUES
  ('Brand IPA', 3, 'Brand');

Testing

We can use the same urls we used in the previous blogpost for testing our new and improved contract-first api. So let us post a new beer first:

Screenshot from 2018-01-28 17-33-52

And finally, get all the beers. This will show our seeded data as well as the beer we POSTed in the previous step.

Screenshot from 2018-01-28 17-35-18

The nice thing about the code that Swaggerhub generated for us, is that they’ve also put the springfox functionality in, so our Swagger contract is automatically available at the /swagger-ui.html url:

Screenshot from 2018-01-28 17-37-33

Summary

That’s all for now folks! We’ve just shown how relatively easy it is to build and implement a Swagger API contract-first with the help of Swaggerhub and SpringBoot.

One of the downfalls of this approach is the need to transform the generated model to our own model classes. Luckily Spring can help us out a little here by using their BeanUtils class. The approach I advertise here is to build a Spring Component per model class in which you put the transform logic (one transform method from model (EO) to generated model (DTO) and one method from generated model to model). You can even define a nice generic interface for those classes. The Spring Component can then be injected into the service implementing the delegate interface for the REST controller.

As stated I couldn’t get the Bean Validation option to do its work in the generated code. I’ll play around some more in the near future and when I get it to work, will put a small additional blog post online.

Another downside is the manual step I had to perform to get the generated code into my maven project. In the next blog, I’ll have a go at automating this with the help of Maven.

References

Putting Spring Boot to REST with Swagger (and grab a beer in the process)

This blog post (the first in years) will be part of  a small series in which I’ll explore the world of Spring Boot (micro)services. I’ll start out by building a simple Spring Boot REST service and expose the service API via Swagger – the de facto standard for describing REST apis.

The code being built in the context of this blog post can be found on GitHub.

Hello Beer

Instead of building the obligatory HelloWorld service, I’ve decided to build a HelloBeer service instead, beer being one of the finer pleasures in life imho.

First Project

Let’s get to work! I’ll create the project with IntelliJ using the Spring Initializr and select the Web, JPA and H2 dependencies.

Screenshot from 2018-01-20 20-40-44

Screenshot from 2018-01-20 20-42-19

After clicking through to the finish line, you’ll get a working Spring Boot project with a pom file containing the dependencies you just selected, and the bootstrap class BeerAppApplication.

Model

The model is very simple: a small Beer class and a BeerType enum. I’ll put the JSR 303 annotations @NotNull on the name to demonstrate later on that the Swagger documentation can reflect this (by displaying the name as a required attribute of a Beer).

@Entity
public class Beer {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @NotNull
    private String name;
    private BeerType type;
    private String brewery;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BeerType getType() {
        return type;
    }

    public void setType(BeerType type) {
        this.type = type;
    }

    public String getBrewery() {
        return brewery;
    }

    public void setBrewery(String brewery) {
        this.brewery = brewery;
    }
}

public enum BeerType {
    LAGER,
    PILSNER,
    PALE_ALE,
    INDIA_PALE_ALE,
    STOUT,
    OTHER
}

Repository

Adding a repository is pretty simple. Just extend the JpaRepository interface (the second typed parameter “Long” should correspond with the type of the id) and you get a lot of repository methods for free. For the fun of it, I’ve added an additional method for getting the list of beers based on the beer type.

public interface BeerRepository extends JpaRepository<Beer, Long> {

    List<Beer> findByType(BeerType beerType);
}

The interface (and the method we’ve added) will be magically implemented by Spring Boot.  And – because we’ve added H2 as a dependency – the beers we save, will be persisted to an H2 memory database (note: every time you restart, the database will be empty again) without writing any additional lines of code or configuration.

Controller

Now all we need to get this baby rolling, is a Restful controller. I’ve added a method for POSTing (saving) a beer and one for GETting a list of beers, optionally filtered by the beertype.

@RestController
@RequestMapping("/hello-beer/1.0")
public class BeerController {

    @Autowired
    private BeerRepository beerRepository;

    @RequestMapping(value = "/beer", method = RequestMethod.POST, produces = "application/json")
    public Beer addToBeerRepository(@RequestBody Beer beer) {

        return beerRepository.save(beer);
    }

    @RequestMapping(value = "/beers", method = RequestMethod.GET, produces = "application/json")
    public List<Beer> getAllBeers(@RequestParam(value = "type", required = false) String beerType) {
        if (beerType == null)
            return beerRepository.findAll();
        else
            return beerRepository.findByType(BeerType.valueOf(beerType));
    }

}

The code is pretty self-explanatory. Just wire in the repository and you’re ready to persist and retrieve some wonderful beers. The endpoints will be prepended with the path /hello-beer/1.0.

Testing

After running the service we can POST a few new beers on the URL /hello-beer/1.0/beer
Screenshot from 2018-01-20 21-53-33

Getting the list of beers filtered by type for example can be done like this: /hello-beer/1.0/beers?type=OTHER
Screenshot from 2018-01-20 21-53-58

Almost to easy, isn’t it? Now let’s try to document the API of our Hello Beer service using Swagger.

Swagger

To get the most out of our service we’ll be needing the following three dependencies:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.8.0</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.8.0</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-bean-validators</artifactId>
    <version>2.8.0</version>
</dependency>

The last dependency will interpret the JSR 303 annotations and put the in the API accordingly
Last piece of the puzzle is some configuration that needs to be added:

@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerConfig {
    @Bean
    public Docket api() {

        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.basePackage("nl.whitehorses.beerapp.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    @Bean
    UiConfiguration uiConfig() {
        return UiConfigurationBuilder.builder().build();
    }

}

Noteworthy is the @Import line that’s needed for the JSR 303 implications to be transferred to the Swagger documentation.

Also take note of the RequestHandlerSelectors filter. I could have picked the RequestHandlerSelectors.any() filter, but if I did that, the error-controller would have ended up in my API adding some weird models in the process. This way I’ll keep my API nice and clean, just focussing on the beers.
Spinning up the application again, you can check the API on the url /swagger-ui.html:
Screenshot from 2018-01-20 22-11-04

As you can see by the red asterisk after the Beer.name property, the JSR 303 annotation is being picked up nicely by the swagger bean validator plugin.

By tweaking the configuration some more, you can probably get the Swagger API to look just the way you like it (for one we could change the title into something more meaningful than just Api Documentation by chaining the apiInfo method to the build method of the Docket).

Conclusion

In this post we’ve seen how easy it is to get a small Spring Boot REST service up and running and generate and expose the corresponding Swagger API documentation. The next blog post will see me exploring the world of contract first development.

I’ll then start by documenting the Swagger API and try to generate the necessary service interface code and only then start building the actual implementation.

References

Grails Web Services

In this blog we’ll expose a Grails service as a SOAP service. According to good practice we’ll build the WSDL first and then write the implementation code.
First things first. Let’s create a new grails application and call it grails-soap

grails&gt; create-app grails-soap

 

CXF

For SOAP support we’ll be using the Grails CXF plugin. Just add the following line in the plugin section of your BuildConfig.groovy file to enable the plugin. Documentation for the plugin can be found here.

compile ':cxf:1.1.1'

 

WSDL

We’ll start with building the WSDL for the service. The service will be called DepartmentService and will return some Department data for a given id. We’ll place the WSDL in the src/java folder.

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;wsdl:definitions name=&quot;DepartmentService&quot;
	targetNamespace=&quot;http://devjournal/DepartmentService&quot; xmlns:wsdl=&quot;http://schemas.xmlsoap.org/wsdl/&quot;
	xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot; xmlns:soap12=&quot;http://schemas.xmlsoap.org/wsdl/soap12s/&quot;
	xmlns:tns=&quot;http://devjournal/DepartmentService&quot;&gt;
	&lt;wsdl:types&gt;
		&lt;xsd:schema xmlns=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
			&lt;import namespace=&quot;http://devjournal/DepartmentService&quot;
				schemaLocation=&quot;DepartmentService.xsd&quot; /&gt;
		&lt;/xsd:schema&gt;
	&lt;/wsdl:types&gt;
	&lt;wsdl:message name=&quot;DepartmentServiceRequestMessage&quot;&gt;
		&lt;wsdl:part name=&quot;in&quot; element=&quot;tns:DepartmentServiceRequest&quot; /&gt;
	&lt;/wsdl:message&gt;
	&lt;wsdl:message name=&quot;DepartmentServiceResponseMessage&quot;&gt;
		&lt;wsdl:part name=&quot;out&quot; element=&quot;tns:DepartmentServiceResponse&quot; /&gt;
	&lt;/wsdl:message&gt;
	&lt;wsdl:portType name=&quot;GetDepartmentById&quot;&gt;
		&lt;wsdl:operation name=&quot;getDepartmentById&quot;&gt;
			&lt;wsdl:input message=&quot;tns:DepartmentServiceRequestMessage&quot; /&gt;
			&lt;wsdl:output message=&quot;tns:DepartmentServiceResponseMessage&quot; /&gt;
		&lt;/wsdl:operation&gt;
	&lt;/wsdl:portType&gt;
	&lt;wsdl:binding name=&quot;GetDepartmentByIdSoap12&quot; type=&quot;tns:GetDepartmentById&quot;&gt;
		&lt;soap12:binding transport=&quot;http://schemas.xmlsoap.org/soap/http&quot;
			style=&quot;document&quot; /&gt;
		&lt;wsdl:operation name=&quot;getDepartmentById&quot;&gt;
			&lt;soap12:operation
				soapAction=&quot;http://whitehorses.nl/Whitebook_SOA_UT/DepartmentService/GetDepartmentById&quot;
				style=&quot;document&quot; /&gt;
			&lt;wsdl:input&gt;
				&lt;soap12:body use=&quot;literal&quot; parts=&quot;in&quot; /&gt;
			&lt;/wsdl:input&gt;
			&lt;wsdl:output&gt;
				&lt;soap12:body use=&quot;literal&quot; parts=&quot;out&quot; /&gt;
			&lt;/wsdl:output&gt;
		&lt;/wsdl:operation&gt;
	&lt;/wsdl:binding&gt;
	&lt;wsdl:service name=&quot;DepartmentService&quot;&gt;
		&lt;wsdl:port binding=&quot;tns:GetDepartmentByIdSoap12&quot; name=&quot;GetDepartmentByIdSoap12&quot;&gt;
			&lt;soap12:address location=&quot;http://www.example.org/&quot; /&gt;
		&lt;/wsdl:port&gt;
	&lt;/wsdl:service&gt;
&lt;/wsdl:definitions&gt;

The underlying xml schema file contains the response element. This file will also be placed in the src/java folder.

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;schema attributeFormDefault=&quot;unqualified&quot; elementFormDefault=&quot;qualified&quot;
        targetNamespace=&quot;http://devjournal/DepartmentService&quot;
        xmlns:tns=&quot;http://devjournal/DepartmentService&quot;
        xmlns=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt;
 &lt;element name=&quot;DepartmentServiceRequest&quot;&gt;
  &lt;complexType&gt;
   &lt;sequence&gt;
    &lt;element name=&quot;Id&quot; type=&quot;int&quot;/&gt;
   &lt;/sequence&gt;
  &lt;/complexType&gt;
 &lt;/element&gt;
 &lt;element name=&quot;DepartmentServiceResponse&quot;&gt;
  &lt;complexType&gt;
   &lt;sequence&gt;
    &lt;element name=&quot;Department&quot; type=&quot;tns:departmentType&quot; maxOccurs=&quot;1&quot;
             minOccurs=&quot;0&quot;/&gt;
   &lt;/sequence&gt;
  &lt;/complexType&gt;
 &lt;/element&gt;
 &lt;complexType name=&quot;departmentType&quot;&gt;
  &lt;sequence&gt;
   &lt;element name=&quot;Id&quot; type=&quot;int&quot;/&gt;
   &lt;element name=&quot;Name&quot; type=&quot;string&quot;/&gt;
   &lt;element name=&quot;Location&quot; type=&quot;string&quot;/&gt;
  &lt;/sequence&gt;
 &lt;/complexType&gt;
&lt;/schema&gt;

 

wsdl2java

Now that we have the WSDL it’s time to generate the Java stubs. Although the CXF plug-in comes with a wsdl-to-java command it kept giving me a “GroovyCastException” when I tried to run it. To workaround this problem, I downloaded the latest apache-cxf distribution here (2.7.11 at the time of this writing) and used its wsdl2java command to generate the stubs.

$ $CXF_HOME/apache-cxf-2.7.11/bin/wsdl2java DepartmentService.wsdl

After running this command from within the /src/java directory, the following stub classes are added to your grails application:

wsdl2java classes
wsdl2java classes

 

service

Now everything is in place, we can start implementing the service. First create a new grails service component called DepartmentService

grails&gt; create-service department

We’ll have this service implement the generated @WebService interface GetDepartmentById and override the getDepartmentById method (corresponding with the SOAP operation of the same name) For simplicity sake, we’ll just hardcode a response:

package grails.soap

import javax.jws.WebService

import org.grails.cxf.utils.EndpointType

import devjournal.departmentservice.DepartmentServiceRequest
import devjournal.departmentservice.DepartmentServiceResponse
import devjournal.departmentservice.DepartmentType
import devjournal.departmentservice.GetDepartmentById


@WebService(targetNamespace = &quot;http://devjournal/DepartmentService&quot;, name = &quot;GetDepartmentById&quot;, serviceName = 'DepartmentService',
portName = 'GetDepartmentById')
class DepartmentService implements GetDepartmentById {

	static expose = EndpointType.JAX_WS_WSDL
	static soap12 = true
	static address = 'DepartmentService'
	
	def serviceMethod() {
	}

	@Override
	public DepartmentServiceResponse getDepartmentById(
			DepartmentServiceRequest departmentServiceRequest) {

		DepartmentType department = new DepartmentType(id: departmentServiceRequest.id, location:'Amsterdam', name: 'Sales')
		return new DepartmentServiceResponse(department:department)
	}
}

As you can see in the code above, we’ve implemented the GetDepartmentById interface and added the @WebService annotation to the service. With the serviceName and portName attributes we can influence the WSDL that’s eventually being served.
The cxf-plugin allows further configuration by means of static properties. Setting the soap12 property to “true” makes the DepartmentService adhere to the SOAP 1.2 specification. With the address property we can adjust the endpoint of the service. By default it would be the default address of the grails service, i.e. “/services/department”. In the above example the endpoint will be “/services/DepartmentService”. Refer to the cxf-plugin documentation for an overview of available properties.
 

Testing the web service

Now let’s fire up the application and give it a spin

grails&gt; run-app

The WSDL should be available at http://localhost:8080/services/DepartmentService?WSDL and can be tested with SoapUI. The screenshot below shows the result.

DepartmentService Test
DepartmentService Test

 

Conclusion

In this blog I’ve shown how easy it is to expose a grails service via SOAP. Although the service had been turned into a SOAP service it’s still available as a normal grail service to the rest of the application, so there’s no violation of the DRY principle and code can be reused.

Grails in the Cloud Foundry

In this blog I’ll show you how easy it is to get a small Grails app up and running on Cloud Foundry making use of a mysql service provided by Cloud Foundry. We’ll be using the Groovy & Grails Toolsuite (ggts) for this, but I’ll also show you the grails commands you can use to accomplish each individual step.

Setup

  • At the time of this blogpost I’m using ggts version 3.1.0.RELEASE based on Eclipse Juno 4.2.1, which can be downloaded right here;
  • ggts comes with a full Grails installation. To make use of command line grails commands outside of the IDE, set the following environment variables. If you’re an Ubuntu user like me, just add these two lines to your ~/.bashrc file:
    • export GRAILS_HOME=<ggts_home>/grails-2.1.1;
    • export PATH=$PATH:$GRAILS_HOME/bin;
  • Apply for a Cloud Foundry account right here. You’ll receive an email of approval which will contain your  password;
  • Enable Cloud Foundry Integration in ggts. Click the Extensions link on the Dashboard, scroll down to Cloud Foundry Integration for Eclipse and install it.
Screenshot from 2013-02-17 15:40:52
Cloud Foundry Integration for Eclipse

Building a simple Grails app

We’re gonna develop a very simple Grails app. Just enough for demonstration purposes. It’ll be an app that enables you to create notes and store them in a database. We’ll call it one-note.

Grails Project

Choose File > New > Grails Project and supply the project-name. Alternatively you could use the command line and type:

grails create-app one-note

There’s also a command line interface available in ggts itself (Navigate > Open Grails Command Prompt). All commands are available here (just ommit the grails prefix), except for the creation of an application.

Screenshot from 2013-02-24 16:54:11
Grails Command Prompt

Domain Class

Choose File > New > Domain Class and name it Note. The Note.groovy domain class will be created for you. You can also create the class via this command line:

grails create-domain-class note

Add two simple fields to the domain class, so it looks like this:

package one.note

class Note {

    String content
    Date dateCreated

    static constraints = {
    }
}

The dateCreated is a standard field which will be supplied for by the Grails framework, the content field will contain the actual note.

Controller

Choose File > New > Controller and name it NoteController. The NoteController.groovy controller will be created for you. The equivalent command would be

grails create-controller note

Add scaffolding and reroute the index action to the list action. Your controller should now look like this

package one.note

class NoteController {

    def scaffold = true

    def index() {
        redirect(action:list)
    }
}

Testdrive the application

That’s basically all we need to run the application locally and make use of an in-memory hsqldb. Select Run > Run As > Grails Command (run-app), and point your browser to http://localhost:8080/one-note and you’re good to go. Select the NoteController in the Overview page, create some notes and your application should resemble the picture below.

Screenshot from 2013-02-24 18:05:49
one-note Grails application

Alternatively you could achieve the same via the command line:

grails run-app

Publish to Cloud Foundry

Although not entirely necessary, it’s a good practice to change your production configuration in the Datasource.groovy file. Add the following lines

environments {
    production {
        dataSource {
            dbCreate = &quot;update&quot;
            driverClassName = &quot;com.mysql.jdbc.Driver&quot;
        }
    }
}

Furthermore edit the BuildConfig.groovy and add the following dependency:

dependencies {
runtime &quot;mysql:mysql-connector-java:5.1.23&quot;
}

Cloud Foundry Integration style

Add a new server (File > New > Other > Server) and select Cloud Foundry as the type.

Screenshot from 2013-02-24 18:33:21
New Server > Define a New Server

Fill in your Cloud Foundry account information and press Validate Account to make sure you entered everything correctly.

Screenshot from 2013-02-24 18:33:35
New Server > Cloud Foundry Account

Now go to the Applications tab and Add the one-note application from Available to Configured and click Finish.

Change Runtime to Java 7, click Next >

Screenshot from 2013-02-24 18:38:11
Application > Application Details

Note the Deployed URL and click Next >

Screenshot from 2013-02-24 18:39:22
Application > Launch deployment

Click Add Service to add a mysql service, give it a name (I choose one-note) and select MySQL database as the type and click Finish.

Screenshot from 2013-02-24 18:40:33
Add Service > Service Configuration

Make sure, the new mysql service is selected and click Finish.

Screenshot from 2013-02-24 19:14:44
Application > Services selection

Now the application will get started and you’ll get a nice overview of your application running in Cloud Foundry.

Screenshot from 2013-02-24 18:49:41
Application overview

Also take note of the Remote Systems window in ggts. Here you can for one take a look at all the log files in your Cloud Foundry environment.

Screenshot from 2013-02-24 13:17:11
Remote Systems

That’s it. You can now test your application on the following url: http://one-note.cloudfoundry.com.

Screenshot from 2013-02-24 19:00:21
one-note in the cloud

Command line style

To enable Cloud Foundry commands via the command line you have to add a plugin to the application:

grails install-plugin cloud-foundry

Next add the following two lines to the ~/.grails/settings.groovy file:
grails.plugin.cloudfoundry.username = “yourusername”
grails.plugin.cloudfoundry.password = “yourpassword”

Now you can push the one-note application to Cloud Foundry:

grails prod cf-push

Accept the default url and  choose y at “Would you like to create and bind a mysql service” and n at the same question for a postgresql service.

While building the war for deployment, you might see and Error about a missing migrations directory. This is caused by the database-migration plugin. It’s harmless, but if you want to get rid of it, just add the migrations directory in the grails-app subdirectory of the application.

That’s it. You can test the application via the same url we used before when we used Cloud Foundry Integration: http://one-note.cloudfoundry.com.

There are lots of command available in the plugin. There are for example commands for restarting and deleting a deployed app or service. You can display the list of available commands with:

grails cf-help

Summary

In this blogpost we’ve built a simple Grails application and pushed it to Cloud Foundry, making use of a mysql database service. We’ve shown how to do it via the command line as well as via the Groovy/Grails Tool Suite with the Cloud Foundry Integration plugin. Whichever way you prefer, both ways are very powerful very easy to use. I myself often use a hybrid approach. For the creation of components and pushing the application to the cloud, I use the command line approach . And for managing the deployed applications, I make use of the nice overview interface that the Cloud Foundry Integration Plugin provides.

References