How to develop or change stuff in GraphHopper and use IDE features like debugging etc?

This question was asked elsewhere and I’ll answer it here for all:

There are different ways to achieve this :slight_smile:

  1. If you want at some point that your changes should be merged into the GraphHopper mainline, then just create a separate branch and start GraphHopper Web via GHServer
  2. If you want to keep certain things separated but reuse the complete GraphHopper JSON API etc then use GHServer in your custom server class and start it with customized settings or guice modules. See attached **
  3. Or use the Java API to integrate GraphHopper core directly in your Java application as explained in the docs

For all these procedures you can use the config.properties to modify certain aspects of GraphHopper, the command line arguments, the GraphHopper Java API or a mixture of all. Where the command line arguments overwrite the config.properties and if graphHopper.init is called as first method then the Java API overwrites everything else.

The command line arguments and properties in config.properties are identically named e.g. the following command line arguments I hand over to GHServer and set/overwrite certain properties to start the area monaco at port 8989:

jetty.port=8989 config=../config.properties osmreader.osm=../core/files/monaco.osm.gz

**

public class MyServer {

    // execute via
    // java -jar target/your-project-0.1-jar-with-dependencies.jar osmreader.osm=berlin.pbf graph.location=/somewhere/graph
    public static void main(String[] args) throws Exception {
        CmdArgs tmpArgs = CmdArgs.readFromConfigAndMerge(CmdArgs.read(args), "config", "graphhopper.config");
        System.out.println(tmpArgs.toString());
        new MyServer(tmpArgs).start();
    }
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final CmdArgs cmdArgs;
    private GHServer server;

    public MyServer(CmdArgs args) {
        this.cmdArgs = args;
    }

    /**
     * Starts 'pure' GraphHopper server with the specified injector
     */
    public void start(Injector injector) throws Exception {
        server = new GHServer(cmdArgs);
        server.start(injector);
        logger.info("Memory utilization:" + Helper.getMemInfo() + ", " + cmdArgs.get("graph.flagEncoders", ""));
    }

    /**
     * Starts GraphHopper server with routing and custom module features.
     */
    public void start() throws Exception {
        Injector injector = Guice.createInjector(createModule());
        start(injector);
    }

    protected Module createModule() {
        return new AbstractModule() {
            @Override
            protected void configure() {
                binder().requireExplicitBindings();

                install(new MyDefaultGuiceModule(cmdArgs));
                install(new MyServletGuiceModule(cmdArgs));

                bind(GuiceFilter.class);
            }
        };
    }

    public void stop() {
        if (server != null) {
            server.stop();
        }
    }
}

Hi Peter,

I just tried to run my current graphhopper setup. However, I was not able to run the MyServer Class from within IntelliJ. I get the following Error while make:
Error:Android Pre Dex: [graphhopper-parent] Android SDK is not specified

Do I really need to get the Android SDK to make the project?

I configured my IntelliJ like:

Main Class: com.graphhopper.http.MyServer
VM Options: -Xmx1000m -Xms1000m -server
Program arguments: jetty.port=8989  config=config.properties osmreader.osm=baden-wuerttemberg-latest.osm.pbf
Working Directory: /$myUserDir/graphhopper
Classpath of Module: graphhopper-web

Best,
Robin

Do I really need to get the Android SDK to make the project?

no

If you use the ‘MyServer’-approach you use it in a separate project and just include ‘core’ and ‘web’ via maven or gradle without the ‘android’ module.

But even if you do this within GraphHopper itself, the maven build does not include ‘android’ by default (see the pom.xml), but I’m not sure what is going wrong here, as I’m a NetBeans user myself. So just assume that GraphHopper is an external project and set the dependencies like you would do for such projects.

I think, that I was looking for this instruction, but I am not sure. I want to reuse many parts of Graphhopper, especially of the web plugin, but i want to add some JavaScript-Code, change the index.html and furthermore later some Flagencoder. Is this possible with Way 2 and how can i override those paths/files (index.html, main.js)?

It is partly possible. You cannot really overwrite the UI stuff. Instead you specific the ‘jetty.resourcebase’ parameter to point to a completely different copy of it:

resHandler.setResourceBase(args.get("jetty.resourcebase", "./src/main/webapp"));

Let me know of any plugging mechanism to make the JS stuff more extendable.

I will try that out.
I’ve created my own project with setting the depency to com.graphhopper.
At the moment i have some problem with setting the depency in pom.xml (working with IntelliJ IDEA 2016)
<dependencies> <dependency> <groupId>com.graphhopper</groupId> <artifactId>graphhopper</artifactId> <version>0.6.0</version> </dependency>

I inserted this code before the closing in my pom.xml.
Now i recieve the following error:

I solved this problem by adding the jarfile to the library of my project.

Now i have another problem. I wanted to add my own FlagEncoder, outside Graphhopper.
The problem i have is, that factor inside EncodedValue has protected acces.
I recieve this error:

[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.3:compile (default-compile) on project custom: Compilation failure
[ERROR] [path]/MyFlagEncoder.java:[275,32] error: factor has protected access in EncodedValue