Blog

Building a Custom Spring Boot Starter

Spring Boot has become incredibly popular since it was first released in 2013. Starting from scratch; a developer can have an application communicating with a database through RESTful endpoints that have security configured for them all within the span of an hour. This was a huge improvement over the often days it would take to accomplish similar tasks using just the core Spring Framework.

Spring Boot itself has some core functionality, but much of what Spring Boot application will be doing; communicating with a database, providing REST endpoints, and processing security on incoming requests, are supplied through starters. The Spring team, and third party vendors that integrate with Spring, have created many publicly available starters which can be seen on start.spring.io.

These starters are great, but organizations have domain specific concerns. Organizations typically only use certain database vendors, have specific requirements when implementing security, among many other needs. Here it can be beneficial to create custom Spring Boot Starters that incorporate these constraints and requirements. In this article we will walk through the process of creating a custom Spring Boot starter.

Not Just Another Shared Library

Organizations creating shared libraries to handle cross-cutting concern like data access or security isn’t new. What is new is the Spring team has provided several extension points within Spring Boot that can be used to improve the developer experience, these shared libraries are called “starters”. Improving developer experience can increase the active use of a library which can help in making sure standards are followed across an organization.

Starter Components

There are several extensions points the Spring team has provided for building starters they are:

  • Auto-Configuration
  • Conditionals
  • Metadata for Configuration

We will step through how to use each of these features when building a starter so that it; requires minimal configuration to be used, is flexible for a variety of scenarios, and provides developers with information they need to configure it.

We will use security, my-org-starter-security, as an example for building the custom starter. Security is a common concern for organizations, it is also something that require some amount of configuration, and also might need to behave differently depending on context. This will give us a good opportunity to flex out all the above features in a semi-realistic scenario.

You can find the code example used in this article on my GitHub.

Auto-Configuration

Spring Boot is often described as being “opinionated”, one of the ways this is done is through auto-configuration. Spring components can be automatically (automagically?) loaded into context without requiring developer intervention. This is great for making your starter easier to consume and also used correctly (i.e. ensure required classes/beans are loaded). To have a component be auto-loaded requires following a few steps:

1. Add spring-boot-autoconfigure as a dependency

For auto-configuration to work, and to have the appropriate classes available, the spring-boot-autoconfigure dependency must be on classpath. The dependency can be added directly, or indirectly by including another starter as a dependency. In my example I am using spring-boot-starter as a dependency.

2. Create a Configuration class

Create a normal configuration class like you would within a Spring Boot application and have it perform whatever required behavior you need. In this example we will have the @Configuration class load a UserDetailsService and PasswordEncoder into the application context.

Full class here.

3. Add spring.factories

Next we need to tell Spring Boot that the class ​SecurityConfig is a candidate for auto-configuration. To do this we need to create a file named spring.factories which needs to be located under the META-INF (typically this is located src/main/resources, like this). Within spring.factories we will add the following:

Now when a developer brings in the my-org-starter-security, the class SecurityConfig will be automatically loaded into the application context.

Conditionals

Auto-configuration is great, but there might be components you want to load only in a certain scenarios. In our hypothetical organization we will have both web based and console based applications. How security works in these scenarios would differ dramatically, however using conditionals we can have only the appropriate classes loaded into the application context depending on the scenario, this saves developers who are using our starter from a lot of headaches.

Spring Boot provides a lot of flexibility when it comes to defining conditionals, however in this example we will use a couple of pre-defined ones @ConditionalOnWebApplication and @ConditionalOnNotWebApplication. Let’s create a couple classes that will only be auto-configured conditionally.

1. Create configuration classes

Like above we will create a couple of standard @Configuration classes, however we will also need to annotate those classes with the appropriate annotations, @ConditionalOnNotWebApplication for NonWebSecurityConfig and @ConditionalOnWebApplication for WebSecurityConfig. The classes look like this:

Note: Conditional annotations can also be placed at the method level if needed.

2. Update spring.factories

The spring.factories file will need to be updated with these new classes to mark them as auto-configuration candidates.

3. Curate Your POM

I will cover this in-depth in a separate article, but a key element in building a good starter, particularly when using @Conditional, is setting up the POM for your starter correctly. Commonly Conditionals will be looking for the presence (or non-presence) of classes on classpath. In my starter POM I made use of optionals, which made consuming my starter easier for console applications:

Metadata for Configuration

Inevitably some amount of configuration is needed. Remembering the exact name for a property or the correct values to supply it with can be difficult. To address this the Spring team provides a mechanism for defining metadata about configuration properties which can provide developers with which properties are available, information about those properties, and hints on valid values.

There are several options for supplying configuration metadata.

1. Add the spring-boot-configuration-processor:

Before you can do anything with metadata you will need to add the spring-boot-configuration-processor to your pom file for the metadata to be generated:

2. Add META-INF/spring-configuration-metadata.json

Under the META-INF folder where we earlier added spring.factories you will need to create another file called spring-configuration-metadata.json which, as its name suggests, Spring will read to generate configuration meta data.

With the initial setup work done, there are several ways to provide configuration metadata. Below at two popular ways of doing this.

Defining metadata in spring-configuration-metadata

Metadata can be defined directly within the spring-configuration-metadata file. Here I am providing metadata on how to configure console security:

With this added, going into application.properties hints are provided saying that my-org.cli.security.required-role is a property, providing information on that property, and then with the hints field, valid values and their meaning can also be provided. This metadata makes configuring security for console applications much easier for developers.

Binding Properties to a Class

Within a @Configuration class I could just use a @Value to retrieve the value of my-org.cli.security.required-role. However I can also bind that property to a class as well, this is particularly helpful when dealing with several properties. To do this simply create a POJO and add a @ConfigurationProperties annotation to it. You will also need to give it a prefix that is the same as the groups value you defined in spring-configuration-metadata, so in this case my-org.cli.security.

Supply Properties to a Configuration Class

If we want to retrieve the values out of CommandLineSecurityConfigurer we will need to annotate a @Configuration class with @EnableConfigurationProperties({ CommandLineSecurityConfigurer.class }), like I did in NonWebSecurityConfig.

Fields and Javadoc as Metadata

Class fields and Javadoc can also be used to provide metadata for properties. I created a second properties class, WebSecurityConfigurer. In this class I have three properties, userEndpoints, adminEndpoints, unsecuredEndpoints, each with Javadoc attached. Because I use the same group name for the prefix in @ConfigurationProperties as I supplied above in spring-configuration-metadata, Spring will process the fields and Javadoc and generate property metadata from it. As can be seen in the screen shot below the code. Like above, the values supplied in applications.properties will be bound to the fields.

Screen Shot 2019-12-30 at 11.31.52 AM

Providing Sensible Configuration Defaults

Another way Spring Boot is described as being “opinionated” is through providing “sensible defaults”. A common way this is experienced is through the default port number Spring Boot uses of 8080. Providing default property values is super easy, as I have done above by initializing unsecuredEndpoints with "/public**". ​

Conclusion

Starters offer a lot of opportunities for organizations to improve the experience of their developers. This article only scrapes the surface of what is possible. Be sure to check out the provided links for more details on how to create starters as well as the official documentation:

Auto-configuration: https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-developing-auto-configuration

Providing metadata: https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-configuration-metadata.html

You can find the code example used in this article on my GitHub.

Travel Tips for Developer Advocates: Part Duex

I published a blog article back in October on my experiences with travel over my first year as a developer advocate. Since then I have thought of several more travel tips, and also learned a couple more, so here is a second article on the topic. If you are a Concur user, you might find my section on Concur trips particularly helpful.

Rapid Fire Travel Tips

  • If you are planning on working during a flight and are flying British Airways, it would be wise to avoid the exit row. British Airways does not allow ANY carry-on baggage to be stored under the seat in front of you. This can make retrieving/storing your work laptop more troublesome.
  • If you find yourself traveling to certain cities frequently, purchase a transit card if applicable. This will make using that city’s public transit easier.
  • Don’t put your passport in the wash, but if you do, dry it out immediately and place it under some heavy books and you should be fine. I have gone through border control in several countries since largely without issue*.
  • Get a passport carrier to hold your transit cards and also help prevent you from doing something dumb and putting your passport in the wash.
  • Check for promotions for hotels you stay at or airlines you fly with. Hotels and airlines frequently have promotions offering bonus points or additional credit towards status, but you have to register for them.
  • Because most hotels have a no fee cancellation policy as long as you cancel the reservation more than a week before the check-in date, it can be a good idea to book a hotel room for large conferences even if you aren’t sure yet you’ll be attending.
  • Before you fly, be sure to download podcasts, tv episodes, movies, or any other entertainment you might be interested in to your phone or mobile device. I’ve been on trans-Atlantic flights where the plane’s entertainment system was unusable for the entire flight!
  • Get a power pack and make sure it’s fully charged before long days of travel. Outlets might not always be available.
  • TripIt can be a great application for storing your travel itineraries, particularly if you have a busy travel schedule.
  • Most of the trouble came because after the second time I put my passport in the wash was the day I left for travel and my passport was a little more “rough” looking. I got a couple of questions during that day of travel, but have since gone through border crossings in several countries without issue.

Powering Through Concur

Concur is a widely used tool by organizations for administrating travel. There are a few other tools, but Concur is one of the biggest and a decent chance you will be interacting with it if you find yourself traveling a lot for work.

Initially I found Concur incredibly frustrating and difficult to use. Over the past year as I have become more familiar with Concur, I have found ways to make it, if not pleasant to use, definitely much more bearable. Below are some tips I have learned over the past year to make working with Concur a bit easier.

Searching for Hotels

Screen Shot 2019-12-23 at 10.37.51 AM

Concur has an option to search for hotels by “reference point” and it is actually pretty effective. Initially when looking for hotels I would painstakingly fill in the address for the conference venue. The reference point option is way faster and easier. It gives “Statue of Liberty” as an example of something to search for, but it can actually match on much less well known spots. For example in October I presented at the JFall conference which is held in the Pathé Ede cinema in Ede, Netherlands. Needless to say, this is hardly a well known location. Concur has no trouble locating it though:

Filter for Your Preferred Hotel Brand Easily

Once you narrowed down the geo-location of where you will be staying, you will need to select your hotel. In my previous article on travel I mentioned the importance of sticking to a single hotel chain. However chains like Marriott, Hilton, IHG, etc. operate under many different brands, and it can be difficult remembering which brands go with which chains, luckily Concur has the ability to sort by Superchain instead:

Screen Shot 2019-12-23 at 10.36.35 AM

Modifying Your Hotel Stay

You travel enough and you will run into situation where your travel plans will change. When your hotel is booked through Concur changing your check-in/check-out dates only takes a few clicks. Find your hotel reservation in Concur, and in the top right corner click “Change”. Modify your check-in/check-out dates as appropriate and you are all set. Using this feature I was able to modify two hotel reservations in all of five minutes when some of my travel plans got moved around.

Screen Shot 2019-12-23 at 10.55.37 AM

Filtering for Your Preferred Air Carrier

Screen Shot 2019-12-23 at 9.33.18 AM.png

Concur doesn’t have a way to filter for airlines like they have for hotel chains. This can make booking air travel a little frustrating until I learned a trick. Once Concur has finished retrieving flight information, you can filter by connecting airports which should be located on the bottom left of the page (it’s collapsed by default). By selecting for the major hubs your primary carrier flies through, the flights to choose from should be filtered much more closely to match your preferences.

Mind the Details When Booking Air Travel

Screen Shot 2019-12-23 at 11.19.55 AM

In the above image there are two flights going from Kansas City (MCI) to Barcelona (BCN) that look all most identical; they are both listed as American Airlines, the total travel time is about the same, and the price is also the same (I removed the actual prices for confidentiality reasons, but trust me they were the same). However if you look at the descriptions for the footnotes, the second option has one additional flight marked as being operated by British Airways (6153), expanding the details gives me this:Screen Shot 2019-12-23 at 11.25.18 AM

On my flight out to Barcelona the trans-Atlantic flight from Dallas (DFW) to London (LHR) is operated by British Airways.

Depending on your opinion of British Airways or American Airlines, this detail could have a fairly significant impact on at least the flying portion of your travel experience. With the first option the trans-Atlantic flight to Barcelona is operated by American Airlines, the second option it is operated by British Airways.

In my situation I would choose the first option because of I have grown accustomed to flying on American, but regardless it is important when selecting a flight to look at these details as it can make a lot of difference.

Conclusion

There’s a lot of trial and error involved when you make that transition from traveling only a few time a year to dozens. I hope these articles can help other people make that transition a bit more smoothly than I have.

I Wasted Days Because I Refused to Ask for Help

This week I have been working on a how-to article providing the step-by-step of building a Spring Boot starter. After reading through the documentation on the subject, I decided to start to put together my code example. A simple example of creating a starter to handle security configuration within an organization. Below is a live shot of me struggling with Spring Boot’s auto-configuration:

Person struggling to climb over fence instead of opening a gate

Like many developers, struggling with technology isn’t exactly an uncommon event as here is another occurrence from only last month:

After pounding my head on this auto-configuration issue, looking at the documentation, looking at other code examples, I eventually realized I needed help, so I “phoned a friend”:  Screen Shot 2019-12-19 at 8.42.07 AM

If you look at the timestamps, within a minute my colleague Ozzy Osbourne, yes that’s his real name, provided me with my answer. Like is so often the case, the problem was a trivial syntax issue, I incorrectly named a file spring.fractories instead of spring.factories.

Scope the Problem and Find an Expert

person saying they are an expertAsking for help is important, but there are better and worse ways of asking for it. In my case when I asked for help, I went to a slack channel devoted to Spring experts. I also knew the problem was with auto configuration. This gave my colleagues the information they needed to know where to look in my code. I scoped the problem, and turned to the people who knew the area well, leading to its rapid resolution.

Because IBM is a huge organization, I am fortunate in having many experts to turn to when I have a question. This is very different from my previous experience; most organizations I have worked at have numbered, in total, in the hundreds or low thousands, with the technical staff only a subset of that. If you work at a smaller organization where the number of “experts” you can turn to is limited I would recommend engaging in your local meetups to expand your network. I have gotten to many developers in my area, Kansas City, this way, which I have turned to for help on more than a few occasions.

Note: If you are a Java developer in the Kansas City area be sure to check out the Kansas City JUG.

Regardless when asking for helping either inside or outside of your organization you should be conscientious of those you are asking for help from. Everyone has their own priorities, so it’s important to scope a problem down as much as reasonably possible and also provide useful background information. This helps you as you don’t have to spend time re-treading tried solutions or chasing down red-herrings.

Pay it Forward

Humans operate on concepts of trust, reciprocity, and mutual respect. As you ask for help, it’s important to be mindful that you are asking someone else to take time out of their day to help you with something. When you scope a problem before asking for help, it shows a sign of respect to who you asked for help that you made a real attempt to resolve the issue yourself first (i.e. you value their time).

As you ask for help, you should also be attentive to others when they need help. I may not be in a position soon to repay my colleague directly by helping him with an issue, but I can still repay some of that goodwill by helping the next person who might ask a question in the Spring experts channel, or some other area I have expertise in.

Conclusion

Most of all what I hope you take from this article is it is ok to ask for help. Like many developers early in my career I was at times overly cautious about asking for help. I was afraid that by asking questions I might be revealing my ignorance and/or that I didn’t know what I was doing (see: imposter syndrome). It is something that every developer needs to works to get over. Even after a dozen years as a professional developer I still have been tripped up by a simple spelling mistake that cost me hours. Next time you find yourself spinning your wheels, scope the problem and find an expert.

Reflections on One Year in as a Developer Advocate

I recently completed a three part series looking back over my first year as a developer advocate. Links and summary of each article in the series is below.

Reflections on One Year in as a Developer Advocate; Content

Creating content is where you will be spending much of your day-to-day as a developer advocate. Content can take many forms, presentations, blog articles, documentation, etc. In this entry in the series we look at the goals, concerns, and difficulties, of developing content.

Read more…

Reflections on One Year in as a Developer Advocate; Travel

For many entering developer advocacy they will see a significant increase in the amount of travel they will do. When you are traveling a couple dozen or more times a year, you will want to re-evaluate your priorities and preparations before and during a trip. I share some of my experience over the past year to make work travel a bit more enjoyable.

Read more…

Reflections on One Year in as a Developer Advocate; Advocating for Developers

What is developer advocacy? As Emily Freeman said, it’s more than just speaking good. In this article I reflect on what it means to advocate for developers, and how my view has evolved over the past year.

Read more…

 

 

Reflections on One Year in as a Developer Advocate; Advocating for Developers

In my opinion, someone in developer relations serves as an advocate for the tech community within their company.

-Emily Freeman

For the final entry in my series looking back over my first year as a developer advocate we will look at what it means to advocate for developers. I would like to thank Emily Freeman for her blog article. Her article, particularly the quote above, led me to re-evaluate my role as a developer advocate. Initially I felt my role was to advocate for my organization (IBM), to developers. From reading Emily’s article, I appreciated that my position really has two roles; advocating for my organization, but also advocating within my organization on behalf of developers. In this article we will look at what each of these roles mean.

Speaking Developerish

Developer advocacy is in some ways a new field. While its roots go back over a decade, the field has seen a surge in popularity in recent years which has transformed how it is viewed. Going from a niche role, to a critical element in how organizations develop their products and services.

Developer advocates are critical because we can connect with developers in terms they relate to and provide information they need. I feel this is at times overly romanticized, suggesting developers are somehow “above” traditional marketing. Closer to reality is that often such marketing is tailored towards a different audience; managers and executives. Developers might care generally about licensing, costs associated with using a product, or if support contracts are available, but often aren’t interested in the details as that goes into decision making that is beyond their role. Developers are interested in how a product will improve their workflows or solve a problem they are facing. For that they need technical information; blog articles, hands-on tutorials, that step through what problem a product is attempting to solve and how to use it.

Developer advocates are able to answer these questions because they have an engineering background. Advocates have experienced those emergency pushes to production, worked with difficult to use or poorly documented products, or spent days reading through logs and code trying to find the root cause of a bug. While every developer’s story is unique, we all have shared experiences and advocates can draw on that experience to create content, deliver presentations, and talk with other developers using terms and language they are comfortable with.

For many hoping to enter the developer advocacy field, our first interaction with a developer advocate was from watching them give a presentation at a conference or meetup group. As Emily, from the title of her article says, developer advocacy is more than the art of speaking good, however presentations are important for two key things; informing developers of new tools or features and as an opportunity for connecting with the development community.

Community Engagement

Much in the way that, broadly defined, problem solving is central to the success of being a developer, a willingness to engage with the developer community is central to the success of a developer advocate. Building and maintaining connections is the means by which advocates can receive feedback on products their organization supports and how they can improve them going into the future. However the developer community isn’t just external, but internal as well.

Returning to Emily’s article, while developer advocacy is often thought to be an external facing role, the internal facing side is critical as well. When we receive feedback, we need to know who to channel that feedback towards. Here my experience might differ somewhat from many developer advocates. IBM, at about 400K employees, is roughly the size of a small city, this along with being a truly global organization, the “I” does after-all stand for International, means I will be in an endless cycle of learning of new teams and names. Still no matter the size of your organization, there are going to be teams and people you will need to know, don’t neglect the building of internal connections as you work to build your external ones.

A Canary in a Coal Mine Coding in Anger

Getting feedback from external developers is great. It is however a somewhat lengthy and infrequent feedback cycle. Agile, TDD, Continuous Delivery, these were concepts created to shorten the feedback cycle for development. Shorter feedback cycles lead to not only faster improvement, but the rapid iterative nature leads often to a higher quality product. As a developer advocate the way we can shorten the feedback cycle is by ourselves actively using the products our organization supports.

Sam makes a great point that you should actively use the documentation your organization produced when using your organization’s products. This is after all how you would want external users to engage with a product your organization supports. While a popular product will have its own share of blogs and other content on the web explaining how to use it, the documentation your organization produces should be seen as the best source for how to use a product. This can only happen though if that documentation is “tested”, i.e. actively used and then improved upon.

However I would also view Sam’s advice through the prism of a specific activity for developer advocates to perform from time to time. As I mentioned in the first article in the series developer advocates are often stretched pretty thin, so you should actively seek help within your organization. This helps not only to reduce your workload, but reinforce the internal connections you will need to build, and also as a form of feedback in and of itself. While working on some recent workshops while looking for help on how to use the products I would be using in the workshop, I was also able to give feedback on how they might be improved going forward.

Conclusion

It has been quite an experience looking back on my first year as a developer advocate. Outside of when I first started my career as a professional developer, where it took a couple of years before felt like I hit my stride, switching roles to developer advocate has also been a steep learning curve. When I went from developer role to developer role, it felt like I could hit my stride within a couple months of joining a new organization, as a developer advocate I feel like I am only just now hitting my stride a year in. While there is still a lot for me to learn and I look forward to doing some more articles looking back on two years of developer advocacy, I feel like I now have a much better idea on the road forward.

If you are thinking of entering, or just entered the role of developer advocacy I hope these articles have provided some insight on the work, life, and responsibilities of what it is to be a developer advocate. If you want to hear more, my DMs are always open on twitter @BillyKorando.