Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
As you might already know, as of 25 March 2021, the Java tools for Eclipse that work with the SAP BTP SDK for the Neo environment are no longer supported. As of 17 June 2021, the Java tools for Eclipse are removed from the SAP Development Tools site.

This means that if you were using the the Java tools for Eclipse, you will need to change your development process. From now on, you will use IDE of your choice and the console client that is part of the SAP BTP SDK for the Neo environment.

The following blog post will help you to get familiar with this development process. It is not a new process - it has always existed and some of you might already use it.

 


If you see a similar error message in Eclipse while trying to add a new cloud server, it is because the Java tools for Eclipse that work with the SAP BTP SDK for the Neo environment are no longer supported. They were available for installation and usage after end of support, until they stopped working properly.

If you are no longer able to install the Java tools for Eclipse that work with the SAP BTP SDK for the Neo environment, it is because they are removed from the SAP Development Tools site.


Development environment


Your development environment depends on what you want to achieve. Here is a sample table with actions and tools, which support these actions:


Working locally


Tools

























 Action Tools
Develop & build - IDE & build tools of your choice
- SAP BTP SDK
Run - Console client (part of SAP BTP SDK)
Debug - IDE of your choice
- Console client (part of SAP BTP SDK)
Profile Eclipse IDE (Oxygen or newer)
- SAP JVM Tools for Eclipse
- SAP JVM

The local server


In order to run the application locally, you need to install a local SAP BTP server; this is done with the console client command neo install-local. By running this command, you install a server runtime in a local folder called server, which by default is located in your SAP BTP SDK installation directory.

In order to configure and manage your local application (e.g. add destination, get application logs, etc.), you might need to work directly with some files in the server folder.

Some of the more interesting files within the server folder are:




























Purpose Location File
Get logs /server/log/
Debug app



/server/bin/



- setenv.sh
- setenv.bat
Add app authentication /server/config_master/com.sap.security.um.provider.neo.local/ - neogroups.json
- neousers.json
Manage destinations



/server/config_master/service.destinations/destinations/




Note: the com.sap.security.um.provider.neo.local folder does not exist upon initial local server installation; you need to create the folder and required files inside if your scenario needs them.

Working on the cloud


Tools





















 Action Tools
Run Console client (part of BTP SDK)
Debug Eclipse IDE (Oxygen or newer)
- SAP JVM Tools for Eclipse
Profile Eclipse IDE (Oxygen or newer)
- SAP JVM Tools for Eclipse

The cloud server


In the cloud scenario you do not have access to a server folder. You can configure and manage your application (e.g. add destination, get application logs) via console client commands.


Development process


Let's go through a sample development process by building a simple Java web application.


Prerequisites


You can use IDE and build tools of your choice for developing the Java application. In the blog post, we will use Eclipse IDE and Maven.

We will also use Linux, Mac OS X, or other Unix based OS; if you are using Microsoft Windows - pay attention to the additional notes on each step.

  • IDE of choice; for the purposes of the blog post: Eclipse IDE

  • Build tool of choice; for the purposes of the blog post: Maven

  • SAP BTP SDK; for the purposes of the blog post: Java Web Tomcat 8, version 3.129.5



Create and build Java web project



  1. Create new Java web project using Maven
    mvn archetype:generate -DgroupId=com.sap.sample -DartifactId=sample-web-app -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false


  2. Create PublicServlet.java file under /sample-web-app/src/main/java/com/sap/sample/

    cd sample-web-app
    mkdir -p "./src/main/java/com/sap/sample/"
    touch "./src/main/java/com/sap/sample/PublicServlet.java"




  • And update its contents
    package com.sap.sample;

    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    public class PublicServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws
    ServletException, IOException {
    response.getWriter().println("<p>Hello!</p>");
    }
    }


  • Update the sample-web-app/src/main/webapp/WEB-INF/web.xml

    <?xml version="1.0" encoding="UTF-8"?>

    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://Java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>Hello!</display-name>

    <servlet>
    <servlet-name>PublicServlet</servlet-name>
    <servlet-class>com.sap.sample.PublicServlet</servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>PublicServlet</servlet-name>
    <url-pattern>/public</url-pattern>
    </servlet-mapping>

    </web-app>


  • Add dependency to Servlet 3.1 API in the pom.xml
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
    </dependency>​




  • Build the project using Maven
    mvn clean install




Run the application locally


This is the documentation describing how to run applications locally.

We have developed and built the Java application. Let's run it locally.

Procedure



  1. Run the project on a local SAP BTP server
    # install local server; the server will be located in the <SDK installation folder>/server by default
    neo install-local​

    # start local server
    neo start-local

    # deploy the sample application and check http://localhost:8080/sample-web-app/public
    neo deploy-local --source <path to the sample-web-app folder>/sample-web-app/target/sample-web-app.war​


  2. Check that the application is running on http://localhost:8080/sample-web-app/public



Debug the application locally


This is the documentation describing how to debug applications locally.

We have developed, built and run the Java application locally. Let's debug it locally.

Note: you can use IDE of your choice; for the purposes of the blog post we are using Eclipse IDE.

Prerequisites



  • You should have already installed a local server and run the application on it.


Procedure



  1. Enable remote debugging of the local SAP BTP server: open /<SDK installation folder>/server/bin/setenv.sh and add in the end of the file:
    CATALINA_OPTS="-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n"

    Note for Microsoft Windows users: check documentation for this step.

  2. Restart the local SAP BTP server
    # stop the local server
    neo stop-local​

    # start the local server
    neo start-local​


  3. Import the project in the IDE.

  4. Attach a remote Java debugger from within the IDE on localhost:5005

  5. Put a debug breakpoint on the PublicServlet.java doGet() method and hit http://localhost:8080/sample-web-app/public


Profile the application locally


This is the documentation describing how to profile applications locally.

We have run the Java web application locally. Let's profile it with SAP JVM Profiler.

Note: if you want to profile your application using SAP JVM Profiler, you must use SAP JVM, SAP JVM Tools for Eclipse and thus Eclipse IDE (Oxygen or newer).

Procedure


Follow the procedure as described in the documentation.

 

Environment variables and system properties locally


We have a Java web application, which reads environment variables and system properties. Let's run the Java web application locally and set the required environment variables and system properties.

Procedure for system properties



  1. Read the system property in your Java web application
    System.getProperties().getProperty("custom.system.property")​


  2. Add the system property in the end of the /<SDK installation folder>/server/props.ini file
    -Dcustom.system.property=my.system.property​


  3. Deploy the application locally and restart the local SAP BTP server if already started


Procedure for environment variables



  1. Read the environment variable in your Java web application
    System.getenv("CUSTOM_ENVIRONMENT_VARIABLE")​


  2. Add the environment variable in the end of the /<SDK installation folder>/server/bin/setenv.sh file
    export CUSTOM_ENVIRONMENT_VARIABLE="MY_ENVIRONMENT_VARIABLE"​

    Note for Microsoft Windows users: add the environment variable in the  /<SDK installation folder>/server/bin/setenv.bat file and using the set CUSTOM_ENVIRONMENT_VARIABLE="MY_ENVIRONMENT_VARIABLE" syntax.

  3. Deploy the application locally and restart the local SAP BTP server if already started


Run the application on the cloud


This is the documentation describing how to run applications on the cloud.

We have developed and run the Java application locally. Let's run it on the cloud.

Procedure



  1. Deploy the application on the cloud
    neo deploy --host <host> --account <subaccount_name> --application <application_name> --source <path to the sample-web-app folder>/sample-web-app/target/sample-web-app.war​ --user <email_or_user>  ​




Debug application on the cloud


This is the documentation describing how to debug applications on the cloud.

We have deployed the Java application on the cloud. Let's debug it on the cloud.

Note: if you want to debug the application on the cloud, you must use SAP JVM Tools for Eclipse and thus Eclipse IDE (Oxygen or newer).

Procedure


Follow the procedure as described in the documentation.


Profile the application on the cloud


This is the documentation describing how to profile applications on the cloud.

We have deployed the Java application on the cloud. Let's profile it on the cloud.

Note: if you want to profile the application on the cloud, you must use SAP JVM Tools for Eclipse and thus Eclipse IDE (Oxygen or newer).

Procedure


Follow the procedure as described in the documentation.

 

Environment variables and system properties on the cloud


This is the documentation describing how to set environment variables and system properties when dep...

We have a Java web application, which reads environment variables and system properties. Let's set the environment variables and system properties and run the Java web application on the cloud.

Procedure for system properties



  1. Read the system property in your Java web application
    System.getProperties().getProperty("custom.system.property")​​


  2. Deploy the application on the cloud and set the required system property via the "--vm-arguments" parameter
    neo deploy --host <host> --account <subaccount_name> --application <application_name> --vm-arguments "-Dcustom.system.property=my.system.property" --source <path to the war file>​ --user <email_or_user>​



Procedure for environment variables



  1. Read the environment variable in your Java web application
    System.getenv("CUSTOM_ENVIRONMENT_VARIABLE")​​


  2. Deploy the application on the cloud and set the required environment variable via the "--ev" parameter
    neo deploy --host <host> --account <subaccount_name> --application <application_name> --ev CUSTOM_ENVIRONMENT_VARIABLE=MY_ENVIRONMENT_VARIABLE --source <path to the war file>​ --user <email_or_user>​



Use SAP BTP SDK API in the web project


Until now, we have developed a simple Java application, which does not take advantage of any SAP BTP APIs. Let's change that.


Add SAP BTP API as Maven dependency


This is a blog post describing how to build Java web applications with Maven.

This are all SAP BTP artifacts on Maven Central.

  1. Add the SAP BTP SDK API as a dependency in the In the /sample-web-application/pom.xml

    		<dependency>
    <groupId>com.sap.cloud</groupId>
    <artifactId>neo-java-web-api</artifactId>
    <version>3.129.5</version>
    <scope>provided</scope>
    </dependency>

    Note: the artifactId and version depend on the kind and version of the SAP BTP SDK.



Add destination locally


We have developed the Java application. Let's add a destination in the existing servlet.

Note: when working locally, you must add all destinations as files with no extension in the /server/config_master/service.destinations/destinations/ folder.

  1. Add destination called outbound-internet-destination in the /server/config_master/service.destinations/destinations/ folder
    Name=outbound-internet-destination
    URL=https\://help.sap.com/doc/8cd05d3af14a42f7a53c0609acf55826/Cloud/en-US/terms_of_use.html
    ProxyType=Internet
    Type=HTTP
    Authentication=NoAuthentication
    TrustAll=true
    CloudConnectorVersion = 2​


  2. Update the PublicServlet.java code to locate the destination and print its properties
    package com.sap.sample;

    import java.io.IOException;

    import javax.annotation.Resource;
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import com.sap.cloud.account.TenantContext;
    import com.sap.core.connectivity.api.configuration.ConnectivityConfiguration;
    import com.sap.core.connectivity.api.configuration.DestinationConfiguration;

    public class PublicServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Resource
    private TenantContext tenantContext;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
    // Look up the connectivity configuration API
    Context ctx = new InitialContext();
    ConnectivityConfiguration configuration = (ConnectivityConfiguration) ctx
    .lookup("java:comp/env/connectivityConfiguration");

    // Get destination configuration
    String destinationName = "outbound-internet-destination";
    DestinationConfiguration destConfiguration = configuration.getConfiguration(destinationName);

    if (destConfiguration == null) {
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
    String.format(
    "Destination %s is not found. Hint:" + " Make sure to have the destination configured.",
    destinationName));
    return;
    }

    String url = destConfiguration.getProperty("URL");
    String proxyType = destConfiguration.getProperty("ProxyType");

    response.getWriter().println("<p>Destination: " + url + "</p><p>Proxy type: " + proxyType + "</p>");
    } catch (Exception e) {
    // Connectivity operation failed
    String errorMessage = "Connectivity operation failed with reason: " + e.getMessage();
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMessage);
    }
    }
    }


  3. Update the sample-web-app/src/main/webapp/WEB-INF/web.xml to declare the JNDI lookup for the destination:
    <resource-ref>
    <res-ref-name>connectivityConfiguration</res-ref-name>
    <res-type>com.sap.core.connectivity.api.configuration.ConnectivityConfiguration</res-type>
    </resource-ref>​


  4. Build the application, deploy it on the local server and request http://localhost:8080/sample-web-app/public. It should print the destination properties. 



Add authentication locally


This is the documentation describing authentication in Neo environment.

We have developed the Java application. Let's add a second servlet in it, which will be secured with a basic authentication.

  1. Create ProtectedServlet.java file under /sample-web-app/src/main/java/com/sap/sample/
    package com.sap.sample;

    import java.io.IOException;
    import java.security.Principal;

    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import com.sap.security.um.service.UserManagementAccessor;
    import com.sap.security.um.user.PersistenceException;
    import com.sap.security.um.user.UnsupportedUserAttributeException;
    import com.sap.security.um.user.User;
    import com.sap.security.um.user.UserProvider;

    public class ProtectedServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
    response.getWriter().println("<p>Welcome " + getUserAttributes(request.getUserPrincipal()) + "</p>");
    } catch (Exception e) {
    response.getWriter().println("Protected operation failed with reason: " + e.getMessage());
    }
    }

    /**
    * Get name and e-mail user attributes and return them as condensed string.
    */
    private String getUserAttributes(Principal principal)
    throws PersistenceException, UnsupportedUserAttributeException {
    // Get user from user storage based on principal name
    UserProvider userProvider = UserManagementAccessor.getUserProvider();
    User user = userProvider.getUser(principal.getName());

    // Extract and return user name and e-mail address if present
    String firstName = user.getAttribute("firstname");
    String lastName = user.getAttribute("lastname");
    String eMail = user.getAttribute("email");
    return (firstName != null && lastName != null ? firstName + " " + lastName + " [" + principal.getName() + "]"
    : principal.getName()) + (eMail != null ? " (" + eMail + ")" : "");
    }
    }


  2. Add the second servlet and a security configuration in the sample-web-app/src/main/webapp/WEB-INF/web.xml
    <?xml version="1.0" encoding="UTF-8"?>

    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://Java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>Hello!</display-name>

    <servlet>
    <servlet-name>PublicServlet</servlet-name>
    <servlet-class>com.sap.sample.PublicServlet</servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>PublicServlet</servlet-name>
    <url-pattern>/public</url-pattern>
    </servlet-mapping>

    <servlet>
    <servlet-name>ProtectedServlet</servlet-name>
    <servlet-class>com.sap.sample.PublicServlet</servlet-class>
    </servlet>

    <servlet-mapping>
    <servlet-name>ProtectedServlet</servlet-name>
    <url-pattern>/protected</url-pattern>
    </servlet-mapping>

    <!-- Secure application -->
    <login-config>
    <auth-method>BASIC</auth-method>
    </login-config>

    <security-constraint>
    <web-resource-collection>
    <web-resource-name>Protected Area</web-resource-name>
    <url-pattern>/protected/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
    <role-name>Everyone</role-name>
    </auth-constraint>
    </security-constraint>

    <security-constraint>
    <web-resource-collection>
    <web-resource-name>Public Area</web-resource-name>
    <url-pattern>/*</url-pattern>
    </web-resource-collection>
    </security-constraint>

    <security-role>
    <description>All SAP BTP users</description>
    <role-name>Everyone</role-name>
    </security-role>

    </web-app>​


  3. Add the neousers.json file in /server/config_master/com.sap.security.um.provider.neo.local/
    The file contains two users with role Everyone: first user with id john and password johndoe, and second user jane with password janedoe.
    Note: create the com.sap.security.um.provider.neo.local folder, if not already created.
    {
    "Users": [
    {
    "UID": "john",
    "Password": "{SSHA}Ub53I5XdyH/Nh3gr3pUQ6vPyjYPPRVKF",
    "Roles": [
    "Everyone"
    ],
    "Attributes": [
    {
    "attributeName": "firstname",
    "attributeValue": "John"
    },
    {
    "attributeName": "lastname",
    "attributeValue": "Doe"
    },
    {
    "attributeName": "email",
    "attributeValue": "john.doe@sap.com"
    }
    ]
    },
    {
    "UID": "jane",
    "Password": "{SSHA}/obq802EmKc+rc4/fjU/XzbvBiaHtNIH",
    "Roles": [
    "Everyone"
    ],
    "Attributes": [
    {
    "attributeName": "firstname",
    "attributeValue": "Jane"
    },
    {
    "attributeName": "lastname",
    "attributeValue": "Doe"
    },
    {
    "attributeName": "email",
    "attributeValue": "jane.doe@sap.com"
    }
    ]
    }
    ]
    }

    Note: SSHA is a password storage scheme, the salted version of the SHA-1. When developing locally, you can use the slappasswd utility - an OpenLDAP password utility for Linux, Mac OS X, or other Unix based OS, which generates such hashes: "slappasswd -h {SSHA} -s <password>".
    There are also few online web pages, which can generate LDAP SSH password hash; just have in mind that this approach is appropriate for testing purposes only.

  4. Build the application, deploy it on the local server and request http://localhost:8080/sample-web-app/protected. It should ask you to log in; usernames and passwords are as follow: is john with password johndoe; jane with password janedoe. 


 

Wrap up


In this blog post we were able to develop, run, debug, profile and configure an application locally and on the cloud without using the Java tools for Eclipse that work with the SAP BTP SDK for the Neo environment.

I hope the blog post helped you to set up and start the development process using the console client that is part of the SAP BTP SDK for the Neo environment.
6 Comments