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

Devoxx 2010 impressions – day 1

Last week I enjoyed 2 great University days at Devoxx. In this blog post i’ll comment on the 2 main talks i’ve visited on monday, i.e. Seam 3 and Spring Roo. Both talks had a lot in common.
In the past both were JEE frameworks which tried to fill a gap in traditional JEE development. The Spring framework simplified for one the whole entity bean fiasco of EJB2 by introducing a model layer based on POJOs and was typically a framework used for integration in the model layer of enterprise development. Springs lessons led to the EJB3 spec in JEE5 and the Managed Bean spec in JEE6.
Seam on the other hand filled the gap of integrating the view and the model layer, making it much easier to couple JSF pages to Session Beans (or their Seam counterparts). Its lessons have led to the CDI spec in JEE6 and (i think) to the EJB Lite spec.
Now, while both were considered a framework in the past, they are now in their latest incarnations both full blown stacks for Java Enterprise Development. And in this they have a lot in common. To name a few:

  • Both have their own (eclipse-)based IDE. For Spring it’s called SpringSource Tool Suite (STS), for Seam we have JBoss Developer Studio;
  • Both have solutions for cross layer concerns, like security, logging, SOAP/REST integration, event handling and AJAX support, to name a few;
  • Both have a solution for building the view layer. Spring has Spring MVC and Seam uses JSF, CDI and facelets;
  • And now both have their own RAD solution. In Spring it’s called SpringRoo, in Seam it’s called SeamForge.

The last 2 components of the stacks are (especially SeamForge) relatively new. Both are shell based and can also be used in Eclipse as a plugin (Of course, their own IDE’s have these plugins installed by default).

I think it’s a good thing that these stacks are emerging. In the end they will provide you with basically everything you need for Enterprise development. And in the end hopefully it will prevent all these hybrid solutions where everyone uses their favorite framework on the job, which hinders maintainability in the long run imho. The SpringSource stack and the JBoss stack are both big players and i honestly believe that commitment to these stacks by the development community will be an ongoing concern for many years to come.
If I had to pick a favorite among the two. I slightly prefer the JBoss stack, because it adheres much more to the JEE specification.

In the next 2 section i’ll summarize some highlights of the 2 talks.

Seam 3: State of the Union

by Pete Muir and Dan Allen

Seam 3 as apposed to the rather monolithic Seam 2 framework is of a modular design. It consists of a set of modules built on top of the core of Seam. This core consists of the reference implementation of CDI, Weld, which currently is supported for the JEE servers JBoss and Glassfish, and for the Web servers Tomcat and Jetty. It is also supported for a standalone JSE environment. Seam 3 is hosted at GitHub and uses Maven for the build lifecycle. There was also talk about the use of Gradle in the near future.

As i sad before. Seam’s 3 approach is more modular than that of its predecessor. Here’s a list of the modules that were presented during the talk:

  • Seam Solder, aka Weld extensions. This is the core of Seam 3 and Pete and Dan stressed that this is the module everyone should use. It provides to name but a few:
    • A lot of familiar Seam 2 annotations (eg. @Requires, @Unwraps);
    • Annotations for Logging;
    • Annotations for Resource handling;
    • Annotations to be used for queries in DAO’s;
  • SeamConfig, which extends the beans.xml configuration file for Seam related configurations in xml-style;
  • SeamInternational, for i18n an l10n support;
  • SeamFaces, which is an enhancement for JSF 2. It contains, to name a few, the familiar (Seam 2) @Conversation scope, support for multiple field validation, composite components and a simple front controller called ViewAction;
  • SeamPersistence, the module for declarative persistence, transactions, manual flushing and the likes;
  • SeamCath for error and event handling;
  • SeamServlet, which provides Servlet enhancements;
  • SeamRest, for REST integration;
  • SeamGWT, for GWT integration.

And already mentioned a big part of the presentation was reserved for a demonstration of the current state of the SeamForge project. It’s the successor to seam-gen. You can use it for RAD. It can generate an entire CRUD application out of the box based on a couple of simple database tables or defined entities. It is shell based and also comes as an IDE (Eclipse) plugin.  I was really impressed by the demo. As with seam-gen, you don’t have to mess with all the configuration files anymore, because you can let SeamForge do this for you. In no time you can generate a fully working demo application for your customers or one to be used as a reference for yourself for development. And SeamForge does this all in Maven style, which is big plus compared to the ANT style seam-gen, if i may say so. I can’t wait to try it all out for myself.

Another big topic was the Arquillian project. It contains for one an embedded container used for testing an enterprise application. Arquillian can be integrated in a testing framework like JUNIT or TestNG. Control of the container is handled via ANT tasks or a Maven plugin.

Extreme Productivity with Spring Roo

by Ben Alex and Stefan Schmidt

Spring Roo is a project within the SpringSource stack comparable to SeamForge. You can generate a CRUD application with it in no time in the Spring style. Like SeamForge, SpringRoo generates a Maven application, it can be controlled via highly intelligent shell commands and also comes with an Eclipse plugin.

It makes heavy use of AspectJ files. For example it puts the getter and setter methods of the generated JPA classes in a seperate AspectJ file per class. This keeps the JPA classes very clean. Another benefit is that the AspectJ classes can be generated (or even incrementally updated) so they can be omitted from the version control system. If you have the AspectJ plugin installed in Eclipse, code completion will work even for the code in the AspectJ files like those getter and setter methods. Of course STS comes with this plugin already installed.

The JPA classes that are generated by SpringRoo contain JPA 2 annotations and a couple of SpringRoo specific annotations.

Removing all of SpringRoo from your application can be done in three simple steps:

  1. Refactor the AspectJ code back in your Java code (can be done via the AspectJ plugin);
  2. Remove The SpringRoo annotations (search/delete);
  3. Remove the SpringRoo jar from you pom.xml.

Another part of the presentation showed the use of the Hades plugin for SpringRoo. With Hades you can generate a generic DAO layer on top of your JPA layer. Very powerful stuff.

The last big part of the presentation showed the view layer generation capabilities of SpringRoo. SpringRoo lets you generate a Spring MVC layer and takes care of a lot of scaffolding for you, again removing you of the burden of getting all those configuration files right. It eg. can take care of:

  • REST support
  • Templating support
  • Themes
  • i18n, l10n
  • Bean validation
  • Security
  • Spring WebFlow

All in all, this was the second time this day i was pretty impressed, and again I can’t wait to play with this stuff.