About Vladimir Dejanovic

Serverless, Java and FN Project, first steps

Serverless isn’t a new thing, but it is fair to say there is still a lot of hype about it and how it will change everything, and how in the future everything will be serverless. Beside serverless/functions provided by cloud providers there are more and more serverless projects coming our way which goal is to break us from vendor lock-in and allow us to run serverless even on premise. Let us look at one such project FN Project.

What is FN Project

If we go to the official website of FN project http://fnproject.io/ we can read something like this:

“The Fn project is an open-source container-native serverless platform that you can run anywhere — any cloud or on-premise. It’s easy to use, supports every programming language, and is extensible and performant.”

FN Project is an open source project backed by Oracle, which base functions on containers. So, in theory, anything that can become container and can read and write from/to stdin/stdout, can become a function in FN project. This is a very nice feature, since it means, that in theory, it can support any programing language, unlike serverless/functions provided by cloud providers, where if your language of choice wasn’t supported you couldn’t use it with serverless.

Another nice feature of FN Project is that it can run on-premise, or in the cloud, or multiple clouds or in the combination of all mentioned.

Init setup

and add it to the path. After this, we are ready to start playing with FN.

Initial function in FN project

The first thing that we need to do is to start FN server. In order to do so, we only need to type this in a terminal/console

$ fn start

To validate that all is working good we can run this command

$ fn version

This will print version of fn server and fn client running on the machine. In the case of my laptop I get this values

$ fn version
Client version: 0.5.15
Server version: 0.3.595

Once we validated that all is good we can start to create our first function.

First function in FN Project

As mentioned FN project is “language agnostic”, in theory, it can support any language, but it doesn’t mean that it supports all languages at the moment. To see which languages are supported with the version we have we can run next command:

$ fn init --help

There is option –runtime which will list all options available on our machine. In my case, I will choose Java programing language. So to create the first function in Java we just need to run this command:

$ fn init --runtime java --trigger http function1

function1 is the name of the function, and here we put the name that we want to use. Option –trigger http means that we want to create HTTP trigger for our function which will allow us to call it over HTTP, for example via curl. After running this command fn will generate initial function for us and put it in the directory named as we named our function, in my case function1.

If we open pom.xml file, it will look like any other pom.xml file. Only dependencies there for FN project will be dependencies for testing part, there are no dependencies for building or running our java fn function.

If we open HelloFunction.java, we will again see that it is plain Java class, with ZERO dependencies.

There is only one method handleRequest that takes String as an input and provide String as an output. This is very different from writing functions in an implementation of cloud providers since they always add specific libraries or other types of dependencies in order for functions to work with their system. In case of FN since there are no dependencies it can run without any problem anywhere and you are not looked in into anything.

“Magic” of FN Project

So how does then FN works? How it knows how to run our function?

All magic is in func.yaml file. Or to be more precise all configuration needed to create a function in FN project. Let us take a closer look at it.

schema_version is pointing out which version of Fn was used to generate this file

name is the name of our function

version is the current version of our function and as we deploy it will be autoincremented

runtime language that we chose to write our function in

build_image docker image used to build our function depends of course on the language of choice

run_image docker image used to run our function

cmd entry point to our function, what needs to be called to perform our business logic

triggers here are defined triggers for invoking our function, in our case we have HTTP trigger

Unit tests in FN project

Maybe you noticed that one of the generated files is HelloFunctionTest.java, this file is indeed unit test file for our function, which is also autogenerated for us, and populated with a simple example of the unit test. Let us take a look at that file.

Except for some fn dependencies and part with @Rule, everything else looks like any other JUnit test in java. This unit test will just invoke our function without passing any parameters, and check if a result is “Hello world!”. The great thing about this test is that we can run it like any other unit test, we can invoke it from maven or IDE in any standard way.

Let us now write the test where we will pass some arguments and validated that our function still works as expected. In order to do so, we can add this code to our test class

Again, we can run it like any other unit test and validate that all is good.

Deploying and Invoking FN function

Now that we defined our function, we understand what files are generated and what is their purpose, we also did unit testing. Then it is time for us to deploy and invoke the function. We can deploy our function to the cloud and docker registry, but it is much easier and faster to deploy it only locally especially while we are busy in development. To deploy function we just need to run this command

$ fn deploy --app myapp1 --local

Here we are telling fn to deploy our function into application myapp1, and to deploy it only locally by providing option –local. Once we successfully deployed our function, we can invoke it. To invoke it we can run next command

$ fn invoke myapp1 function1

We provide the name of our application and the name of our function. If we would like to provide input to our function we can do it in this way

$ echo "Java is great" | fn invoke myapp1 function1

If you remember we also created HTTP trigger, so let’s use it to invoke our function.

$ curl http://localhost:8080/t/myapp1/function1-trigger

FN function with JSON

We can already do a lot of nice things with this, but let us move to the next level, where we will use JSON as input and output of our FN functions. First, we need to create a simple POJO class, something like this

Join Us

With 1,240,600 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!

Disclaimer

All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners. Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.