Coders Campus Podcast

Coders Campus Podcast

Download on the App Store

Coders Campus Podcast episodes

  • The Ultimate Guide to Hosting a Java Web App with Amazon Web Services (AWS)

    Let's start things off by explaining what Amazon Web Services (AWS) actually is and why it's useful to you as a Java programmer.

    Amazon Web Services are a bunch of “products” that Amazon is offering to make our lives as programmers easier.

    These products come in the form of web applications that help us to do the “un-fun” stuff of programming.

    Mostly it involves what we call the “dev ops” (development operations), which are the processes that we use to make sure that our code can be properly enjoyed by all of our users.

    To put it simply, AWS helps us to put our applications on the public web for anyone to access and enjoy.

    Typically when we're coding, we're firing up a web server privately on our own laptops / desktops. We have a Tomcat server installed somewhere that runs our code on localhost:8080 and we code like happy little monkeys.

    But what happens when we finish our application and we're ready to show it to the world? Sure we can upload it to GitHub, but that's only to be enjoyed by other programmers… we want our family and friends (and complete strangers) to use our apps and tell us how amazing we all are, right?

    Right.

    You get the idea.

    Overview

    Here's a quick overview of this ultimate guide so that you have a 10,000 foot view of what we're going to be talking about:

    Step 1: Sign up for AWS

    Step 2: Create a Tomcat Server with Elastic Beanstalk (an AWS “product”)
    Step 3: Prep your code for deployment to Elastic Beanstalk
    Step 4: Deploy your code to Elastic Beanstalk
    Step 5: Create a Database in AWS using Amazon RDS
    Step 6: Configure the Amazon RDS Instance
    Step 7: Connect your code to the RDS Instance
    Step 8: Point a Domain Name to your Fancy new Hosted Application
    Step 9 (Optional): Create an SSL Certificate and Tweak your Settings

    Once you've gone through all of these steps, you'll have a fully functional cloud-based Java web application hosted with Amazon Web Services.

    You smart little monkey you!

    Cost / Pricing

    One thing that people worry about is: how much is this going to cost me?

    It's funny that as programmers we're so worried about paying for products and services related to programming. I'm not sure where that kind of thinking came from, but I really think it's a bit poisonous. We're always reaching for the free alternatives, but they're often either much more complicated to use, or they're just not a useful in general.

    But having said that, AWS has set things up so that you can use all their services for free for 12 months… well… mostly… To be more specific, you can use one instance of each of their services for free for 12 months. That means you can create one Tomcat server, one database, one “hosted zone” etc. for free for 12 months.

    You see, Amazon bases pricing off of hourly usage. So they'll give you around 744 hours of free usage per month for all of their products / services. This means that if you launch two Tomcat servers, you'll be using about 1,488 hours per month, which means you'll be paying for 744 hours of Tomcat usage.

    They also have a graduated cost structure, which means that you can choose to pay less for less powerful “servers” or pay more for gradually more and more powerful “servers”. As of the time of posting this article, a “micro” instance (which is a Server with 1 Gig of RAM) goes for about $0.012/hr (or about $8.64/month). A micro instance is great for a development environment and even a small production environment if you don't have any active users.

    For a full list of their prices, you can check out this page.

    Step 1: Sign Up for AWS

    In order to get started, you'll need to sign up for an AWS account.

    This can be done via aws.amazon.com

    Find the button on the screen that says something like “Create an AWS account” or “Sign into the Console”. Usually it's in the top right.

    This should take you to the account creation / sign in screen that looks something like this:

    If you already have a regular Amazon account (like the one you use to shop on Amazon), then you can use this account to just sign in and get the process started.

    Otherwise, click on the “I am a new user” radio button and type in an email address to create a new Amazon account.

    If you're creating a brand new account, then you'll need to fill out some account information (name / email address / password) on the next screen. It should look something like this:

    Next up is the screen you'll see if you just logged in with your existing Amazon credentials (or if you just filled out the previous screen with your new account information).

    Here you'll need to tell AWS more about yourself or your business.

    If you're creating this account for your business, then choose the “Company Account” radio button. If you're just signing up to use this for your own personal reasons (like creating apps for fun or just for learning purposes), then choose “Personal Account”.

    Once you've filled out all your personal / business information, you'll need to give them your payment information.

    Keep in mind that so long as you follow my instructions in this post, you shouldn't be charged anything for using AWS for the first 12 months… keep in mind, this is not something I can guarantee and I don't take responsibility for any charges you may incur through your usage of AWS. I can only be a guide to ensure you won't be charged for the first 12 months by taking advantage of the AWS free tiers. Also keep in mind that the 12 free months offer was available as of the time of the posting of this article (in late 2016 / early 2017).

    Okay, having said that, here's the screen you'll be presented with when needing to fill out your payment information:

    Next up, you'll need to confirm your identity by receiving a phone call and either saying or typing in a PIN that you're assigned. Go ahead and fill out your phone number and press the “Call me Now” button.

    Once you hit “Call me Now”, you'll be presented with a pin on a screen that looks like this:

    When your phone rings, pick it up and type in that PIN (or say it out loud) to verify your account.

    When you've successfully entered your pin, you'll see this screen:

    Go ahead and click on the button that says “Continue to select your Support Plan”.

    Amazon Web Services offers a bunch of support plans that gives you the opportunity to have access to an Amazon employee who can help you to set everything up. Generally speaking, unless you're a large corporation, you probably won't need to choose anything other than their basic support plan (which is completely free) and gives you access to their online documentation.

    Here's what that screen looks like (not pictured is the yellow “continue” button at the bottom of the screen):

    And voila, you are now done creating your account!

    You can now go ahead and login to the console by clicking on the “Sign in to the console” button. This will bring you back to the login screen that we started on initially. You can type in your account information that you created previously to login to your AWS dashboard.

    Once you've signed in, you should see a Console / Dashboard that looks something like this:

    Again, keep in mind that Amazon will likely make changes to their views over time, so your dashboard might not look exactly like the one pictured above.

    Alright! Congrats on getting signed up and logging into your dashboard for the first time.

    The next step is to create a Tomcat server using Amazon Web Services “Elastic Beanstalk” product.

    Create a Tomcat Server with Elastic Beanstalk

    Alright, so next on your “todo” list should be to create a Tomcat server on an Elastic Beanstalk instance.

    What's essentially going to happen here is that we're going to create a virtual server in the cloud (an instance) that will be running a Tomcat server.

    Typically what happens is that you'll create a Linux server with about 1GB of RAM. This is known as a t2.micro instance, and it's part of Amazon's free tier offering.

    To create this server, here's what you do.

    First login to your AWS dashboard and navigate to Elastic Beanstalk by clicking on the “services” menu in the top right, then click on “Elastic Beanstalk” (in the “Compute” section).

    Once in Elastic Beanstalk, you'll be presented with a “getting started” screen. All you need to do to get going is to click on the “Get Started” button (or on the “Create New Application” link in the top right).

    On the next screen, you'll need to enter a few simple details to get your environment up and running:

    1. Specify the name of your application (this is typically the name of the product/project that you're building)
    2. Choose your platform (In our case, since we want to launch a Java web app, we'll use a Tomcat platform)
    3. Finally, you can choose to launch a sample application or your own WAR file (We'll start with a sample application for now, we can easily change this later)
    4. Once you click the “Create Application” button, AWS will be hard at work creating your environment for you.

      This part usually takes about 10 minutes to complete, so you might want to get up and grab a bit to eat while it's working.

      Once AWS finishes its work, you'll be presented with a screen that you'll become very familiar with:

      This is the main Elastic Beanstalk screen for your application.

      There are four main things to take note of…

      1. The region that your instance exists. In our example I chose the North Virgina region (aka us-east-1). If you change regions, then you won't be able to find your elastic beanstalk instance that you just created.
      2. Your app's tab. If you have many applications running in the same region, you'll be able to switch between them via this tab
      3. Your app's URL. When you visit this URL, you'll see your application in all its glory (screen-shot of our sample application running pictured below)
      4. Your app's version. Right now we're just running a sample app, but once you launch a real application, you'll need to specify unique version numbers for each build.
      5. Okay, now that you've launched your app and you've taken note of the important information on this screen, go ahead and click on your app's URL to see it in action:

        Kinda cool right?

        You just launched a Linux server with Tomcat installed on it, and it's now running a sample application which you can visit via your app's unique public URL!

        Before we jump into what needs to be done to launch your own code onto this server, let's take a look at some other important configuration options for your new cloud environment.

        Go ahead and click on the “Configuration” tab on the left side of your Elastic Beanstalk screen:

        The first thing I want to show you is how to change the instance you're running.

        As you can see from this screenshot, you're running a t1.micro instance… I think this instance is slightly less powerful than the t2.micro, but both instances are free.

        So let's have a look at how to change over to the t2.micro instance.

        Click on the gear icon in the top right of the “Instances” box:

        This will open up your instance configuration options screen where you'll be able to change from a t1.micro to a t2.micro instance.

        Just click on the drop down next to the “Instance Type” label and change your selection to the t2.micro instance and click on the “Apply” button in the bottom right:

        Don't worry too much about messing this step up, because you will be shown a screen that will ask you to confirm that you'd like to switch instances:

        Note: If you're switching to a non-free tier, it will say so on this screen. If there's no warning telling you that you're switching away from the free tier, then you're good to go.

        Note: Keep in mind, if you were running an actual live application, this would bring you app down for around 10 minutes while it launches a new instance.

        Here's the screen you'll also become accustomed to seeing; the “environment updating” screen:

        Once your new t2.micro instance is ready to go, you'll see that your screen will change from the “INFO” status to the “OK” health status.

        Congrats! You've now just upgraded your instance to a slightly more powerful one with a bit more RAM.

        Step 3: Prep Your Code for Deployment to Elastic Beanstalk

        Boo yah! You've got a running instance in elastic beanstalk… but it's not really exciting, because it doesn't actually contain your application's code yet.

        So let's resolve this issue!

        There are two possibilities that could unfold here:

        1. Either you have created your application using Spring Boot
        2. Or you haven't created your application using Spring Boot
        3. If you fall into camp #1 (i.e. you created your app as a Spring Boot application), you've already done everything you need to do in order to make your code deployable to Elastic beanstalk. Congrats! Now you can move onto Step #4.

          If you fall into camp #2 and you didn't create your application using Spring Boot, there may only be one thing you need to do in order to make things work properly.

          First thing is to just create a deployable WAR file from your project… this is usually done my invoking a Maven Install on your code-base. Make sure that you've got your maven pom.xml file set to deploy as a WAR and not a JAR (this is found in the section of the pom file)

          You can then take that WAR file and upload it to Elastic Beanstalk and see if it works… For my case, I wasn't so lucky. When I deployed my WAR file, the application didn't boot up properly. I didn't see any obvious errors or warnings, I just had a blank website when I visited the endpoint URL. So I had to try something different to get it working.

          Now, I can't speak to ALL the different scenarios that could arise here, but I can fill you in on the problem I had when I tried to deploy an old app into the cloud.

          What I did to fix my “blank website” issue was just convert my existing project over to a Spring Boot application.

          There's some documentation on how to do this on Spring's website via docs.spring.io

          The basic idea there is that you replace your existing class that contains your main method with the Spring Boot version.

          Spring Boot's version looks like this:

          @SpringBootApplication
          public class Application extends SpringBootServletInitializer {
          @Override
          protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
          return application.sources(Application.class);
          }
          public static void main(String[] args) throws Exception {
          SpringApplication.run(Application.class, args);
          }
          }

          But again, you might need to do some further tweaking to your code-base, so be sure to follow the instructions in the Spring documentation link above.

          Step 4: Deploy your code to Elastic Beanstalk

          Now that your code is prepped and ready to deploy to AWS, I'll show you how easy it is to deploy your code.

          Deploying Code Step 1: Make Sure You Create a WAR File

          The first pre-requisite step here is that you've set up Maven to deploy your project as a WAR file (instead of a JAR)

          This can be seen inside of your pom.xml file under the setting. It should look something like this:

          4.0.0
          com.proffesso
          proffesso-core
          1.5.1.12
          war
          CourseCreation
          CourseCreation project for Spring Boot
          Deploying Code Step 2: Run a Maven Install

          Your next step is to actually have maven package your code together into a deployable WAR file.

          Thankfully Maven makes this easy.

          1. Right click on your application's root project folder inside of Eclipse / Spring Tool Suite.
          2. Choose Run As
          3. Choose Maven Install
          4. Once you do this, Maven will get to work creating a WAR file for you to deploy.

            This file is typically created in the “target” directory of your app's directory… but Maven will tell you where this file has been created in the logs.

            Here's a screenshot of what to look for in order to find your WAR file:

            Now it's just a matter of logging into AWS, navigating to your app in Elastic Beanstalk and Updating your app by uploading this WAR file.

            Hit that big beautiful blue “Deploy” button and your WAR file will be uploaded to Elastic Beanstalk and deployed before your very eyes!

            Once the WAR file is uploaded, it typically takes around 60 seconds to process it and deploy it to your server. So just sit tight and watch AWS do it's magic and transition from the warning state to the “OK” state.

            Once the health is back to “OK”, you should be able to visit your unique URL for your website and see the fruits of your labor.

            Create a Database in AWS using Amazon RDS

            Sweet, so if you've follow all the instructions up to this point, then you've launched your application into the cloud!

            But…

            You still need to hook it up to a database, and if you were using a reference to localhost:8080 for your database connection string, then this newly launched cloud application isn't going to work properly.

            To solve this problem, we'll need to dive into how we can launch a database in the cloud using Amazon RDS.

            Navigate to the RDS product:

            Click the “Get Started Now” button, or alternatively, if you've already created an RDS instance in the past, you'll need to click the “Launch a DB Instance” button:

            Then for this post, we'll be creating a MySQL instance. These tend to be the cheapest, as MySQL is a free technology, but you can feel free to choose whichever option best suits your needs.

            Then I choose to launch an instance under a Dev/Test profile (as opposed to a Production type DB instance) as we're just getting started and the DB we're launching won't likely be the one we use in a production environment… so you can save some cash by choose the free option (i.e. dev/test version of MySQL).

            Next up we'll need to choose what kind of instance to run for the DB… in this case, I'd recommend you use the t2.micro instance as it's free tier eligible. Also, be sure to say “No” to the multi-AZ Deployment to stay on the free tier.

            I also choose the minimum 5GB of General Purpose SSD storage. It's plenty fast and it'll get the job done in terms of size… as of the writing of this article, my entire Proffesso.com application only uses about 1.5 MB of data for 100 teachers and thousands of students.

            Note: Don't be intimidated by Amazon's warning regarding using less than 100GB of data… they're just trying to get more money out of you ;) 5GB is plenty of space for now… you can always expand it later (you can't shrink your DB however, sneaky sneaky Amazon).

            Next up is your standard connection type information for your database. Choose a unique DB instance identifier. Note: this identifier is used to identify the AWS DB instance (not the name of the database).

            You'll also set up your username / password that you'll use to connect to your DB.

            Then you'll need to give your database a name (among other things), for now I just assign a name and leave everything else set as the default you see below:

            Now you're all set to launch your first Amazon RDS instance!

            But don't get too excited, there's still a bunch of other configuration we'll need to do.

            Go ahead and click on the “View Your DB Instance” button to watch the database get created before your very eyes… it usually takes about 10 minutes or so to get through the entire process of launching the instance to the point where it's available for use.

            Step 6: Configure the Amazon RDS Instance

            Once the status of your new DB instance changes from “creating” to “backing up” to “available” you'll be ready to start configuring things.

            The first step here is to ensure that you can connect to your DB from outside of your VPC (virtual private cloud). At this moment, if you attempted to connect to your DB from your app or from a DB IDE (like Toad or Workbench) it wouldn't work.

            So let's open up some ports so that we can connect to our new DB “from the outside”.

            Note: as of the writing of this article in early 2017, it looks like AWS automatically creates an entry for your IP address to connect to the DB instance. So if all goes well, you should be able to connect to your DB instance as soon as it's created… but it still important to understand how these security settings are set up so that if ever your IP address changes, you'll be able to properly connect.

            First step is to identify which security group was created for your DB instance.

            To do this, click on the arrow to expand the details section of your DB. When you do this you'll be in the “monitoring” tab, but we'll need to click on the “details” tab on the left side of the DB information to see the security group information. See the screenshot below for more details:

            Armed with the information of knowing our security group (in this case the security group ID is sg-cef63db1) we can now head over to the EC2 page by clicking on “Services -> EC2”:

            This will bring us to our EC2 page. From here, this is where we will need to edit our security groups for our EC2 instance. Click on the “Security Groups” option along the left side of the screen. Then we'll select our security group from before (sg-cef63db1) and we'll switch over to the “Inbound” rules.

            In the image above, you can see that it already has one rule, a “MYSQL/Aurora” rule that opens port 3306 for an IP address. The IP address you see in the screenshot was my IP address at the time this DB instance was created. If you don't have a line like this in your set up, here's how you add one… Click the “Edit” button to edit the “Inbound” rules and either edit the existing rule or add a new one like so:

            You can also choose to add a brand new rule and open it up so that it will allow all inbound traffic on port 3306. To do this, just choose the “Anywhere” option as the source like so:

            Now, it should go without saying that allowing any and all inbound traffic is a security risk. So I wouldn't suggest using that setting in production.

            But having said that, your new DB instance should be ready to rock!

            Step 7: Connect your code to the RDS Instance

            You can login to your DB instance using MySQL Workbench or Toad for MySQL using the following info:

            1. Host -> Endpoint (i.e. coderscampusdbs.cqejacgw6k3q.us-east-1.rds.amazonaws.com)
            2. Username -> myUsername
            3. Password -> [your password]
            4. Database -> myDatabaseName
            5. Port -> 3306
            6. Note: all this connection information can be found on the details tab of your DB instance, I'll show another screenshot highlighting all these data points below:

              Next, you'll need to connect your application's code to this database.

              This is easily done via your properties file which you used to connect to your database previously.

              If you're using a Spring Boot app, this can be found in your application.properties file.

              Point a Domain Name to your Fancy new Hosted Application

              Alright, so far you've got:

              1. Your application hosted in Elastic beanstalk – check
              2. Your database hosted in RDS and linked to your application – check
              3. A user friendly URL pointing to your application – not yet
                1. We're so close to being completely done with launching our Java app into the cloud.

                  In order to get rid of the non-user friendly URL that Elastic Beanstalk assigns to your application, you'll need to make use of another AWS product called “Route 53”.

                  So let's hop on over to the Route 53 Product:

                  This will bring up a page that will likely look like the following screenshot… Click on the “Get Started” button:

                  Inside of Route 53, we can create “Hosted Zones” which allow us to forward our incoming HTTP traffic to our Elastic Beanstalk application from any domain we own.

                  So the only pre-requisite here is that you'll need to own a domain name that will forward to our Elastic Beanstalk application.

                  For this example, I'll be using a domain I own by the name of “businessoftech.com”. The final outcome will be that if someone navigates to businessoftech.com it will send them to my Java application.

                  So I'll show you how I created my own “Hosted Zone” using the businessoftech.com domain name (you'll obviously need to use a different domain name for your hosted zone):

                  Once this hosted zone has been created, make note of the nameserver values in the “NS” row:

                  These nameservers are what you'll need to point your domain name to. How you do this will vary from provider to provider, but you can easily google the term “Change nameserver on domain with [xyz provider]”.

                  In my example, I use GoDaddy.com as my domain name provider. So I need to navigate to the DNS settings of my “businessoftech.com” domain and change the nameservers:

                  Note: this is what the GoDaddy nameserver settings look like, I needed to choose a “custom” setting for the nameservers inside of GoDaddy's settings.

                  Once we've forwarded the domain's nameservers over to Route 53's nameservers, we're ready to create a “Record Set” inside of Route 53.

                  I could write a whole article on DNS settings and record types, but for now the only thing you need to know is that we need to create “A Records” inside of Route 53. These are the pieces of data that tell the interwebs where to go when someone accesses a domain name.

                  So we want to configure it so that when someone navigates to businessoftech.com it should point to the AWS app.

                  Here's how we do that!

                  Create a new “Record Set”, it defaults to an “A Record” type, so we just need to set the alias to be “yes” and point it to our elastic beanstalk app:

                  Optionally, you might also want to point a subdomain to the same place as well. A common subdomain is “www”. So if someone navigates to www.businessoftech.com, it will also go to the app in AWS.

                  Create another record set, but this time set the “name” to be “www” like so:

                  Now, I'd like to say that we're done.

                  And we pretty much are done at this point.

                  But the only thing you need now, is patience (which can be very difficult for programmers).

                  You'll need to wait between 5 minutes and a few hours for these changes to take effect.

                  This means that even though we've set everything up properly, if you go to “businessoftech.com” (or whatever domain name YOU were using), it still won't be pointing to our application.

                  You just need to wait.

                  When I ran through this test, it took about 25 minutes before the changes propagated and I actually saw the domain forwarding to the app.

                  From my limited experience with this DNS stuff, I've noticed that if you live in the USA, the changes will likely propagate quickly (5 minutes or so) and if you live in Canada it takes about (20 – 30 minutes). If you live in a country without solid internet infrastructure, it can take much longer. I've seen DNS changes take hours in India.

                  So, go get a cup of tea, or make yourself a meal and forget about all this work you just did.

                  After you've taken a break, come back and try to navigate to your domain name and see if it's now pointing to your application.

                  If you've waited hours, and still nothing is working, then maybe go back over all these steps and see if you may have missed something.

                  The post The Ultimate Guide to Hosting a Java Web App with Amazon Web Services (AWS) appeared first on Coders Campus.

                  25 min
                2. EP14 – How to upgrade your code to Java 8

                  It's one thing to understand the new coding concepts and paradigms with Java 8, but it's another thing entirely to know the best way to upgrade your existing code.

                  I've been hard at work creating a new platform that hosts all of my courses called Proffesso.com. I started coding this app using Java 7, and then started learning about all the cool Java 8 features.

                  So this app I built was more or less “complete” for version 1.0 before I decided to upgrade it to Java 8.

                  So all of these tips are based on recent real world experience.

                  For Loops No More

                  One upgrade that I've seen lots of availability for is to replace any of your for loops with streams.

                  Now this doesn't work in ALL cases, as sometimes complex nested for loops are tough to convert over to the Java 8 Streams API, but for the most part it's a quick win.

                  One example of this upgrade could be seen in a Controller where I was populating two lists.

                  1. ActiveCourses
                  2. NonActiveCourses
                  3. The purpose of these two lists were to keep track of which courses a particular student had paid for, and which courses they may have cancelled (or maybe their last payment attempt had failed).

                    If the course was active, then it would be accessible to the student, if it was NOT active, then they shouldn't have access to the course. Simple.

                    Here's what the Java 7 code looked like:

                    List offers = user.getOffers();
                    List activeCourses = new ArrayList<>();
                    List nonActiveCourses = new ArrayList<>();
                    for (Offer offer : offers)
                    {
                    if (isActive(offer))
                    activeCourses.addAll(offer.getCourses());
                    else
                    nonActiveCourses.addAll(offer.getCourses());
                    }
                    nonActiveCourses.removeAll(activeCourses);

                    So the details of this are as follows.

                    An Offer contains a List of Courses. An Offer also contains the data needed to determine if all the courses in the Offer are active or not active.

                    The caveat here is that a Course can belong to many Offers, so if a Course is active in one Offer but not active in another, then they should still have access to that Course… Hence the second part of the code where we remove active Courses from the nonActiveCourse list.

                    Now, since we have some for loop madness going on here, this code is a prime candidate for Java 8 Streams.

                    Let's have a look at the upgraded code:

                    List offers = user.getOffers();
                    List activeCourses = offers.stream()
                    .filter(offer -> isActive(offer))
                    .map(Offer::getCourses)
                    .flatMap(Collection::stream)
                    .collect(Collectors.toList());
                    List nonActiveCourses = offers.stream()
                    .filter(offer -> !isActive(offer))
                    .map(Offer::getCourses)
                    .flatMap(Collection::stream)
                    .collect(Collectors.toList());
                    nonActiveCourses.removeAll(activeCourses);

                    Now, this particular scenario was a fairly complex one as the functionality of the Course object was dependent on a property on the Offer object (its parent).

                    So although our Java 8 solution is “technically” only 3 lines of code, the performance is worse because we are iterating over the offers one extra time (compared to the Java 7 solution).

                    So there can be an argument that an increase in readability of the code is worth the extra performance hit. But since this performance hit doesn't tend to occur with most Java 8 upgraded code, it's not too big a deal.

                    Having said that, the purpose of this tutorial is to talk about how to spot possible Java 8 upgrades, not the discussion of whether or not you SHOULD do the upgrade.

                    Again, in most cases, you SHOULD do the upgrade.

                    So all in all, whenever you see a for loop, there's always a possibility of upgrading to Java 8.

                    Null Checks

                    The next candidate for Java 8 upgrades comes when you see the dreaded “null check”.

                    For example:

                    Offer offer = offerRepo.findOne(offerId);
                    if (offer == null)
                    throw new OfferNotFoundException();

                    This is the type of code that you'll see all over the place.

                    You try to load an object, but before you can use that object, you always need to deal with the null case. Because if the object comes back as null for any reason, and you try to perform a dot operation on that object, you'll get a NullPointerException.

                    Boooooooooo.

                    So the solution is to do a “null check”.

                    The good news is that you can now upgrade this code with Java 8.

                    Anytime you see a null check, just substitute Java 8's Optional keyword like so:

                    Offer offer = Optional.ofNullable(offerRepo.findOne(offerId)).orElseThrow(() -> new OfferNotFoundException());

                    Ahhh, fancy!

                    Now, this particular example throws an exception in the case of a null being returned from our repository call… but what happens if you don't want to throw an exception?

                    You can just return a default value like so:

                    Offer offer = Optional.ofNullable(offerRepo.findOne(offerId)).orElse(new Offer());

                    The key is, whenever you see code that says if (something == null), you're ready to giggle like a little school girl and drop some Java 8 Optional on that bad boy.

                    Summary

                    So those are the main things to look out for in your code-base. If you know of any other “quick wins” when it comes to upgrading to Java 8, let me know in the comments section below.

                    The post EP14 – How to upgrade your code to Java 8 appeared first on Coders Campus.

                    31 min
                  4. EP13 – Default Methods in Java 8

                    Default methods for interfaces

                    Why should you care?

                    Programming to an interface. It's something we've been told is the right thing to do because it promotes flexible and extensible programs.

                    But here's one big issue with that approach. Before Java 8, you had to be extra sure that your interface design is “complete” if you release it into the wild.

                    Here's what I mean by that.

                    Let's assume you've published some code that other people will be using. This is typically done via releasing your app as a 3rd party plugin / library.

                    Within this library that you've released, you include many interfaces (because you're a good programmer and you've been programming to interfaces).

                    Let's say one of these interfaces is called MyWidgetService

                    public interface MyWidgetService {
                    void doSomethingAwesome();
                    void doAnotherAwesomeThing();
                    }

                    Done and done.

                    You're satisfied with this interface and the functionality it represents.

                    Until some new feature requests come in… And suddenly this interface is now out of date and needs one more abstract method: doTheAwesomestThing().

                    What's the issue right? Just add it in there and be done with it!

                    Not so fast. If you add another method in this interface, every other developer's application who relies on your app has the potential to break.

                    Wrath hath no fury like coders scorned.

                    Introducing Default Methods

                    Default methods allow you to add some actual functionality to your methods within the body of the method!

                    Whaaaaat?!

                    I know right.

                    So this means that you will be able to modify your existing interface by adding a new “default method” to it, and it won't cause a programmer uprising when they update their code base.

                    So how are these magical default methods created?

                    public interface MyWidgetService {
                    void doSomethingAwesome();
                    void doAnotherAwesomeThing();
                    default void doTheAwesomestThing() {
                    System.out.println("I'm the body of the 'doTheAwesomestThing()' method");
                    }
                    }

                    Okay, so with our interface updated with our new default method, all implementing classes of this interface will inherit the default functionality of the doTheAwesomestThing() method (without any compilation errors).

                    Note: if you're not actually implementing any sort of useful code inside of your default method, then I would imagine that it would be a good practice to throw an exception in the body of the method letting programmers know that the method hasn't actually been implemented with useful code.

                    Default Method Inheritance

                    If a parent interface declares a default method, and a child interface implements the parent interface, then the child interface will also inherit the functionality of its parent's default method.

                    You can also override the functionality of the parent's default method in the child interface if you like.

                    And finally, of course, if you override the functionality of an interface's default method in a concrete class, then the implementation in the concrete class will take precedence when run.

                    The post EP13 – Default Methods in Java 8 appeared first on Coders Campus.

                    26 min
                  5. EP12 – Java 8’s New Optional Keyword

                    NullPointerExceptions are a royal pain in the butt. They can strike at almost any point if your code encounters any “edge cases” that you hadn't previously thought of.

                    And when a NullPointerException is thrown, it can severely impact the quality of your user's experience.

                    For something as simple as “Hey, there's nothing here”, it's amazing how serious a problem this can be.

                    Well, that's where Java 8 has stepped up their game and finally provided us with a keyword we can use to solve this issue.

                    [Enter Stage Left]: Optional

                    The Java 8 Optional keyword is used as a wrapper around objects (kind of like a container).

                    In Oracle's tutorial on this keyword they use the example of a soundcard in a computer.

                    A computer can have a soundcard, or it could be missing a soundcard. So you could use the Optional keyword to get around the possible NullPointerExceptions.

                    Here's a diagram that gives you an idea of what it visually looks like to use Optional:

                    So, if you're in a situation where you're pre-Java 8, here's how you'd have to deal with all the possible NullPointerException issues:

                    String version = "UNKNOWN";
                    if(computer != null){
                    Soundcard soundcard = computer.getSoundcard();
                    if(soundcard != null){
                    USB usb = soundcard.getUSB();
                    if(usb != null){
                    version = usb.getVersion();
                    }
                    }
                    }

                    A pretty big mess right? We're probably all so used to writing this kind of code to check for nulls, but it's madness.

                    Java 8 Optional Syntax

                    So how do we write some nicer code now that we have Java 8 on our side? Let's have a look:

                    public class Computer {
                    private Optional soundcard;
                    public Optional getSoundcard() { ... }
                    ...
                    }
                    public class Soundcard {
                    private Optional usb;
                    public Optional getUSB() { ... }
                    }
                    public class USB{
                    public String getVersion(){ ... }
                    }

                    Pretty straight-forward I hope. All we're doing here is wrapping the Soundcard and USB objects with the Optional keyword.

                    Fair enough, but how do we access the values? Let's use Java 8 Streams to get the job done (Note: If you haven't learned about Streams yet, check out this article I wrote on the subject).

                    List usbVersions = computers.stream()
                    .flatMap(Computer::getSoundcard)
                    .flatMap(Soundcard::getUSB)
                    .map(USB::getVersion)
                    .orElse("UNKNOWN");

                    So what this code will do is it will extract all the usb versions from a list of Computers, but, in the case that there is no soundcard or no usb object available, it will fallback to the orElse() method.

                    So if a computer doesn't have a Soundcard, or if it doesn't have a USB, we'll get “UNKNOWN” and NO NULLPOINTERS! Boo yah!

                    So really what this Optional keyword is doing, is that it's forcing us to deal with the null case.

                    Creating Optional Objects

                    Alright, so we've seen how to deal with Optional objects that come from a stream.

                    But now let's take a look at how to create them.

                    Optional sc = Optional.of(new Soundcard());

                    One thing to understand here is that when you perform an Optional.of() call, the value shouldn't be null, otherwise it will still throw a NullPointerException.

                    If this seems strange to you, then you will likely prefer a different method:

                    Optional sc = Optional.ofNullable(new Soundcard());

                    With the Optional.ofNullable() method, if the object being passed in is null, you'll just get an empty Optional object when you try to access the soundcard inside.

                    Doing Stuff with your Optional Value

                    Does this look familiar:

                    SoundCard soundcard = ...;
                    if(soundcard != null){
                    System.out.println(soundcard);
                    }

                    Yeah, we've all been there. Let's harness the power of Optional:

                    Optional soundcard = ...;
                    soundcard.ifPresent(System.out::println);

                    Makes a lot more sense now right? If there's a value present in the Optional wrapper, it'll get printed out to the console. Otherwise, no worries, you're not going to throw a stupid NullPointerException because you tried to print an empty object.

                    Logging just got 10 times easier and safer!

                    PS. you can also use a soundcard.isPresent() check that returns true if soundcard contains a value.

                    PPS. oh yeah, you can also just get your object from the Optional container by saying soundcard.get()… but be careful, because that could throw a NoSuchElementException if there is no object in the container.

                    Java 8 Optional – Default Values and Actions

                    Pre-Java 8 this was a common scenario:

                    Soundcard soundcard =
                    aSoundcard != null ? aSoundcard
                    : new Soundcard("basic_sound_card");

                    Let's clean that up a bit with Java 8:

                    Soundcard soundcard = aSoundcard.orElse(new Soundcard("default"));

                    So this code reads like so… I'd like to declare a soundcard object and try to populate it with aSoundcard. If aSoundcard doesn't have a value, then assign a default value instead.

                    Now if you're new to Java 8, this might seem complicated… but it's only unfamiliar to you, it's actually pretty simple stuff.

                    The post EP12 – Java 8’s New Optional Keyword appeared first on Coders Campus.

                    38 min
                  6. EP10 – Why you need to start using Streams in Java

                    First and foremost, let's talk about why you should learn how to use streams.

                    Streams in Java 8 are essentially the solution to aggregating data easily.

                    What the heck do I mean by aggregating data?

                    Consider a database query that uses aggregates.

                    In SQL, the aggregates we have access to are operations that are performed on groups of data like:

                    • counting rows
                    • summing up values
                    • finding a min or a max
                    • getting an average
                    • All of these operations can be performed on data that is grouped into buckets.

                      If you're not at all familiar with the concept of aggregate functions and grouping, I'd highly suggest reading my articles / listening to my podcasts on the topics: SQL Aggregate Functions and SQL Group By

                      Data Aggregation without Streams

                      Okay, so if streams are great for data aggregation, then let's see some examples.

                      Let's say we have a game. In this game there are Players, and Players have high scores. They also have location information (i.e. city and state).

                      Now, if we wanted to get the top high scores for players in all 50 states in the USA, how would we do this with our Java 7 level coding skills (read: not using streams)?

                      Let's see how we would get aggregate information without using streams:

                      (brace yourself, code is coming!)

                      Player.class

                      package com.coderscampus;
                      public class Player
                      {
                      private Long id;
                      private Integer highScore;
                      private String state;
                      private String name;
                      public Long getId()
                      {
                      return id;
                      }
                      public void setId(Long id)
                      {
                      this.id = id;
                      }
                      public Integer getHighScore()
                      {
                      return highScore;
                      }
                      public void setHighScore(Integer highScore)
                      {
                      this.highScore = highScore;
                      }
                      public String getState()
                      {
                      return state;
                      }
                      public void setState(String state)
                      {
                      this.state = state;
                      }
                      public String getName()
                      {
                      return name;
                      }
                      public void setName(String name)
                      {
                      this.name = name;
                      }
                      @Override
                      public String toString()
                      {
                      return "\nname=" + name + ", state=" + state+ ", highScore=" + highScore;
                      }
                      }

                      WorkingWithStreams.class

                      package com.coderscampus;
                      import java.util.ArrayList;
                      import java.util.Arrays;
                      import java.util.Collections;
                      import java.util.Comparator;
                      import java.util.HashMap;
                      import java.util.LinkedHashMap;
                      import java.util.List;
                      import java.util.Map;
                      public class WorkingWithStreams
                      {
                      static List players = new ArrayList<>();
                      public static void main (String[] args)
                      {
                      System.out.println(getHighScoresWithoutStreams());
                      }
                      private static List getHighScoresWithoutStreams()
                      {
                      // without the use of streams, we'll need to break down each step
                      // of the process for finding the high scores in each state
                      // Step 0: make sure our players List is populated with data... normally
                      // we would have a database, but for our purposes, we'll just hard code
                      // some example data from the populatePlayerData method.
                      populatePlayerData();
                      // Step 1: Group the Player data by state
                      Map> groupedPlayerDataByState = new HashMap<>();
                      for (Player player : players)
                      {
                      if (groupedPlayerDataByState.containsKey(player.getState()))
                      {
                      groupedPlayerDataByState.get(player.getState()).add(player);
                      }
                      else
                      {
                      groupedPlayerDataByState.put(player.getState(), new ArrayList(Arrays.asList(player)));
                      }
                      }
                      // Step 2 & 3: Sort grouped Player data by high score and return the highest score
                      List highScores = new ArrayList<>();
                      for (Map.Entry> entry : groupedPlayerDataByState.entrySet())
                      {
                      Collections.sort(entry.getValue(), new Comparator () {
                      @Override
                      public int compare(Player player1, Player player2)
                      {
                      return player2.getHighScore().compareTo(player1.getHighScore());
                      }});
                      highScores.add(entry.getValue().get(0));
                      }
                      return highScores;
                      }
                      private static void populatePlayerData ()
                      {
                      players.add(createPlayer(1L, "John Doe", 5048, "Arizona"));
                      players.add(createPlayer(2L, "Jane Doe", 2400, "Arizona"));
                      players.add(createPlayer(3L, "Super Man", 1450, "Washington"));
                      players.add(createPlayer(4L, "Bat Man", 3205, "Washington"));
                      players.add(createPlayer(5L, "Frodo Baggins", 100, "Washington"));
                      players.add(createPlayer(6L, "Daenerys Targaryen", 10000, "Colorado"));
                      players.add(createPlayer(7L, "John Snow", 9800, "Colorado"));
                      players.add(createPlayer(8L, "Arya Stark", 6050, "Colorado"));
                      players.add(createPlayer(9L, "Sansa Stark", 7220, "California"));
                      players.add(createPlayer(10L, "Tyrion Lannister", 4680, "California"));
                      }
                      private static Player createPlayer (Long id, String name, Integer highScore, String state)
                      {
                      Player aPlayer = new Player();
                      aPlayer.setHighScore(highScore);
                      aPlayer.setId(id);
                      aPlayer.setName(name);
                      aPlayer.setState(state);
                      return aPlayer;
                      }
                      }

                      The output of all that code above will be this list of Player high scores by state:

                      [name=Daenerys Targaryen, state=Colorado, highScore=10000,

                      name=Sansa Stark, state=California, highScore=7220,
                      name=John Doe, state=Arizona, highScore=5048,
                      name=Bat Man, state=Washington, highScore=3205]

                      Now that's a CRAP load of code just to get this output… but without the use of Streams and Lambdas in Java 8, this is more or less what you would have to do to get the correct output.

                      Data Aggregation with Streams

                      Thankfully the alternative is stupidly simple.

                      First let's have a look at what the code would be to get our desired output using Streams, then I'll explain it.

                      What I'm going to show you is the one method that will do the work we need to return a list of Players. This method can be called from the main method in our code example above.

                      private static Collection> getHighScoresWithStreams()
                      {
                      return players.stream()
                      .collect(Collectors.groupingBy(Player::getState,
                      Collectors.maxBy(Comparator.comparing(Player::getHighScore))))
                      .values();
                      }
                      Optional Keyword

                      Obviously, there's a LOT going on inside of this code, but that's why I'm here to try my best to explain what's going on.

                      Starting from the top, the first thing you may see and scratch your head over is the Optional keyword. The Optional keyword was also introduced in Java's version 8. I'll cover that topic in-depth on the next post.

                      For now, you just need to know that this means there may or may not be a Player object inside of the Optional Collection container object.

                      Stream() Method

                      Next up is the actual stream method. This is the method you call when you want to start the process of creating a stream from your iterable Collection.

                      In this case, we have a collection of Player objects, this is the collection that we want to start streaming.

                      Once we've started our stream, there are a few things that we can do to our data. Sometimes you'd want to filter your data so as to eliminate data points that you don't care about, but that's not what we're doing in this example (as we want to consider all data points). I'll show an example with filtering next.

                      What we do want to do, is group our transactions together by some criteria. In our example, we want to group by the Player‘s state.

                      This is accomplished by first executing the collect method. The collect method is usually that last operation that you perform on a stream (though that isn't evident from our example here). Again, I'll show more examples after this.

                      In order to collect our data such that it will be returned to our collection of Players, we need to tell Java how we'd like to collect our data. So we tell Java that we'd like to group our data together using the Collectors.groupingBy method.

                      You can think of the Collectors keyword like a utility class. It's got a whole bunch of static methods that can be used to help us tell Java how we want to collect our data.

                      So when we initiate the Collectors.groupingBy method, we need to tell it how we'd like to group our data… so we say groupingBy(Player::getState).

                      Now, we're not done with the grouping function just yet. If all we wanted to do was to group our data by the Player‘s state, then sure, we'd be done… but we want to get the MAX value for each state.

                      Luckily the Collectors.groupingBy method can also take a second parameter. This second parameter is the “downstream” parameter which performs a reduction on the data. All this means is that it will reduce the number of returned data points in some way. For our purposes this reduction is going to reduce the data set to just the maximum value in each bucket.

                      So how do we tell Java that we'd like to reduce our data set to just the maximum values? Well lucky for us, we have a Collectors.maxBy utility method.

                      The Collectors.maxBy method takes one parameter, a Comparator.

                      Now from our last lesson, we learned about Lambdas and how to use them with a Comparator. You could just pass in a lambda expression like we already learned about… or, you could make use of yet another utility method: Comparator.comparing.

                      With the Comparator.comparing method, you just pass in the method of the class you'd like to compare on. So for our example we pass in Player::getHighScore. It will automatically compare values highest to lowest. If you wanted to get the reverse order, then you would just append .reversed() to the Comparator.comparing() method call.

                      And finally, now that we've told our collect method call how we'd like to collect our data, we're left with a Map of Strings as the key (the Player‘s state) and a List of Players as the values. Remember… We grouped Lists of Players by state, so that's what we're getting after all our collector calls ;)

                      So what we truly want to end up with, is not a Map, but a List. So how do we get the values from a Map? We invoke the .values() method on our Map.

                      And voila! We have our result set.

                      So, with four lines of code, it took me about 40 lines of text to explain what was going on. That's both the upside AND the downside of Java streams. They're efficient in terms of execution and conciseness, but there's a lot going on in the background that you need to understand.

                      Another Java Streams Example

                      As promised, I'd like to talk about another example.

                      This time, let's just say that we want to get a list of Players so are over the age of 20. Maybe the reason for this is that you want to throw an adults only party?

                      First, let's assume that we have the appropriate age property coded into our Player object. I'm too lazy to re-post the entire Player object with this new property, but we should all be familiar with how to add a property to an object at this point, right?

                      Now, how do we get a list of Players who are older than 20 with streams? Let's have a look:

                      players.stream()
                      .filter(p -> p.getAge() > 20)
                      .collect(Collectors.toList());

                      Here we can see the use of the filter method.

                      Filtering is pretty straight forward. The Filter method takes one parameter, a Predicate object.

                      A Predicate is a special interface provided by Java as of version 8. Recall that we talked about another one of these special interfaces in the last lesson… it was called the Consumer interface.

                      The difference between a Consumer interface and a Predicate interface is that the Consumer doesn't return anything, but the Predicate returns a Boolean.

                      This is important, because if we were to code a method for filtering, we would need to return a Boolean value to say if we should or shouldn't include a particular data point.

                      So, this is why the filter method takes a Predicate.

                      Here's a peek at what the Predicate looks like:

                      @FunctionalInterface
                      public interface Predicate {
                      boolean test (T t);
                      }

                      So using Lambda expressions, we can concisely write out an appropriate filter like we did above with: filter(p -> p.getAge() > 20).

                      Then finally, we fire off our collect method which will allow us to return all our our filtered data. In this case we use the Collectors.toList() utility method to convert our data points into a List of Players (very handy).

                      Example Using Map Functions

                      So, we've seen how to use some neat utility methods with the Collectors object, and we've seen how to filter results. Now let's have a look at how we can use the mapping functionality with streams.

                      With the mapping functions, you can translate your larger data set into a smaller one and return it.

                      A great example can be shown with the getPlayerIds() method that we'll build.

                      Let's assume that we want to get a List of the Player IDs, we can stream them and return them with the map function:

                      public List getPlayerIds()
                      {
                      return players.stream()
                      .map(Player::getId) // instead of returning all the players, just return the player IDs
                      .collect(Collectors.toList());
                      }

                      Hopefully this one is fairly straight-forward to understand. The key here is that we're wanting to return a Player‘s ID, so we use the map function to facilitate the translation from Player to Long.

                      Another Random Mapping Example

                      There are other mapping functions that we can make use of, like the mapToInt method. Let's have a look at a simple example:

                      Stream.of("a1", "a2", "a3")
                      .map(s -> s.substring(1)) // returns a stream of Strings: ["1", "2", "3"]
                      .mapToInt(Integer::parseInt) // returns a stream of Integers (an IntStream): [1, 2, 3]
                      .max() // returns an OptionalInt: 3
                      .ifPresent(System.out::println); // prints 3

                      The post EP10 – Why you need to start using Streams in Java appeared first on Coders Campus.

                      44 min
                    • EP09 – Java 8 – Lambda Expressions

                      With the release of Java's version 8 back in 2014, it has quickly become the most quickly adopted Java version to date.

                      Why are people so excited about it?

                      Well there are some pretty neat new “toys” we can play around with.

                      One such “toy” are lambda expressions. Though they may seem complex, I'll try my best to break them down and make them as simple as possible.

                      Benefits of the Lambda Expression

                      From what I can tell, there's really only one big advantage to using a Lambda expression…

                      Less code to write!

                      I'll explain what I mean with an example.

                      Let's consider the compare() method, which is used as part of the Comparator interface.

                      We typically see the Comparator used as an anonymous inner class, and anonymous inner classes are notorious for a lot of “noise”.

                      Let's assume we have a list of Transactions that need to be sorted by their date. How would we accomplish this without Lambas?

                      List transactions = getTransactionsFromDB();
                      Collections.sort(transactions, new Comparator()
                      {
                      @Override
                      public int compare(Transaction t1, Transaction t2)
                      {
                      return t1.getDate().compareTo(t2.getDate());
                      }
                      });

                      Now let's take a look at how we can make this less verbose with Lambdas:

                      List transactions = getTransactionsFromDB();
                      Collections.sort(transactions, (Transaction t1, Transaction t2) -> t1.getDate().compareTo(t2.getDate()));

                      A lot less code right?

                      Much less… but with less code comes a bit less clarity sometimes as to what's actually going on. So let's talk syntax.

                      The Lambda Syntax

                      The lambda is represented by the arrow -> syntax.

                      Arguments go on the left of the arrow and the body of the expression goes on the right.

                      In our example above, the arguments are Transaction t1, Transaction t2.

                      The body of the expression is t1.getDate().compareTo(t2.getDate()).

                      But how does Java know what to do given that there seems to be a lack of information for it to execute on?

                      Here's how Java works its magic… When you're executing the Collections.sort() method, the second argument that it expects is a Comparator.

                      The Comparator is an interface that defines one method that takes two templated parameters (in our case the templated parameters are Transaction t1 and Transaction t2)

                      So, this means that since Java knows that you should inserting a Comparator as the second parameter of the Collections.sort() method, it has some sort of idea as to what method you could be implementing.

                      Then when you insert our two Transaction arguments to the left of the Lambda syntax, Java knows that you must want to use the compare method.

                      I think of it like method overloading. When you have a bunch of methods that all share the exact same name, but they all have different method signatures… Java knows which method to invoke based on the arguments you pass in to the method. The same concept is happening here, it's using the method signatures to figure out which of the interface's methods you'd like to invoke.

                      Then, since this is an interface after all, there's no body in the interface's method… so we need to give it some code! This is the code that we include to the right of the Lambda's arrow syntax.

                      Java can then put all the pieces together and re-create the more verbose anonymous inner class code and your program will work just as well as it did before.

                      Further Shortening of Lambda Code

                      One more thing that you can do to shorten your Lambda expression code is to remove the parameter types for the parameters to the left of the arrow syntax.

                      Java will be able to infer the data types in most cases, so they can almost always be omitted.

                      Let's revisit our sorting code from before and remove the data types:

                      List transactions = getTransactionsFromDB();
                      Collections.sort(transactions, (t1, t2) -> t1.getDate().compareTo(t2.getDate()));

                      Do you see how it now just says (t1, t2) instead of (Transaction t1, Transaction t2)?

                      That's more Java 8 magic at work. Java knows that the (t1, t2) variables should be of type Transaction.

                      Pretty cool stuff.

                      Let's look at more examples!

                      Looping with Lambdas

                      Java 8 also released a handy method called forEach for Collections.

                      So now we can just execute a .forEach() method on collections that have iterators.

                      Let's use lambdas in combination with this forEach() method to output our Transactions to the console.

                      List transactions = getTransactionsFromDB();
                      transactions.forEach(t -> System.out.println(t));

                      So this begs the question… what abstract method is the forEach method working off of?

                      Well, the forEach method takes a Consumer action as a parameter.

                      The Consumer interface has a method that takes a generic T object as a parameter.

                      public interface Consumer {
                      /**
                      * Performs this operation on the given argument.
                      *
                      * @param t the input argument
                      */
                      void accept(T t);
                      }

                      To help make things more clear, let's re-write this with an anonymous inner class:

                      List transactions = getTransactionsFromDB();
                      transactions.forEach(new Consumer()
                      {
                      @Override
                      public void accept(Transaction t)
                      {
                      System.out.println(t);
                      }
                      });

                      So again, the forEach method takes a Consumer as a paramter. The Consumer interface defines a method called accept, which takes a generic object (in our case, it's taking a Transaction). We then define a body for the accept method, which outputs a transaction to the console.

                      Neat right?

                      I'm sure with time, as Lambdas become more widely accepted and used, they will become second nature to us Java programmers.

                      So for now, when you're writing your code and you're about to create an anonymous inner class, pause for a second and think of how you could turn it into a lambda expression instead!

                      The post EP09 – Java 8 – Lambda Expressions appeared first on Coders Campus.

                      46 min
                    • EP08 – Java Reflection – Writing Generic Java Code

                      If you've ever used the JavaScript language before, you might be familiar with the eval() function.

                      If you've never used JavaScript before, then no worries, I'll have an in-depth explanation as to what's going on.

                      For you JavaScript coders out there, the eval() function is used so that you can write any strings you like inside of the function, and the JavaScript engine will interpret it and run it like it was native JS code.

                      This “execution of code written out as Strings” concept is very similar to what reflection in Java accomplishes.

                      Reflection in Java is a way to call the methods of objects without needing the actual reference to those objects.

                      Another way to say it is, you can programmatically execute methods with reflection in Java.

                      Getting Started with Java Reflection

                      So, one of the keys to working with reflection in Java is to make use of the Method class.

                      The Method class gives us access to some cool stuff… Namely the ability to “invoke” methods that you want to have invoked (programmatically).

                      Let's assume you've got a standard Java class that has some getter and setter methods like so:

                      public class User
                      {
                      private Long id;
                      private String email;
                      private String password;
                      public Long getId()
                      {
                      return id;
                      }
                      public void setId(Long id)
                      {
                      this.id = id;
                      }
                      public String getPassword()
                      {
                      return password;
                      }
                      public void setPassword(String password)
                      {
                      this.password = password;
                      }
                      public String getEmail()
                      {
                      return email;
                      }
                      public void setEmail(String email)
                      {
                      this.email = email;
                      }
                      }

                      The User above is a super common Java bean that represents some user.

                      You've seen what it looks like to “invoke” any of these methods. For example, if we wanted to invoke the getter method for a User‘s email, it would be:

                      // Let's assume we can load a user from the database by ID like so:
                      User aUser = userRepository.findOne(1L);
                      // now we invoke the getEmail() method to get the email address of user with ID 1.
                      String userEmail = aUser.getEmail();

                      Nothing fancy going on here (assuming you know what a repository is, if you don't I'd recommend reading about it here)

                      So now let's introduce Java reflection.

                      Here's that same code, only now we'll invoke the getter method using reflection:

                      import java.lang.reflect.InvocationTargetException;
                      import java.lang.reflect.Method;
                      User aUser = userRepository.findOne(1L);
                      try
                      {
                      Method method = aUser.getClass().getMethod("getEmail");
                      String userEmail = (String) method.invoke(aUser);
                      } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
                      {
                      // If your code makes it in here, you're likely having an issue with one of the following:
                      // 1. Your method name is incorrect / doesn't exist on the User class
                      // 2. The method exists, but when Java tried to invoke it, you didn't pass the right object to invoke the method on
                      // 3. The method exists and you passed the right Java object, but you didn't give it the correct method signature (i.e. you didn't pass in the right types for the parameters.
                      e.printStackTrace();
                      }

                      Naturally it takes more code to make reflection do its thing, namely in the number of exceptions that need handling.

                      But the “business-end” of the code really comes down to two things:

                      1. Assigning a Method variable with the appropriate method you wish to invoke
                      2. Invoking the method
                      3. The first step is accomplished by first getting the appropriate class with which you'd like to work: aUser.getClass(). Then once we have the class we'd like to work with, we can locate the method we'd like to invoke via the getMethod() method.

                        Very meta.

                        The most important thing to note here is that the process of “getting a method” via the getMethod() method takes a String as an argument.

                        This means that you can pass in a String variable to this method… This means that the process of “getting” a method and invoking it can be completely dynamic and can change at run-time.

                        This is the whole reason why Java reflection exists! The ability to programmatically invoke methods.

                        Using Reflection to Invoke Methods with Parameters

                        Okay, so we've seen how to invoke a method that takes no parameters (i.e. a “getter” method) Now let's take a look at how to invoke a method that takes an argument (i.e. a “setter” method)

                        Note: just in case you're thinking that reflection is only get “getter” and “setter” methods, it is not, you can use reflection to invoke almost any methods you'd like. I say “almost” any methods because I'm not exactly sure if it can be used to invoke ANY method you want, so I'm just covering my own butt :)

                        Okay, having said that, let's invoke the setEmail() method with Java reflection:

                        import java.lang.reflect.InvocationTargetException;
                        import java.lang.reflect.Method;
                        User aUser = userRepository.findOne(1L);
                        try
                        {
                        Method method = aUser.getClass().getMethod("setEmail", String.class);
                        method.invoke(aUser, "[email protected]");
                        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
                        | InvocationTargetException e)
                        {
                        e.printStackTrace();
                        }

                        What our code above will do is the equivalent of writing aUser.setEmail("[email protected]").

                        The difference that you'll notice between the first Java reflection example and the second is that we have to add parameters to our getMethod() and method.invoke() methods.

                        We need to tell Java what the method signature is for the method we'd like to invoke. The reason we need to do this is because we can have methods with the same names, but different arguments in their method signatures. So just giving the name wouldn't be enough information for Java to locate the specific method you'd like to invoke.

                        And secondly, you need to actually pass the value(s) of the arguments for the method to use when invoked.

                        Iterating Through the Methods of a Class

                        Now, there may come a time when you don't want to pass the exact method name and method signature of the method you'd like to programmatically invoke.

                        One real-world example of this scenario is when saving values via an AJAX call.

                        If we have a form that needs to be filled out on a webpage, and the values will be sent to a database for storage as soon as the form fields are filled out, then reflection plays an important role.

                        Here's a snippet of code that I've used before to save both String and Double values from form fields.

                        // passing in, for example: emailAddress (as the fieldName)
                        // we need to capitalize the first letter to properly invoke the setter method (i.e. emailAddress becomes EmailAddress)
                        fieldName = StringUtils.capitalize(fieldName);
                        // get all the methods for a given class. Let's assume we've passed in User.class as the clazz variable
                        Method[] methods = clazz.getMethods();
                        Method method = null;
                        // since we grabbed all the methods from the User class (for example), we can iterate through them all
                        for (Method aMethod : methods)
                        {
                        // find any method that equals the one exact one we're searching for (i.e. "setEmailAddress")
                        if (aMethod.getName().equals("set" + fieldName))
                        {
                        method = aMethod;
                        // if this setter method is expecting a String, then we set the value that we got from the webpage
                        if (method.getParameterTypes()[0].getName().indexOf("String") > -1)
                        {
                        // we know that this setter method takes a String
                        method.invoke(obj, fieldValue);
                        }
                        // if this setter method is expecting a Double, then we convert the value from a String to a Double and set it
                        else if (method.getParameterTypes()[0].getName().indexOf("Double") > -1)
                        {
                        // If we're parsing a monetary value, then strip out any currency characters in the String before converting to a Double
                        fieldValue = fieldValue.replace("$", "");
                        // we know that this setter method takes a Double
                        method.invoke(obj, Double.valueOf(fieldValue));
                        }
                        break;
                        }
                        }
                        // save the object that was modified by the Java reflection code... in this case, we can assume that the "obj" variable is "aUser".
                        repo.save(obj);

                        This is some lovely and generic code that allows me to invoke the setter methods of ANY object I wish, and it will dynamically convert the values that I wish to set into the methods (given that it's either a String or a Double). Of course, I can also program it to convert from a String to any other data types, I just need to add them into the if structure.

                        The post EP08 – Java Reflection – Writing Generic Java Code appeared first on Coders Campus.

                        36 min
                      4. EP07 – Thymeleaf Part 3

                        All the show notes for this episode are available via the parent post.

                        These notes are only here as a placeholder for the podcast episode.

                        The post EP07 – Thymeleaf Part 3 appeared first on Coders Campus.

                        32 min
                      5. EP06 – Thymeleaf Part 2

                        All the show notes for this episode are available via the parent post.

                        These notes are only here as a placeholder for the podcast episode.

                        The post EP06 – Thymeleaf Part 2 appeared first on Coders Campus.

                        37 min

                      About Coders Campus Podcast

                      From the publisher's feed

                      Learn how to program using the Java programming language. This podcast will teach you step by step how to use the Java programming language to create your own applications or web applications! These…