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

com.cedarsoftware.util.UrlInvocationHandler Maven / Gradle / Ivy

There is a newer version: 3.5.0
Show newest version
package com.cedarsoftware.util;

import com.cedarsoftware.util.io.JsonReader;
import com.cedarsoftware.util.io.JsonWriter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * Useful utility for allowing Java code to make Ajax calls, yet the Java code
 * can make these calls via Dynamic Proxies created from Java interfaces for
 * the remote server(s).
 *
 * Example:
 *
 * Assume you have a tomcat instance running a JSON Command Servlet, like com.cedarsoftware's or
 * Spring MVC.
 *
 * Assume you have a Java interface 'Explorer' that is mapped to a Java bean that you are allowing
 * to be called through RESTful JSON calls (Ajax / XHR).
 *
 * Explorer has methods on it, like getFiles(userId), etc.
 *
 * You need to use a SessionAware (JSESSIONID only) or CookieAware UrlInvocationHandler to interact
 * with the server so that the cookies will be placed on all requests.  In Javascript within browsers,
 * this is taken care of for you.  Not so in the Java side.
 * 
 * Map cookies = new HashMap();
 * String url = "http://www.mycompany.com:80/json/"
 * InvocationHandler handler = new CookieAwareUrlInvocationHandler(new URL(url), cookies);
 *  // This will handle all cookies, or you could use (where 'sessionId' holds the value of the JSESSIONID
 * InvocationHandler handler = new SessionAwareUrlInvocationHandler(new URL(url), sessionId);
 *
 * Explorer explorer = (Explorer) ProxyFactory.create(Explorer.class, handler);
 *
 * At this point, your Java code can do this:
 *
 * List files = explorer.getFiles(userId);
 * 
* * @author John DeRegnaucourt ([email protected]) & Ken Partlow ([email protected]) *
* Copyright (c) Cedar Software LLC *

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ public class UrlInvocationHandler implements InvocationHandler { private final URL _url; public static int SLEEP_TIME = 5000; public static int RETRY_ATTEMPTS = 20; private static final Log LOG = LogFactory.getLog(UrlInvocationHandler.class); public UrlInvocationHandler(URL url) { _url = url; } public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { int retry = RETRY_ATTEMPTS; while (retry > 0) { HttpURLConnection c = null; try { c = (HttpURLConnection) UrlUtilities.getConnection(_url, true, true, false); c.setRequestMethod("POST"); setCookies(c); // Formulate the JSON call as a String ByteArrayOutputStream ba_out = new ByteArrayOutputStream(); JsonWriter jwr = new JsonWriter(ba_out); jwr.write(new Object[] {m.getName(), args}); IOUtilities.close(jwr); if (LOG.isDebugEnabled()) { // DEBUG String jsonCall = new String(ba_out.toByteArray(), "UTF-8"); LOG.debug("Calling MOD server:\n " + jsonCall); } c.setRequestProperty("Content-Length", String.valueOf(ba_out.size())); OutputStream out = c.getOutputStream(); ba_out.writeTo(out); IOUtilities.close(out); getCookies(c); // Get the return value of the call JsonReader reader; if (LOG.isDebugEnabled()) { ByteArrayOutputStream input = new ByteArrayOutputStream(32768); IOUtilities.transfer(IOUtilities.getInputStream(c), input); byte[] bytes = input.toByteArray(); String jsonResp = new String(bytes, "UTF-8"); LOG.debug(jsonResp); reader = new JsonReader(new ByteArrayInputStream(bytes)); } else { reader = new JsonReader(IOUtilities.getInputStream(c)); } Object[] res = (Object[]) reader.readObject(); // Do we need to close reader? Don't want to stop http keep alives. reader.close(); Object result = res[0]; checkForThrowable(result); return result; } catch (ThreadDeath e) { throw e; } catch (Throwable e) { LOG.error("Error occurred getting HTTP response from server", e); UrlUtilities.readErrorResponse(c); Thread.sleep(SLEEP_TIME); retry--; } finally { UrlUtilities.disconnect(c); } } return null; } protected static void checkForThrowable(Object object) throws Throwable { if (object instanceof Throwable) { Throwable t; if (object instanceof InvocationTargetException) { InvocationTargetException i = (InvocationTargetException) object; t = i.getTargetException(); if (t == null) { t = (Throwable) object; } } else { t = (Throwable) object; } t.fillInStackTrace(); throw t; } } protected void getCookies(URLConnection c) throws IOException { } protected void setCookies(URLConnection conn) throws IOException { } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy