The following steps will explain how to create the very first HelloWorld example on SCP Neo using the SAP S/4HANA Cloud SDK. If you want to follow this tutorial, we highly recommend checking out the first part of this blog series. You will not need any additional software as the server will run on your local machine.

Note: This post is part of a series. For a complete overview visit the SAP S/4HANA Cloud SDK Overview.


Goal of this blog post

The tutorial will show you the first steps when developing applications for the SCP Neo using the SAP S/4HANA Cloud SDK. To be precise, we will cover the following steps:

  1. Generate a project stub using a Maven Archetype
  2. Understand the project structure and its artifacts
  3. Implement and understand the Hello World Servlet
  4. Implement and understand the integration test
  5. Deployment


Generate Project from Archetype

Since you have already installed Maven, you can use it to generate a project stub from the SAP S/4HANA Cloud SDK Maven archetype. Just use your console (e.g. IDE, OS, navigate to a parent directory for your project and run the following command.

mvn archetype:generate -DarchetypeArtifactId=scp-neo-javaee6 -DarchetypeVersion=1.0.0-SNAPSHOT

Once the generation process is started, Maven will ask you for the usual module parameters:

groupId an identifier representing your group, company or organization (e.g.
artifactId an identifier for your application (e.g. firstapp)
version the version of your application (e.g. 1.0-SNAPSHOT)
package the name of the top-level package your source code will reside in (typically equal to your groupId, e.g.

After the required values are provided, Maven will generate the new project from the Cloud SDK archetype:

For the tutorial we suppose you have chosen “firstapp” as artifactId / project name.

Now you can work with it just like any other Maven project.

cd /path/to/firstapp
mvn clean install

Understand the project structure and its artifacts

Once the Maven project is generated, you can open your favorite IDE and load the project as “Maven Project”. After importing the project into your IDE, the overall structure will look like this:

The first thing you will notice, is the directories firstapp-app and firstapp-integration-tests. These are Maven sub-modules and they serve different aspects of your code testing environment. The following separation of application and test modules makes it possible to run integrations test without deploying.

  • firstapp-app contains the source code and configuration of your actual web application
    src/main/java Here goes your production code, nothing else. As you can see, there’s already the HelloWorldServlet, which we will look at in more detail soon.
    src/main/resources Anything that you require in your production code but is no compilable code goes here (typically things like API definition files for RAML or OpenAPI, Database Migration Files for Flyway or Liquibase)
    src/main/webapp contains the deployment descriptor for your web application – the infamous web.xml
    src/test/java This is the place for your automated tests.
    src/test/resources Tests may also require additional resources to work properly such as configuration files. This is their place.
    pom.xml This is your project management file for Maven where you can maintain other open source dependencies or use plugins that ease your build Environment.
  • firstapp-integration-tests contains the integration tests for your application. Its structure is similar to firstapp-app.
    src/test/java Here you can put all your integration tests. As you can see, there’s already the HelloWorldServiceTest corresponding to the HelloWorldServlet.
    src/test/resources Here go all the resources needed for the integration tests to run.

Implement and understand the Hello World Servlet

Now that you understand the project structure, take a closer look at the

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloWorldServlet extends HttpServlet
    private static final long serialVersionUID = 1L;
    private static final Logger logger = LoggerFactory.getLogger(HelloWorldServlet.class);
    protected void doGet( final HttpServletRequest request, final HttpServletResponse response )
        throws ServletException, IOException
    {"I am running!");
        response.getWriter().write("Hello World!");

The HelloWorldServlet extends HttpServlet, so this will be a HTTP endpoint that we can visit. We map this endpoint to the /hello-servlet route using @WebServlet("/hello-servlet").

By overriding the function doGet, we define what happens when a client performs an HTTP GET request on the /hello-servlet route. in this case we simply write a response containing “Hello World!”.

Implement and understand the integration test

Let’s take a look into the integration test project. It already contains a test for our simple HelloWorldServlet:

import com.jayway.restassured.RestAssured;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import static com.jayway.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith( Arquillian.class )
public class HelloWorldServiceTest
    private static final MockUtil mockUtil = new MockUtil();
    private URL baseUrl;
    public static WebArchive createDeployment()
        return TestUtil.createDeployment(HelloWorldServlet.class);
    public static void beforeClass()
    public void before()
        RestAssured.baseURI = baseUrl.toExternalForm();
    public void testService()
        final String body = given().get("/hello-servlet").body().asString();
        assertThat(body).isEqualToIgnoringCase("Hello World!");

As you can see, HelloWorldServiceTest uses JUnit to define the test.

  • It declares BeforeClass and Deployment for the general test setup.
  • The MockUtil provides easy access to mocked backend systems, e.g. preconfigured ERP connections for the test cases.
  • A WebArchive is deployed as a test run setup, including predefined additional classes, here: HelloWorldServlet.class
  • The integration test features RestAssured to easily run WebService calls over HTTP. Later you will see the advantages of having this library on hand, when dealing with more sophisticated examples. Here it runs an assertion test on the result of a GET request to the local /hello-servlet route.


It is time to finally deploy the application.

To run all required Maven goals, you can use the following commands in the project root path, i.e. parent module:

mvn clean install
mvn scp:clean scp:push -pl firstapp-app

The first command will cascade the goal execution of clean and install to both Maven sub modules. It will break in case of any compilation errors or test failures.

The second command will run a cleanup and startup for the SCP Neo application. The -pl argument defines the project location in which the Maven goals are being executed. If there is already a previously started instance of the application running, the goal scp:clean will try to stop it on localhost:8080 and will remove the cached server files of the application. scp:push will start the application on localhost:8080. The web server is started as background process and will take additional seconds to initialize.

Once a couple of seconds have passed, you can open a browser and go to http://localhost:8080/hello-servlet

  • You will be greeted with a login screen.
  • Enter test / test


Hello world!

That’s it.

When you are done and want to close the local SCP deployment, please use the scp:clean command for the application project. It will close any connection and stop the server.

mvn scp:clean -pl firstapp-app



Hint: Force application shutdown

In case the Maven scp:clean goal does not shutdown the application background process, even after the second execution, we recommend terminating it by hand. First you need to detemine the process id by the public port. Then terminate the process.

# Windows
netstat -o -n -a | findstr 0.0:8003
taskkill /F /PID <PID>
lsof -i :8003
kill -9 <PID>
To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply