All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xpatterns.spark.core.java.SparkJobRestClient Maven / Gradle / Ivy

package com.xpatterns.spark.core.java;

import com.google.gson.Gson;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Map;


/**
 * Created by radum on 10.04.2014.
 */

public abstract class SparkJobRestClient {
    public static final String VERSION = "3.0";
    public static final String SPARK_UI_PORT = "sparkUiPort";
    private String serverURI;
    public final SimpleDateFormat CUSTOM_DATE = new SimpleDateFormat("\"yyyy-MM-dd HH:mm:ss\"");


    public SparkJobRestClient(String uri) {
        this.serverURI = uri;
    }

    public String getServerURI() {
        return serverURI;
    }

    public abstract void writeInfo(String info);

    public abstract void writeError(String error);

    protected abstract String getXPatternsSjsBridgeClassPath();


    public String launchJob(String input, String contextName, Boolean sync) throws Exception {

        if (checkContextExist(contextName)) {
            writeInfo("Launching Job on existing context <" + contextName + ">");
        } else {
            throw new RuntimeException("Job Context <" + contextName + "> does not exist!");
        }
        HttpClient httpclient = HttpClients.createDefault();


        String uri = String.format("%s/jobs?runningClass=%s&contextName=%s", getServerURI(), getXPatternsSjsBridgeClassPath(), contextName);
        writeInfo("Launching Job URI: " + uri);

        HttpPost httpPost = new HttpPost(uri);
        httpPost.setEntity(new StringEntity(input));

        HttpResponse response = httpclient.execute(httpPost);


        validateResponseURI(response, uri);

        String requestResult = EntityUtils.toString(response.getEntity());
        Map values = new Gson().fromJson(requestResult, Map.class);


        if (requestResult.contains("ERROR")) {
            writeError("RequestResult: " + requestResult);
            throw new RuntimeException(requestResult);
        }


        writeInfo("Job [" + values.get("jobId") + "] launched successfully, starting execution");

        return (String) values.get("jobId");
    }

    private boolean checkHttpResponse(HttpResponse response) throws Exception {

        HttpEntity entity = response.getEntity();
        int statusCode = response.getStatusLine().getStatusCode();

        String logPrefix = "SparkJobRestClient->checkHttpResponse";

        if (entity == null) {
            writeInfo("SparkJobRestClient->checkHttpResponse->Http entity response is null!");
        }

        if (200 != statusCode && 202 != statusCode) {
            throw new RuntimeException(logPrefix + "Http Response [Status: FAILED]!!!\nStatusCode:" + statusCode + "\nErrorMessage: " + getHttpResponseEntityAsString(response));
        }

        return true;
    }

    // ATTENTION if the stream is consumed twice U should expect java.io.IOException: Attempted read from closed stream
    private String getHttpResponseEntityAsString(HttpResponse response) {
        String responseString = "";

        try {
            responseString = EntityUtils.toString(response.getEntity(), "UTF-8");
        } catch (IOException e) {
            throw new RuntimeException("HttpResponse->getHttpResponseEntityAsString was called twice!!! Avoid that!: " + e);
        }

        //writeInfo("HttpResponse->Entity content: " + responseString);
        return responseString;
    }


    private boolean validateResponseURI(HttpResponse response, String uri) throws Exception {
        int statusCode = response.getStatusLine().getStatusCode();
        final String message = "SparkJobRestClient->HttpResponse->checkHttpResponse->statusCode: " + statusCode;
        if (200 != statusCode && 202 != statusCode) {
            throw new RuntimeException("Response FAILED!!!" + message + "***URI***" + uri + "---statusResponse---" + response.getStatusLine().getReasonPhrase());
        }

        return true;
    }


    public void deleteContext(String contextName) throws Exception {
        // check if context exists before deletion
        if (checkContextExist(contextName)) {
            HttpClient httpclient = HttpClients.createDefault();
            String uri = String.format("%s/contexts/%s", getServerURI(), contextName);

            HttpDelete httpDelete = new HttpDelete(uri);

            int retryTimes = 1;
            boolean validateDeleteResponse = false;
            while (retryTimes <= 5 && validateDeleteResponse == false) {
                try {
                    HttpResponse response = httpclient.execute(httpDelete);
                    checkHttpResponse(response);
                    writeInfo(EntityUtils.toString(response.getEntity()));
                    validateDeleteResponse = true;
                    writeInfo("Context " + contextName + " deleted!");
                } catch (Exception ex) {
                    ex.printStackTrace();
                    writeError(ex.getMessage() + "\n Retry count: " + retryTimes);
                    retryTimes++;
                }
            }
        } else {
            writeInfo("Context <" + contextName + "> doesn't exist!");
        }
        Thread.sleep(5000);

    }

    public boolean checkContextExist(String contextName) throws Exception {

        HttpClient httpclient = HttpClients.createDefault();
        String uri = String.format("%s/contexts/%s", getServerURI(), contextName);

        HttpGet httpGet = new HttpGet(uri);

        HttpResponse response = httpclient.execute(httpGet);

        boolean result = 400 == response.getStatusLine().getStatusCode() ? false : true;
        return result;
    }

    public void createApp(String appName, String resourcePath) throws Exception {
        HttpClient httpclient = HttpClients.createDefault();
        String uri = String.format("%s/jars/%s", getServerURI(), appName);

        HttpPost httpPost = new HttpPost(uri);
        FileEntity fileEntity = new FileEntity(new File(resourcePath), "binary/octet-stream");
        httpPost.setEntity(fileEntity);

        HttpResponse response = httpclient.execute(httpPost);
        checkHttpResponse(response);
        writeInfo(EntityUtils.toString(response.getEntity()));
    }

    public String getJobStatus(String jobId, String contextName) throws Exception {
        HttpClient httpclient = HttpClients.createDefault();
        String uri = String.format("%s/jobs/%s?contextName=%s", getServerURI(), jobId, contextName);
        HttpGet httpGet = new HttpGet(uri);

        HttpResponse response = httpclient.execute(httpGet);
        checkHttpResponse(response);

        String requestResponse = EntityUtils.toString(response.getEntity());
        Map values = new Gson().fromJson(requestResponse, Map.class);

        return values == null ? "Status is not retrieved!!!" : (String) values.get("status");

    }

    public Integer createContext(String contextName, HashSet parameters, int postCreationWaitTime) throws Exception {
        writeInfo("Context <" + contextName + "> will be created");
        boolean resultResponse = false;
        HttpResponse response = null;

        HttpClient httpclient = HttpClients.createDefault();
        String uri = String.format("%s/contexts/%s",
                getServerURI(), contextName);

        writeInfo("Context URI: " + uri);

        String finalParameters = "";
        for (String entry : parameters) {
            finalParameters += entry + "\n";
        }
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setEntity(new StringEntity(finalParameters));
        try {
            response = httpclient.execute(httpPost);
            resultResponse = checkHttpResponse(response);

        } catch (RuntimeException e) {
            //this comes only from validationResponse line!!!
            throw new RuntimeException("Context <" + contextName + "> was NOT created! Caused by..." + e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException("Context <" + contextName + "> was NOT created! Caused by..." + getHttpResponseEntityAsString(response));
        }

        if (resultResponse) {

            String responseAsString = getHttpResponseEntityAsString(response);

            Map values = new Gson().fromJson(responseAsString, Map.class);

            String sparkUiPort = values.get(SPARK_UI_PORT);
            if (values != null && sparkUiPort != null)
                return Integer.valueOf(sparkUiPort);
        } else {
            throw new RuntimeException("Context creation failed!");
        }

        return -1;
    }

    //Hadoop Configuration
    public void uploadFileToHDFS(String path, byte[] bytes, String hdfsHost, String hdfsUser) throws IOException {
        Configuration conf = getHadoopConf(hdfsHost, hdfsUser);
        FileSystem fs = FileSystem.get(conf);
        FSDataOutputStream output = fs.create(new Path(path));
        output.write(bytes);
        output.close();
    }

    public Configuration getHadoopConf(String hdfsHost, String hdfsUser) {

        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://" + hdfsHost + ":8020");

        conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
        conf.set("hadoop.job.ugi", hdfsUser);

        return conf;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy