0

I am trying to embed the latest Jetty in android. But it is not working.

I am trying to make Jetty listen to a custom incoming HTTP method, NOTIFY. It works in desktop, now I am trying to import it to Andoird

Here is my code.

package com.example.arjun.hellotest;

import android.util.Log;

import java.io.IOException;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

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

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;

public class HelloWorld extends AbstractHandler
{
    @Override
    public void handle( String target,
                        Request baseRequest,
                        HttpServletRequest request,
                        HttpServletResponse response ) throws IOException,
                                                      ServletException
    {
        // Declare response encoding and types
        response.setContentType("text/html; charset=utf-8");

        // Declare response status code
        response.setStatus(HttpServletResponse.SC_OK);

        // Write back response
        response.getWriter().println("<h1>Hello World</h1>");

        // Inform jetty that this request has now been handled
        baseRequest.setHandled(true);

        String requestMethod = baseRequest.getMethod().toUpperCase();

        StringBuffer jb = new StringBuffer();
        String line = null;

        Map<String, String> map = new HashMap<String, String>();

        try {

            switch (requestMethod) {

                case "POST":
                    // do post logic
                    Log.w("JettyTest", "Handle POST request");
                    break;

                case "NOTIFY":
                    // do notify logic
                    Log.w("JettyTest", "Handle NOTIFY request");

                    Enumeration headerNames = request.getHeaderNames();
                    while (headerNames.hasMoreElements()) {
                        String key = (String) headerNames.nextElement();
                        String value = request.getHeader(key);                        
                        map.put(key, value);

                    }                 

                    for (String key : map.keySet()) {
                        Log.w("JettyTest", key + ": " + map.get(key));
                    }

                    Log.w("JettyTest", "Remote: "+request.getRemoteHost()+":"+request.getRemotePort());

                    BufferedReader reader = request.getReader();
                    while ((line = reader.readLine()) != null)
                        jb.append(line);

                    Log.w("JettyTest", jb.toString());
                    break;

                case "GET":
                    // do get logic
                    Log.w("JettyTest", "Handle GET request");
                    break;

                // so on.....

                default:
                    // do default
                    Log.w("JettyTest", "NOT IMPLEMENTED");

            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main( String[] args ) throws Exception
    {
        Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Server server = new Server(8082);
            try {
                server.getConnectors()[0].getConnectionFactory(HttpConnectionFactory.class);
                server.setHandler(new HelloWorld());

                server.start();
                Log.w("JettyTest", "Server Started");
                server.join();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        };
        new Thread(runnable).start();
    }
}

I am getting 1 error

  1. Error:Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'.

    java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex

(I went through this SO but I still get the same error after following every suggestion)


In AndroidManifest file

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

In my buildgradel file

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.example.arjun.hellotest"
        minSdkVersion 22
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
repositories {
    mavenCentral()
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    implementation 'com.android.support:design:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    implementation files('libs/jetty-all-uber.jar')
}
arjun
  • 1,594
  • 16
  • 33
  • 1
    Don't know about your specific issue with dex, but [`jetty-all-uber.jar` is not valid for use as a dependency in other projects](https://dev.eclipse.org/mhonarc/lists/jetty-users/msg06030.html). – Joakim Erdfelt Feb 13 '18 at 16:57
  • Now what can I do? Is it possible to include Jetty for this task? Or else how to achieve this task? – arjun Feb 13 '18 at 18:59
  • 1
    The Jetty recommended way is to use the various jetty artifacts from `central.maven.org` (including referenced transient dependencies). Your gradle build should support that usage. - https://stackoverflow.com/questions/16671277/maven-dependencies-with-android-studio-gradle – Joakim Erdfelt Feb 13 '18 at 19:05
  • I found this - https://github.com/youten/JettyOnAndroid. I will try to follow what they have written. – arjun Feb 13 '18 at 19:10
  • 1
    [Jetty 8.x is EOL (End of Life)](https://dev.eclipse.org/mhonarc/lists/jetty-announce/msg00069.html) and not recommended for use. (especially with SSL/TLS) – Joakim Erdfelt Feb 13 '18 at 19:12
  • I used [9.0.0.v20130308](http://central.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.0.0.v20130308/) because extremely new versions gives the same dex error. But this version it builds. But now nothing happens in the app. I can't verify if the server is started. There is nothing in adb log. I have a default untouched MainActivity file generated while building the project and this `HelloWorld.java` file in the same folder. Am I doing it right? – arjun Feb 13 '18 at 19:52
  • This is out of scope for stackoverflow now. (There is no answer, and the problem is larger then is suitable for a question/answer). Please use the jetty-users mailing list for help (you'll find many folks that have done this already there) – Joakim Erdfelt Feb 13 '18 at 19:58

0 Answers0