Костыли для апплетов

Рубрика: Java, JavaScript/Ajax | 9 September 2008, 09:54 | juriy

Вам приходилось слышать в адрес апплетов выражение: “dead man walking”? Апплеты – часть Java платформы, задуманная, как мощнейшее средство, позволяющее проинтегрировать Java прямо в web страницу, практически полностью теряющее свои достоинства из-за тонн ограничений, которые на них возложены.
Последние несколько дней я бился над вопросом: как заставить апплет “выглянуть в мир”, за параноидальным прокси моего офиса.

[UPDATED]
Проблему, вроде бы, решил. Удивительная штука. Проблема возникала при использовании HTTP Client из Commons. Обычный URLConnection работает отлично. Ладно уж, решение, описанное ниже можно изпользовать для более интересных задач.

Основное разочарование, которое меня ожидало: вопреки настройкам Java Plugin упорно не хотел использовать настройки прокси из браузера и нахально ломился напрямую (естественно, получая по рукам).
Вторая проблема, даже если дать пользователю возможность самостоятельно ввести настройки прокси (что далеко не каждый типичный пользователь сможет сделать), необходимо также “попросить” пользователя ввести логин-пароль для авторизации. Зачастую пароль совпадает с паролем XP-account’а пользователя, а эту информацию даже очень дружественному апплету даст не каждый.

Решение, которое я нашел, это “костыли” для апплета. Если апплету так тяжело послать примитивный HTTP запрос на хост, с которого он сам загружен, надо поручить эту работу тому, кто с ней нормально справляется: браузеру. Ведь ajax запросы учитывают все настройки прокси, а при помощи LiveConnect из JavaScript можно вызывать публичные методы апплета.
На самом деле, и из апплета можно вызывать функции JavaScript, но по заверениям форумчан эта функциональность иногда не работает.

Самое простое решение, которое я смог придумать: JavaScript периодически опрашивает апплет: не хочет ли тот послать какой-нибудь запрос. Текст запроса апплет возвращает в некотором публичном методе. Если запрос не пустой, JavaScript посылает асинхронный запрос к серверу (Ajax), передавая текст запроса из апплета прямо на сервер. Когда от сервера приходит ответ, JavaScript передает его назад апплету. Таким образом, JavaScript с Ajax запросами выступает в качестве шины для асинхронного обмена сообщениями.

Вот код JavaScript’а:

// Every 5 seconds poll applet for request
var executer = new PeriodicalExecuter(poll, 5);

// That's the method that actually polls applet
function poll() {
	var applet = document.getElementById('tstapp');

	// get() is a public method of applet
	var request = applet.get();

	// If there's some request from applet - send it to server
	if (request.length > 0)
		sendRequest('http://someserver.org/script.php', request);
}

// I use prototype.js to do all Ajax-related stuff for me
function sendRequest(url, data) {
		var myAjax = new Ajax.Request(
		url,
		{method: 'post', parameters: data, onComplete: ajaxResponse}
	);
}

// This is a callback method invoked when response from
// server is ready. Just passes result to applet
function ajaxResponse(originalRequest) {
	passResponse(originalRequest.responseText);
}

// Pass response back to applet
function passResponse(resp) {
	var applet = document.getElementById('tstapp');
	applet.put(resp);
}

Апплет тоже довольно примитивный:

public class TestApp3 extends JApplet {

	private JTextField textField;

	public void init() {
		textField = new JTextField();
		textField.setText("nothing yet");
		add(textField);
	}

	public String get() {
		return "request text";
	}

	public void put(String response) {
		textField.setText(response);
	}
}

Естественно, для использования этого способа в реальном мире, необходимо сделать несколько дополнений. К примеру, корректно обработать ситуацию, когда апплет не успевает загрузиться за первые 5 секунд жизни страницы.

Я еще не опробовал этот метод на реальном проекте, но выглядит конструкция вполне жизнеспособно. Я протестировал связь JavaScript/апплет под FF, IE и Safari (спасибо Farcaller и его MacOS) везде работает нормально.

Как всегда оказалось, что идея связать Ajax и апплет пришла не мне первому в голову. Вот ссылочка на демку, которая использует эту связку для сохранения данных страницы на клиенте.

Комментариев: 4

4 Responses to “Костыли для апплетов”

Комментарии:

  1. Illya Kysil

    Есть одно “но” – привязка настроек прокси идёт к браузеру по умолчанию, а не к браузеру, в котором открывается страница.

    Кроме того, по разному обрабатывается галочка “Use the same proxy server for all protocols” из диалога Proxy Setting в Internet Options. HTTP Client из Commons считает, что если прокси один для всех (галочка установлена), то для создания TCP/IP соединения нужно ломится к Socks proxy. А вот URLConnection так не считает.

  2. Farcaller

    ага, так вот зачем это все было нужно :)

  3. juriy

    Илья, спасибо что объяснил. Потому что этот нюанс довольно сильно попортил нервы.

    Что касается “нюанса”: у большинства пользователей браузер по умолчанию настроен нормально. А аудитория, которая умеет держать браузеры не-по-умолчанию, да еще и ходить через разные прокси, сможет плагин под себя настроить. Хотя, согласен, неприятно.

    Интересно, неужели есть какие-то технические сложности, которые мешают реализовать этот функционал по-человечески?

  4. nikolay

    Добрый день.
    Смотрел, какие свойства есть у класса System в апплете (System.getProperties()), и обнаружил, что есть такое:
    http=proxy.XXXXsoft.com:3128,https=proxy.XXXXsoft.com:3128,ftp=proxy.XXXXsoft.com:3128,gopher=proxy.XXXXsoft.com:3128
    (и еще свойство “javaplugin.proxy.config.bypass” с исключениями)
    т.е. то, что в настройках браузера про настройки прокси и прописано! (в ФФ3 это так).

Leave a Reply