Three Tech Wishes for 2017

Happy 2017! As we put 2016 in the rearview mirror, we’re all taking a look at the outlook for 2017 as I did here but I wanted to take a more personal angle here and explore what I desperately want to see from the tech community. This list is by no means exhaustive and for the sake of time (and online attention spans) I’m limiting it to my top three.

Google Account Management: Dealing with multiple Google accounts is an unfortunate and annoying fact of life for me both as a regular user and as a developer. In this year alone I’ve probably written thousands of lines of code for myself and for clients to deal with this problem by basically scraping calendar events between two or Google accounts. The business case for this problem is pretty simple. Company A gets a contract to do some work but they don’t have the resources in house, so they subcontract part (or all) of the job to Company B, but Company A doesn’t want the client to figure out that Company B exists and is actually doing the work, so they give all the Company B people Company A Google accounts. My event scraping solution is sloppy and fraught with all sorts of little issues. Google should find a way to implement some sort “vanity account” system that let’s the actual email addresses be masked between multiple domains, so that the customer sees what Company A wants them to, but Company B doesn’t have the overhead of dealing with yet another GMAIL account.

Reactive Programming Hype: A lot has been made of Reactive Programming in 2016. While there is definitely some fire to the smoke, things are getting way too hyped and frankly I’m seeing Jr developers pitching reactive programming on freelance gigs as some sort of silver bullet that will solve all the problems you have have and even ones you don’t know you have yet. This is scary! Sure there has always been hype around “new” (sneer quotes because Reactive Programming is only new from a ‘certain point of view’) technologies and methodologies but this hype train around all things with the word or root ‘react’ in them has the kinetic energy of ten hydrogen bombs. I’ve gotten too many projects in this year from prospective clients that were over-engineered in one of these reactive libraries by some Jr dev who just got a little too excited on the Kool-Aide sales pitch and the story is sadly all the same – the client was happy with what he was told but what he got was a steaming pile of hard to reason about spaghetti code and ultimately a rewrite. For 2017 let’s just pull the cord a little on the hype train, OK?

Docker Direction: Despite some fairly significant pain in upgrading between Docker versions and other more minor issues, I am still a serious believer in Docker as the premier containerization solution. Coder Radio listeners will remember that even as a callow youth I was on the Docker train right from the beginning but my faith has been somewhat shaken and I’d like some clearer communications regarding where the technology is going, who they feel their ideal target users are, and where Docker the company sees its role beginning and ending — in other words where will they and where won’t they compete with vendors who are selling / implementing Docker.

Those are my three (I hope fairly doable) wishes for 2017, but before I go…. I also want to note what I didn’t mention here that I have in my end of year / new year posts for the last years – App Store monetization and more specifically a sign from Apple on where they see that going. We got our answer in 2016 – subscriptions. While that will work for a number of apps and is working fine for my Backpoints (iOS & Android), it does not satisfy all the needs of independent developers and likely will not create the high-value ecosystem of professional paid (paid defined as taking money in any non-donation way) software that the iOS App Store originally enjoyed. When I think about Apple and their answer to the monetization issues on the App Store, I am remained of that great quote from Dan Brown’s Angels and Demons: “God answers all prayers, but sometimes his answer is ‘no’.”

Google Home Review

I’ve been spending some time with a Google Home at my office. It’s. been a pretty interesting experience overall and makes me more confident in my previous assertion that of the big three in tech (Apple, Google, and Microsoft), Google is going to dominate the digital assistant / bot space. While my experience with Home was not perfect, it was a pretty impressive showing for a first generation device.

The Good: Google Home is smart as a whip! There’s just no way around that. My office mate and I spent hours trying to trip it up on trivia, calculations, and finding obscure movie and song facts and the device held up just fine. By far the most useful functionality for our office has been dictating songs to it and passing back and forth; prior to the Home, we would take turns playing (put your hate in the comments) vinyl records. Sure, we could do this with a PC or even an iPad but just being able to pick songs verbally has been an surprisingly enjoyable experience. I know this sounds a bit silly, but it reminds me of when I got my first iPad – I had mocked the iPad as just a large iPod Touch, but I changed my tune after my first few minutes using Apple’s tablet. This is just how I feel about Home, though I went in with a little more of an open mind than I did with the iPad.

The microphone seems fine but I do occasionally have to re-state requests to the device and it’s not clear if I just mumbled or my NJ accent was too hard for Home to parse on certain phrases. The speakers are pretty good and don’t have that tinny quality to the sounds that I was worried about before I got the device. For most users Home will likely be the highest quality speaker they have in their house, but I can see audiophiles wanting something a bit more.

The Bad: I’ve experienced occasional service outages with Home that required it to the restarted. The error message given suggests that my wifi may have been to blame, but every other device on the network was fine. It’s impossible to dig deeper into this, but it stands to reason that the issue is a service hiccup on Google’s end. Silly as it sounds, it kills the magic of a voice interface if you have to get up (in my experience) every other day to unplug and restart the device.

The Ugly: Google account management is a mess on just about every Google product and Home is not exception. Home only allows you to have one account on the device — this is a terrible design decision as it makes the assumption that one account equals one person. The reality for my use case and many others is that on e person will have multiple accounts. My guess is the most common case would be users (like me) have one Google account personally that has their Play Music, YouTube Red, and other Google entertainment services on it and also have a Google Work account used primarily for email and (most importantly for the purposes of Home) calendar. In my case, I put my personal Gmail on Home to get the entertainment functionality but am totally cut off from my work calendar. Ideally, I’d like a system where Google understands that users have different Google accounts for different contexts and allows the user to take calendar services from a Google Work account while using their personal account for entertainment and everything else.

All in all, I like the Home. It is definitely a first generation product, but most of the issues with it are fixable via software. Currently, I don’t see any real competition for Home other than Amazon’s Alexa but Amazon is in a very different business than the big three, so I would question their commitment to building a truly expandable AI assistant – Google’s opening of Actions to third party developers is a strong step in the right direction. Apple seems unwilling or unable to make Siri more than a lame parlor trick and even if they did, they’d likely be very paternalistic in terms of user privacy, severely limiting third party developer access. Microsoft is doing some really cool stuff, but they don’t have the platform beachhead that Google has in Android and all of the Google related services and that Apple has with iOS. The most surprising aspect of using Home is how it has me strongly considering picking up the next flag ship Android device to get that Google AI functionality on the road. Do you have a Home or comments / questions on this post, sounds off in the comments or Twitter.

Pallet Town: First Steps to Functional

I’ve been taking a deeper look at Functional Reactive Programming in the form of RxJavaand ReactJS. While I am still at the early stages of really looking at this and forcing myself to actually work in these technologies that I’m still no really sure make a lot of sense for my use cases (more on that at a later date), I was taken aback by the simple usefulness of the “Functional” part of the equation. At the risk of grossly oversimplifying the benefits of functional programming (or at least adopting a more functional style in your object oriented code), there is a ton to be gained with just a little bit of re-thinking of how you think about the relationships between your objects and how you structure your methods. This is because one of the main benefits of functional programming is that it minimizes state and therefore unintended side-effects. Here are the two quickest and easiest ways to improve your code today using a more functional mindset.

One Function == One Action:” Every function you write should do one thing and only one thing. Let’s take a very simple sample of what this should look like:

public Pokemon getPokemon(int id) {
	Pokemon  myPokemon = PokemonStore.getById(id);
	myPokemon.setType("fire");
	PokemonStore.save(myPokemon);
	return myPokemon
}

The Assumptions in that are that we have some PokemonStore class that is effectively an ORM for your Pokemon. That’s fine. The issue here is that our ‘getPokemon’ function doesn’t just fetch us the correct record by id as you would expect it to. Instead it updates it ‘type’ property and reserves the mutated record to the datastore before returning the record. This is obviously terrible on a number of levels but looking at it from a functional point of view, the primary sin is that it does three things (getting a record, mutating a record, and saving a record) rather than just one and what it does doesn’t match the method signature. A better version of this method would have mutating the type in another method and simply return the record:

public Pokemon getPokemon(int id) {
	Pokemon myPokemon = PokemonStore.getById(id);
	return myPokemon;
}

As you can see that’s easy to read, does one thing, and there’s little to know risk that a future developer won’t understand what the method is supposed to do.

Deterministic Outputs: A method given the same inputs should always return the same outputs. If that’s not true, then you likely have too much coupled state in your code that is causing unforeseen issues. This is a great example of what not to do:

public Pokemon getFirstPokemonInRoster() {
	List<Pokemon> roster = User.CurrentUser().getRoster();
	Pokemon starter = roster.get(0);
	return starter;
}

There’s a lot not to like in this method. For starters it relies on the start of a Users.CurrentUser() singleton, which instantly creates couple state. Another issue is that it’s not very flexible — is it really true that we will only ever care about the current user’s roster? Finally it’s not written in a way to be optimized for easy BDD / testing and violates the functional principle (or perhaps guideline) of passing in the objects / values a method needs to run into the method directly rather than pulling them from another place. Here’s a minor change that addresses all of those issues:

public Pokemon getFirstPokemonInRoster(int userId) {
	User user = UserStore.getById(userId);
	List<Pokemon> roster = user.getRoster();
	Pokemon starter = roster.get(0);
	return starter;
}

As you can see, the revised method can now the pull the roster for any arbitrary user and does not rely on a user singleton. You can easily imagine a test being written that passes in a valid user id to test the golden path for this and also another test with an invalid value for the userId paramater; incidentally, my method still doesn’t handle that case, but there are multiple ways you might do that and catching that sort of thing is really what automated testing is for ;).

I hope you’ve found this helpful! If you have any questions or comments, please sound off below or on Twitter.

Business Innovations: Fast Pass

As I sit in the flight back from my family vacation to Walt Disney World in Orlando Florida, I find myself in awe of what I can only describe as the most ingenious business innovation since the independent subcontractor – the Fast Pass. If you haven't been to WDW in a while, Fast Passes are basically attraction reservations and they work just like restaurant reservations. This may seem like a pretty simple concept and not that innovative, but let's take a look at two real-world case studies from my last week in Orlando and note how the Fast Passes proved invaluable to WDW.

WDW is currently in a state of being "re-imaged", the jargon the "imagineers" over at Disney use when they are modifying the WDW attractions. One of the parks that is slated to undergoe and is currently undergoing a good deal of re-imagining is EPCOT, in particular the "World Showcase". One of the most notable changes the "World Showcase" has undergone is the addition of a ride themed after the popular children's film Frozen. As one of the newest attractions and being themed after a smash hit with kids of all ages, the ride has some monster wait lines where you can see dozens of eager little girls dressed up as one of the film's leads, Anna or Elsa. Even my coal black heart wouldn't dare deny these princesses their shot to "experience Frozen" if but for a few minutes. Still, mom and dad don't want to stand in line for an hour and there are meal reservations to be kept as well as other (perhaps more adult appealing) attractions to see. What does a savvy Disney-goer do? You open the My Disney Experience app possibly weeks before you even get to Orlando and book a Fast Pass for a date and time that is convenient with the rest of your schedule for each Frozen fan in your party. That's it. You've just taken a wait that could have been well over an hour and gotten it down to something like ten minutes. This is great for the park-goer and also great for Disney, as it mitigates one of the primary pain points of going to WDW, the lines.

Mistakes happen even in the Magic Kingdom. Systems can fail or employees can just plain screw up. There's a lot of complicated RFID tech being used at any given time at WDW and I saw on more than one occasion in the last week where the Magic Bands simply wouldn't work for some reason. This happened to my family as we entered the Magic Kingdom theme park — for some unknown reason my band worked fine but my wife's failed; ironically, she is an annual pass holder and I am not. We knew her pass was still good but were admittedly a little frustrated after having been asked to step aside at the entry point while the staff could verify that Lara's pass was indeed valid. After a few minutes of waiting, the staffer got back to us with a sincere sounding apology and a couple of Fast Passes to any attraction we like as an apology for the system's glitch. Our frowns were turned upside-down. The beauty of using the Fast Passes like this is that they don't cost Disney anything at all and in this case they still got to do the somewhat awkward pass verification that they wanted, but instead of having an offended guest Lara remains ever the happy Disney princess. They key to this is that there is a difference in the monetary value (read cost) of the Fast Pass to Disney (i.e. $0) and the practical value to the guest.

Many of us struggle in our small businesses in trying to find a way to give something of value to the customer in cases of an error or just as a way to build a better relationship. Unfortunately, very few of us have managed to get up to the level of sophistication as Disney has in terms of having such a wide delta between the monetary cost to our firms and the perceived value by the customer. All too often, we find ourselves doing work effectively for free due to scope issues or eating opportunity costs by going into unpaid "account service" meetings. I wish I had some solution that I could stand on a soapbox and extol, but I don't. Still, I think maybe it's time to take a cue from the house of mouse and re-imagine how we run our agencies.

Lemur Review

Coder Radio listeners will know that I have been agonizing over replacing my three-old MacBook Pro and with the recent Apple announcement of their new MacBook, I ended up ordering a System 76 Lemur laptop with Ubuntu 16.10 Linux pre-installed. If you’re interested in the specific specs of the system, you can see them here. My thoughts in the future of computing (or the next “big thing” if you prefer) being AI powered by Linux on the cloud. My crazy predictions about the future of AI and the stages it will go in are a post for another day – for today, let’s go over the Lemur itself as it compares to the MacBook Pro it’s replacing.

The general hardware is good but a little more plastic feeling than I am familiar with. I like the inclusion of a USB-C port but do wonder who is still using VGA and if that space on the body would not have been better used for another USB port. I was pleased that my high-res Dell monitor and peripherals all worked out of the box with the Lemur – that’s a big win for System 76, as device compatibility concerns (real or imagined) tends to be a main thing that keeps would-be-switchers from going Linux. The general “just works” quality of the Lemur with Ubuntu 16.10 is by far the most impressive aspect of my experience with it.

On average, I am getting about 4-5 hours of battery life with the screen just about all the way turned up and playing / streaming music or podcasts basically constantly. That’s less than ideal, but I am confident, I could bleed an hour so more out of it if I did less streaming and dimmed the screen some.

The matte screen on the device is surprisingly good and has helped to bring me around on matte screens in general. I might have liked a more “retina” screen but the 1080 resolution is more than fine for my needs.

The keyboard is a bit of step down from the MacBook Pro keyboard that I am used to. There is far less key travel and at times it feels a bit too insubstantial to type on, however, it’s about on par with most non-Apple keyboards on windows laptops with the possible exception of the current Dell XPS 13 and is by no means the worst laptop keyboard that I’ve used.

The track-pad is just bad. Even compared to other non-Apple laptops, the track-pad doesn’t cut the mustard. It at times feels “jumpy” and at other times feels slow and unresponsive. It’s also awkward feeling on my fingers but that’s probably a bit too subjective to worry about for most. I’ve taken to keeping a USB mouse in my bag with the Lemur.

The sound from the on-board speakers is adequate but leaves a bit to be desired when compared to the MacBook Pro speakers. Neither is very good, so there’s not a lot to worry about here – in general, if you care about audio like I do you’re probably always disappointed with laptop speakers. The most glaring issue here is that at high volumes the sound becomes tinny.

All in all, I think the Lemur is a good choice for someone looking for a Linux laptop that could be great if just a little more care was taken with the track-pad and keyboard, as the other minor points I’ve made here are probably specific to my tastes / expectations.

Comments? Questions? Forest burning FOSS rage? Hit me up on Twitter.

Upcomming Sonnet Collection & Preview

I’ve been working on a side project of writing one sonnet a day for my wife for just over two weeks now and will be collecting them and publishing them in a collection once the book is full, assuming there are no shenanigans with the publisher; the book in question is a leather bound hand-made notebook she gave me a number years ago and will fit just under one hundred sonnets, so we’re probably looking at the new year to go into pre-production on the book itself. In the meantime, I’ve been encouraged to periodically share selections here as a sort of preview, so here’s the first. Astute readers may notice that not all of them are “perfect” sonnets. One of my goals in this project is to bring a classic form back for modern readers, but when form and function don’t mesh perfectly, I’ve chosen to sacrifice form and other times I’ve simply chosen to keep the spirit of the form but adapt it in significant ways.

I hope you enjoy this and I’d appreciate any feedback in the comments or on Twitter.

Sonnet for Lara #17

There is a place where trees stay evergreen

and leaves never descend fully aground.

It’s a country that we’ve not ever seen,

but together we can take a ship there bound.

 

There is a place where grass is never frost bitten

and Winter’s chill passes temperately.

Let’s fly together there before fate’s written,

and let our love’s Spring last eternally.

 

There is a place that Time has forgiven

and they there know neither age nor decay.

Let’s stay there and let us not be driven,

for we can forever be as today.

 

If you would make the trip with me afar,

then I too could shine brightly as you, Star.

Bye MacBook, Hello Lemur!

Apple is widely believed to be releasing new Macs next week and I am celebrating this long overdue update to the MacBook Pro by replacing my existing MacBook Pro with a Linux laptop from System 76. This isn’t one of those “Apple sucks posts” but I did want to go over briefly why I find myself moving away from Apple platforms and in to the open-source arms of Ubuntu Linux for my production needs but am still firmly entrenched in the i-ecosystem for my content consumption and light office productivity needs. Generally speaking, I am making a bet that the puck is going toward Linux powered AI.

Let’s start with content consumption. I ‘own’ over one hundred and eighty movies in iTunes, over fifty albums on iTunes, and a family subscription to Apple Music. I also have a number of newspaper and magazine subscriptions that just frankly have far better user experiences on iOS than Android. Basically, I’m pretty highly invested in the Apple content ecosystem, so moving away from Apple totally would be costly and more than a little wasteful. Also, I am pretty happy with the Apple TV / iOS devices / iTunes setup.

There’s also the issue of time’s insistent march on. iOS and mobile platforms in general are extremely mature. That’s great for users but less than exciting to me as a developer. Don’t get me wrong I still love iOS and Android development, but it’s just not that exciting or bleeding edge anymore. The sad fact being that both those platforms are very mature and most apps are just re-implementations of commonly accepted design patterns; that goes doubly for those that are clients to relatively simple REST APIs.

Going forward for the next five to ten years, I think there’s going to be some serious action in the field of AI or ‘bots’ if you prefer. In my opinion most of the most significant innovations are going to be on cloud-based Linux servers that power these pieces of software. Of course mobile platforms will likely be the most common front-ends for this type of software, but my guess is that will be in a more limited thin-client capacity. That’s the bet my Twitter followers may have figured out that I have been working on some side AI bots for months now and that’s where I think this is all ultimately going.

Let me know what you think especially if you think that I’m crazy! If you’re curious, the laptop I went with for my MacBook replacement is the Lemur by System 76. The Lemur joins my home office’s Ratel as the second machine in my growing Linux / System 76 fleet.

I Can’t Hire For Sales!

Sales solves everything is an old expression I’ve heard since I was a kid and I have to say that I fundamentally agree with it. You really can bail yourself out of myriad business problems by simply selling more and therefore increasing top-line revenue. Like many founders who do their own sales, I’ve tried to hire Sales Reps several times and have had varying degrees of failure in making those reps productive to anywhere near a level that I myself can close. In other words, Sales Rep is the position that I simply can’t hire for effectively.

Sales is ultimately about cold hard cash and as a startup (especially a bootstrapped one) funding the normal near six figure base of an enterprise Sales Rep in addition to a standard 5-10% commission on closings, can be a tough pill to swallow. Like many founders in this position, I’ve opted to cut that base down to something more sustainable and target commission rates at the top end or even beyond that 10% range; at one point, I even tried to go with very high commission rates and no bases but that turned out to be a total disaster in that it forced my rep to basically close any deal — do not employ 100% commission reps. Unfortunately, Sales Reps are like everyone else with financial responsibilities and tend to be pretty attracted to larger base salaries (at least that’s been my experience in the software space) and that creates a situation where smaller shops are often not the first choice of the most capable or accomplished reps.

Cash aside, the other issue tends to be domain / market knowledge and training budgets and processes. Basically, given the pool of reps that are available to small firms, there’s a higher than even chance that their reps will tend to be on the more junior side of the experience and therefore have less product knowledge than their more senior counterparts. The founder of the small firm is then forced into a position of either investing heavily in training up an asset that may not pay off or worse may go to the competition once they’ve gained enough product / market knowledge to command a higher base or simply treat their reps as replaceable cogs, hiring many low-paid reps, offering little to no training, and dismissing all but the highest performing reps. If you’ve ever worked in insurance or know someone who has the latter will sounds very familiar to you and likely leaves a bad taste in your month. Compounding the issue of investing in more junior reps is the fact that the founder himself if likely to have far better numbers in terms of raw closings and terms, making him increasingly (and from a purely numbers perspective correctly) reluctant to invest in training.

Sales solves everything. That’s why I’m doing my own sales from now on. Are you a founder? What has your experience been in hiring Sales Reps? Did it work out? Are you still doing your own sales?

Slack-pocalypse Now

Slack is reducing my productivity and is almost certainly having a material negative effect on my day to day performance as well as my job enjoyment. Things started so well with Slack and I and I still love the vision of reducing email but something’s change, something’s been twisted….

In the beginning the initial goal of Slack was to make team communications easier and cut down on useless (or at the lest nonproductive) emails. I am happy to say that for the most part that’s happened for us internally at Buccaneer; in fact, we have almost zero internal email threads in a given week that aren’t forwarding something from a customer-facing person to someone else and even then most of that is handled in Slack as well. That’s great!

Then Slack added guest accounts, single channel accounts, and the ability to have multiple accounts on one Slack client and what was a great internal communication tool became the customer service portal from Hell. I can see how the folks over at Slack thought they might reduce the strain of customer communications just as they had internal communications. Possibly they thought Slack chats might replace daily stand ups, weekly status meetings, or “checkin emails”. Sadly, they were mistaken. Due to the expectation of virtually immediate response on Slack, it actually makes these problems worse.

In terms of daily standup (which I will go to my grave claiming is pointless in a group greater than six) Slack is treated as “in addition to” rather than a “replacement for”. Same problem for weekly status meetings.

Though it’s the daily (or worse “build”) checkin email that Slack has truly perverted , twisting it into a nightmare that leaves me muttering “the horror the horror” at the end of every sprint. The beauty of the checkup email and email in general is that it’s socially acceptable to not reply immediately. Indeed, one of the best ways to respond to those sort of things for me was to wait until I had something positive to say or respond by EOB whichever came first. Just a few hours can make what might be a bad or awkward conversation into a good one and email allowed me to manage my time in a way that I could find those hours with no more (and sometimes not even) a “I’ll follow up with you by EOB”. Thanks to Slack, the conversation goes a little more like:

Get enough of these and you’ll be dreaming of the halcyon days of once weekly conference calls and formal EOB update emails.

Don’t get me wrong. I am not against open lines of communication but sometimes things take time and you want to craft a more sophisticated response than you can get when being barraged by messages. Of course from the sender’s perspective Slack is a form of instant messaging with an emphasis on the instant as in NOW part. Unfortunately, responding to even the most cursory of messages requires a context switch and any experienced developer will tell you that’s a productively killer.

What Slack needs is a more aggressive version of their current Do Not Disturb feature. One that not only warns the sender that you are not available but that actively says you are busy. This is something that HipChat, an Atlasssian competitor to Slack, has had since before Slack was even around. On HipChat if you mark yourself as busy, it puts up a red logo that looks like a traffic sign and actively warns any senders that they are probably interrupting you by messaging you. The difference may seem subtle if you aren’t like me and used HipChat for a long time before Slack, but in terms of communicating your status to your team and any customers in the system, HipChat is clear — away really means away, available really means available, and busy means leave me alone I am working.

What do you think? Is it just me? Find me on Twitter and let me know. Also, do fill out the contact form on this page, I am a 50% promotion for getting new hybrid app development projects started. If you’ve been thinking of getting an app for your business or even just have an idea you want to validate, there’s never been a better time to reach out!

Programming Pitfalls: Cors & Spring Boot

It’s no secret that I have been dipping my toes back into the world of enterprise Java development over the last moth or so. Thankfully, I haven’t been forced to go full Java EE. In fact for enterprise development I’m getting off pretty easy in the form of Spring Boot.

Spring Boot is an offshoot of the popular Spring framework and brings many conveniences from modern non-Java web development frameworks to Spring developers. It’s related to the Spring MVC framework but is more geared toward use in a mircoservices architecture. I’ll be working in it for a few more weeks and will get some more thoughts together at a later date but for now let’s go over the pain that is CORs. For those that don’t know, CORs is a browser feature that protects against cross-site scripting in JavaScript and the web would be a much more dangerous place without it. As always, security comes at a price and in this case that price is that web services that interact with an API on another domain or IP need to allow cross site access in their response headers or just about every modern browser won’t let the response through.

Ideally, you’d want to change your ‘Access-Allow-Origin header’ to the domains that your client applications will be hitting your API from but if you’re API is public or you don’t yet know what the final domain of your client app.

In Spring Boot this can be done with a simple Filter like so:

@Component 
public class SimpleCORSFilter implements ContainerResponseFilter {
    @Override 
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        MultivaluedMap&lt;String, Object&gt; headers = responseContext.getHeaders();
        headers.add("Access-Control-Allow-Origin", "*");
        headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        headers.add("Access-Control-Allow-Headers", "*");
    }
}

Notice the @Component above your subclass of ContainerResponseFilter, that’s what tells the the framework about this calls. What this calss does is add the values to the “Access-Control-Allow-Origin, “Access-Control-Allow-Methods”, and the “Access-Control-Allow-Headers”. In the example above, we are going with the most open settings possible. You likely will want more secure / conservative settings unless your service is intentded to public. This is an important point and it took me hours to figure it out –It is important that this file be in the same package as your “Application” class (the class that has the SpringApplication.run) in it.

I hope this helps somebody! If you found this post interesting reach out to me on Twitter.