Tuesday, March 20, 2018

Lets give Spring the Boot

Hi folks.  It's been a while since I've posted anything here.  Let's just say that life is complicated.

I was inspired to write this based on some recent experiences with Spring Boot.  This is a very powerful technology that relies on Spring and takes it to new and interesting places.  The bottom line is that while there are many ways to structure a system, if we pick one and stick with it we see some real benefits.  Productivity improves, communication between developers is facilitated, and some really cool automation can be brought to bear on the task of building a system.

So what IS Spring Boot?  It's really a few classes and conventions wrapped around Spring that frees the developer from a lot of the grunt work that used to be required.  For instance, the need for xml configuration files has been essentially eliminated.  Can I get an amen?  There is a lot more to it, but why don't we just dig in and create a simple application?

package com.oopuniversity.hellospringboot;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class App  {
    public static void main(String args[]) {
        SpringApplication.run(App.class, args);    }
}

There you have it.  A complete application which does nearly nothing...  And yet it's really got a lot going on inside of it.  This will actually create an application server listening (by default) on port 8080.

If we run this program we will see output like this:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.0.RELEASE)

2018-03-19 20:08:06.184  INFO 248504 --- [           main] com.oopuniversity.hellospringboot.App    : Starting App on Razer-Laptop with PID 248504 (C:\Users\jd\workspace\basics\hello-spring-boot\build\classes\java\main started by jd in C:\Users\jd\workspace\basics)
2018-03-19 20:08:06.186  INFO 248504 --- [           main] com.oopuniversity.hellospringboot.App    : The following profiles are active: development
2018-03-19 20:08:06.225  INFO 248504 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6a01e23: startup date [Mon Mar 19 20:08:06 EDT 2018]; root of context hierarchy
2018-03-19 20:08:07.349  INFO 248504 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2018-03-19 20:08:07.386  INFO 248504 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2018-03-19 20:08:07.386  INFO 248504 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.28
2018-03-19 20:08:07.398  INFO 248504 --- [ost-startStop-1] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [C:\Program Files\Java\jdk1.8.0_152\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\ProgramData\Oracle\Java\javapath;C:\Program Files (x86)\Razer Chroma SDK\bin;C:\Program Files\Razer Chroma SDK\bin;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\PuTTY\;C:\ProgramData\chocolatey\bin;c:\bin;c:\bin\flyway-5.0.6;C:\Program Files\MySQL\MYSQL Server 5.7\bin;C:\Program Files\MySQL\MySQL Utilities 1.6\;C:\Program Files\Git\cmd;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;C:\Program Files\Amazon\AWSCLI\;C:\Program Files (x86)\Graphviz2.38\bin;C:\Ruby24-x64\bin;C:\Users\jd\AppData\Local\Microsoft\WindowsApps;C:\Users\jd\apache-maven-3.5.2\bin;;.]
2018-03-19 20:08:07.500  INFO 248504 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2018-03-19 20:08:07.500  INFO 248504 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1277 ms
2018-03-19 20:08:07.606  INFO 248504 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2018-03-19 20:08:07.609  INFO 248504 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2018-03-19 20:08:07.609  INFO 248504 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2018-03-19 20:08:07.610  INFO 248504 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2018-03-19 20:08:07.610  INFO 248504 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2018-03-19 20:08:07.898  INFO 248504 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6a01e23: startup date [Mon Mar 19 20:08:06 EDT 2018]; root of context hierarchy
2018-03-19 20:08:07.967  INFO 248504 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2018-03-19 20:08:07.969  INFO 248504 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2018-03-19 20:08:07.993  INFO 248504 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-19 20:08:07.993  INFO 248504 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-19 20:08:08.024  INFO 248504 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-19 20:08:08.131  INFO 248504 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2018-03-19 20:08:08.162  INFO 248504 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2018-03-19 20:08:08.164  INFO 248504 --- [           main] com.oopuniversity.hellospringboot.App    : Started App in 2.244 seconds (JVM running for 2.621)

That's really am amazing amount of output for what appears to be a one-liner, isn't it?  One of the beautiful things about Spring Boot (and Spring in general) is that it is well documented internally and tells you what it's doing.  Perhaps more importantly it's really good about telling you what went wrong, which is pretty much an inevitability.

Since no URIs are defined, it won't actually serve up any pages as written, but you can tell it's doing at least something by hitting it with a browser.

Spring Boot is incredibly well suited to today's world of cloud-native applications built as micro-services.  An application such as this really doesn't need anything more than a functional JVM to be spun up as one instance or a hundred.  Everything it really requires to run can be bundled into a single .jar file and distributed where needed.  There's no more hassle with deploying application servers and the attendant configuration and devops challenges.

Let's add some functionality to this little program, so that it actually does a task for us.  We're going to build a RESTful calculator.  If you aren't familiar with RESTful services you can go look up what I'm talking about, but in short RESTful services are stateless web-based services that accept parameters in a URL and return usable responses to whoever calls them.  This allows for amazing levels of integration, and every task can be built using the technology best suited for it.

Since this is really just a technology demonstrator, I will not be building any of this using best practices for project layout and the like.  All of that is ultimately important but unnecessary for the purpose of this post.

Let's start with adding two numbers.  As this will be a RESTful service, everything needed to perform the math must be specified on the URL.  I will define it like this:

/add/number1/number2

That way, all I should really need to do to add 1 and 1 is call "http://localhost:8080/add/1/1"

Doing this is really very easy.  First, I need to inform Spring Boot that I want to serve up RESTful responses.  In the real world I'd create a new class (or several of them) for this purpose, but for now I'll just add it to the same little program.



That's straightforward enough.  Now we have to put in the code to do the math:

First we will need to add a couple of supporting imports:



And then we're ready to craft a working service:



The '@RequestMapping' annotation sets up a URI with embedded variables that will be used to invoke our new service.  The @PathVariable annotation ties the embedded variables to the parameter list for our method.

Believe it or not, that's all we need to get this working:



As you can imagine, it's as straightforward as can be to extend this to additional operations.

I will leave it as an exercise for the reader to add more operations to this.  It's very straightforward and you really shouldn't have any problems doing so.

That's about it for now.  Have fun!




Saturday, June 11, 2016

Basics: Just what IS an object, anyway?

This is a pretty long one by the standards of this blog.  Try to stay with it, though, the concepts are crucial.

Whether people are experienced developers used to procedural languages or newcomers to programming in general, really understanding objects tends to be a bit of a sticking point.  It's odd, because once you start to get it, everything seems quite natural.

An object is a representation of...  something.  Sometimes they represent fairly nebulous concepts, sometimes they represent very real physical things, but in all cases they're a kind of model.  Objects have properties, just like a flower has a color or a bee has [6] legs.  Objects have methods, which are really just things you can ask them to do, like 'release pollen' or 'sting someone'.  Finally, objects have events, or at least they can generate events.  That could be 'I've been pollinated' or 'I left my stinger in someone'.  Any particular object may make use of one, two or all three of these constructs.

Objects are based on classes in Java.  There is an all too human tendency to use the terms interchangeably and I've probably been guilty of doing that, too.  Technically, a class defines how an object should be built and an object is an instance of such a class.  Basically, after you write your code you compile it to create a .class file, and then when you run your code you can make a new object from said class. Making objects is easy enough, most of them get created (or instantiated) by using the new keyword like this:

    SimpleObject myObject = new SimpleObject();

Let's break that down:

First, we have declared that we're interested in working with a variable of type SimpleObject.  In other words, someone out there has written a SimpleObject.java file that defined a SimpleObject class and you're going to make an object from that definition.

That variable will be called 'myObject'.  We have to name our variables or we'd have a really hard time referring to them in our code!

We're not referring to a previously existing SimpleObject, we're going to make a completely new one.  The actual creation is handled by a constructor inside of SimpleObject.java, and we need to rely on that constructor doing its job, correctly setting up anything within the new object that needs to be in place.

Some objects don't appear to have constructors at all if you read the code, but that just means that there is no need for a constructor to do any setup work, so the programmer was able to rely on Java creating a default constructor for them.  The code for SimpleObject may have been written either way.  We don't care at this point, we just know we can call it.  I'll get back to constructors a little later when we talk about actually writing a class of your own.

Defining an class in Java is straightforward enough.  You don't really have to do any more than create a .java file with a bit of correct syntax.  The following example is enough to make a SimpleObject class (which really can't do anything but exist):

package com.oopuniversity.simpleobject;

public class SimpleObject {
}

Of course, a class that doesn't do anything isn't very useful, but I think it's good to have a picture in your head of all the 'extra' stuff that absolutely needs to be in place.  Code can look a bit busy to new developers, and its best to know what is basically template stuff that you should make sure is there and then ignore.

Just to break it down, that 'package' statement up at the top tells the compiler where the generated class file should go.  It's basically specifying an output directory, but using periods instead of slashes or backslashes.   Packaging is primarily an organizational tool and it turns out to be an important one later on.

Then we have 'public class SimpleObject' which tells us we're defining a class called SimpleObject.  That public keyword is important, it controls whether other objects in a larger program are able to create SimpleObjects or even refer to them at all.  For now, just use 'public'.  The day will come when you start to use other modifiers for specific reasons, but if you're reading this to learn you don't have those reasons yet.

Then we have some curly braces.  Those are ubiquitous in Java programs, and basically set boundaries for chunks of code.  In this case, they are setting the boundary for the beginning and end of the class, although they don't actually contain anything.  Anything between those brackets will be considered an attempt at having something be a part of SimpleObject.

Man, four paragraphs to describe three lines...  I guess a fair amount of information is consolidated down into even that useless bit of code!  Fortunately, that stuff always stays pretty much the same.  Once you understand that structure, you can kind of stop worrying about it and move on.

I mentioned above that I would talk about constructors.  Well, that time has come.  The following code is (aside from being in a different package) precisely identical to the previous code:

package com.oopuniversity.simpleobjectwithconstructor;

public class SimpleObject {
    public SimpleObject() {
    }
}

The only differences are:

  1. We changed the package definition, which lets us have this version of SimpleObject sit in the same project as the previous version without any conflicts.
  2. Now we have something new inside the braces that define the class.

The package definition is needed because I'm keeping everything inside one big project.  Just like you can't have two files with the same name in one directory, you can't have two classes with the same name in one package.

The new stuff inside the braces is defining a default constructor for SimpleObject.  It's public which means other objects can use it to make a new SimpleObject.  It has nothing between the parentheses, which means you can create a SimpleObject without having to give it any parameters, which are nothing more than pieces of information you give it (we'll talk about those soon).  Then it has some more of those fun curly braces, which again define boundaries.  Anything inside this particular pair of braces belongs not just to the class, but to the constructor itself.

Why would you want to write a constructor like this, making your class busier?  Well, you wouldn't, and that's why you get this for free with any class you write that doesn't bother defining a constructor of its own.  However, you DO need to know about and understand this for one simple reason:  It is also possible to define a class using a constructor (or a whole bunch of them if you like) that has parameters.  If you do this, the compiler will *not* create a default constructor for you and you won't be able to use a default constructor unless you explicitly write one.

https://github.com/OOPUniversity/OOP_Basics