Skip to Content

The context

As most people who come from the ABAP world, I started my journey into SAPUI5 by using SAP’s tools: Eclipse and the SAPUI5 plugin. It appears to make our lives easier by setting up a local server for testing and running the proxy servlet to handle CORS problems. I say “appears” because then we see in the forums a lot of people with proxy related problems. In Eclipse you use something like this in your oData URLs


proxy/http/<server>:<port>/sap/opu/data/sap/<service>


At the very least this is bad because you need to change your code when you deploy to a SAP server (or create a bunch of ifs to validade where your call if being made). What you should have is this:

/sap/opu/data/sap/<service>


and let the host be determined automatically by the server config. At first you are happy Eclipse handles this (albeit poorly), after a while you will want more control. This is how to do it.

The solution

Let me make this clear: Eclipse is a terrible SAPUI5 editor. You will want to get rid of it and I will help you do it. First step: running your own webserver with proxy. The solution – Node.js and Grunt.

First you must install Node.js from https://nodejs.org. This will install the NPM javascript package manager that will be your friend for a lot of tasks. Then open terminal and run (with sudo/administrator if necessary):

npm install -g grunt-cli


Grunt is a javascript based task runner that handles repetitive development tasks for you. Setting up a webserver with proxy is such a task. There are two important files that you should put in your project folder (which you see in every Github project):

– package.json: Describes your project and its dependencies (for Node/NPM);

– gruntfile.js: Describes the tasks that should be run (for Grunt)

I’ll write another blog to describe these in more detail, but for the time being lets focus on the gruntfile.js that will setup the server and proxy:


var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;
module.exports = function(grunt){
    require('load-grunt-tasks')(grunt, {scope: 'devDependencies' });
    grunt.initConfig({
        connect: {
            server: {
                options: {
                    port: <desired local port>,
                    hostname: 'localhost',
                    keepalive: true,
                    middleware: function (connect, options){
                        return [
                            proxySnippet,
                            require('serve-static')(options.base[0])
                        ]
                    }
                },
                proxies:[
                    {
                        context: '/sap/opu/odata',
                        host: '<sap_host>',
                        port: '<sap_port>',
                        https: false
                    }
                ]
            }
        }
    });
    grunt.registerTask('default',[
        'configureProxies:server',
        'connect'
    ]);
}












The server-options setups the local webserver and the proxies setting redirects all URLs that begin with ‘/sap/opu/odata’ to the specified remote server. Notice that you can configure several proxies for different URLs inside the [ ].

To run the script, just navigate to the project directory in Terminal, and then run “grunt”. You should get something like this:


Captura de ecrã 2015-04-4, às 10.48.11.png

Well … after you install the dependencies anyway :). To do this, save this simple package.json in your main project folder:


{
  "name": "<Project name>",
  "version": "0.1.0",
  "description": "<Descrition>",
  "main": "Component.js",
}












And then run these commands on the terminal (since you are not using the global install “-g” you won’t need sudo or administrator):



npm install grunt-contrib-connect --save-dev
npm install grunt-connect-proxy --save-dev
npm install load-grunt-tasks --save-dev
npm install serve-static --save-dev










Now just run grunt again and you will get the screenshot I showed before. Remove the hostname and port from your oData calls, and they will be redirected according to the grunt file using the /sap/opu/odata path.

To confirm the redirections are being correctly handled, you can run grunt with the –verbose setting. If you do, every redirection made by the proxy will show up in the terminal:

Captura de ecrã 2015-04-4, às 11.03.59.png

Now that you don’t need Eclipse to setup the webserver and proxy, you are one step closer to not needing it. Further steps on the next blog.


Side notes

If you look at the package.json you will see that entries have been added to the devDependencies. We will use this later to automatically install the dependencies using “npm install” – you don’t have to perform all these steps manually every single time.


Finally, to make it clear how powerful these open source tools are becoming, I would like to point out that even Microsoft has included them in Visual Studio 2015 templates. You now see package.json and gruntfile.js (and bower.json) on ASP.Net projects 🙂


Edit 01/12/2015: Update require(‘serve-static’)(options.base[0]) because of new connect version.

To report this post you need to login first.

12 Comments

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

  1. Yanming Cao

    It’s great to see people using NodeJS and tools that are built with NodeJS to automate their work! NodeJS is a great set of tools for developers.

    (0) 
    1. Joao Sousa Post author

      That’s more a NPM problem, I see you have checked the link How to setup Node.js and Npm behind a corporate web proxy

      Don’t be insulted by this question (it’s better not to assume anything in SCN), but you have replaced http://proxy.company.com:8080 with the true server/port of your proxy correct?

      I’m not the best person to help, you should probably check npm forums for that. I haven’t used proxies since I use my personal Mac to program, not my company issued Windows tank.

      (0) 
        1. Joao Sousa Post author

          If you don’t have windows authentication, you need to put the user and password on the URL. On that link, you have an example: “npm config set proxy http://“user:P@ssword”@proxy.server:1234”

          I hate proxies, even in my corporate PC I use 4G most of the time (in the office).

          (0) 
  2. Tobias Hofmann

    For the lazy ones: “C:\Program Files (x86)\Google\Chrome\Application\chrome.exe” –disable-web-security

    An alternative is to run a local reverse proxy (apache, nginx).

    (0) 
  3. Frank Luzat

    Thanks for this guide.

    It helped my setting up my UI5 dev. environment without Eclipse and Tomcat.

    Nevertheless, I had to do some changes to the provided gruntfile, since there have been some changes to the connect module meanwhile:

         var mountFolder = function(connect, dir){ 

              return connect.static(require(‘path’).resolve(dir)); 

         }; 

    The above snippet is never used. I removed it and everything still works.

         connect.static(options.base[0]), 

    This yields “Warning: connect.static is not a function”


    It must be replaced to work with the latest version of the connect package:


         require(‘serve-static’)(options.base[0]),



    (0) 
    1. Michael Appleby

      Please create a new Discussion marked as a Question.  Comments to a Blog (or Document) is not the right vehicle for asking questions as the results are not easily searchable.  Once your issue is solved, a Discussion with the solution (and marked with Correct Answer) makes the results visible to others experiencing a similar problem.  If a blog or document is related, put in a link.

      NOTE: Getting the link is easy enough for both the author and Blog.  Simply MouseOver the item, Right Click, and select Copy Shortcut.  Paste it into your Discussion.  You can also click on the url after pasting.  Click on the A to expand the options and select T (on the right) to Auto-Title the url.

      Thanks, Mike (Moderator)

      SAP Technology RIG

      (0) 
      1. Frank Luzat

        Hi Michael,

        My comment is clearly related to the original blog post and points out some necessary corrections for the script to work with the current library version.

        Someone taking the script from this blog would most likely look into these comments if some part of it is not working?!

        (0) 

Leave a Reply