IBM®
Перейти к тексту
    в России и странах СНГ [изменить]    Условия использования
 
 
   
    Главная страница    Продукты    Услуги и решения    Поддержка и загрузка    Мой профиль    
Перейти к тексту

developerWorks Россия  >  XML | Технология Java | Open source  >

Знакомство с протоколом публикации Atom, Часть 3: Введение в проект Apache Abdera

Создание приложений с поддержкой Atom при помощи Abdera, нового проекта с открытым исходным кодом

developerWorks
Опции документа

Опции документа, требующие включения JavaScript, не отображаются

Обсудить

Исходные тексты примера


Выскажите мнение об этой странице

Помогите нам улучшить содержание


Уровень сложности: средний

Джеймс Снелл, разработчик программного обеспечения, IBM

23.04.2007

В предыдущих статьях данной серии представлен обзор протокола публикации Atom и описаны различные варианты его применения в практических приложениях. Настоящая статья показывает, каким образом Вы можете реализовать приложения с поддержкой Atom, используя новый проект с открытым исходным кодом, называемый Abdera, который в настоящее время разрабатывается фондом Apache Software Foundation.

Данное исследование предполагает, что Вы уже знакомы со спецификацией формата Atom и имеете общее представление о синдикации (в разделе Ресурсы предоставлены необходимые ссылки). Все приведенные примеры написаны на Java, а пример проекта Eclipse, содержащий все примеры кодов, доступен для загрузки.

Начало работы

Перед тем, как Вы начнете работать, убедитесь, что у Вас установлена последняя версия Apache Abdera. Загрузить ее можно из хранилища промежуточных версий Apache на hhttp://svn.apache.org/repos/asf/incubator/abdera/java/branches/0.2.1-incubating/. Перед загрузкой убедитесь, что у Вас есть клиент промежуточной версии и отдайте команду:

> svn co http://svn.apache.org/repos/asf/incubator/abdera/java/branches/0.2.1-incubating/

Загрузив исходный образ, Вы можете скомпоновать Abdera, используя Ant версии 1.6.5 или выше.

> cd trunk
> ant -f build/build.xml dist

По завершению компоновки, скомпилированные jar-файлы и зависимости располагаются во вновь созданной директории "dist". Для запуска примеров в Вашем classpath должны быть следующие jar-файлы. Обратите внимание, что не для всех примеров необходимы все jar-файлы, перечисленные в перечне зависимостей:

Таблица 1. Jar-файлы, необходимые для запуска примеров
Abdera (dist)Зависимости (dist/lib)
  • abdera.client.0.2.0-incubating.jar
  • abdera.core.0.2.0-incubating.jar
  • abdera.parser.0.2.0-incubating.jar
  • abdera.protocol.0.2.0-incubating.jar
  • axiom-api-1.0.jar
  • axiom-impl-1.0.jar
  • commons-codec-1.3.jar
  • commons-httpclient-3.0.1.jar
  • commons-logging-1.0.4.jar
  • geronimo-activation_1.0.2_spec-1.1.jar
  • log4j-1.2.12.jar
  • stax-1.1.2-dev.jar
  • stax-api-1.0.jar
  • jaxen-1.1-beta-7.jar

Начало работы

Проект Abdera состоит из набора отдельных модулей, которые указаны приведенной ниже таблице в алфавитном порядке. Наиболее важными и часто используемыми модулями являются парсер, зависимости и ядро:

Таблица 2. Модули проекта Apache Abdera
МодульОписаниеЗависимости
Сборка Сборка Ant для целого проектаApache Ant 1.6.5+
клиентКлиент протокола публикации Atom ядро, парсер, протокол, commons-codec-1.3.jar, commons-httpclient-3.0.1.jar
ядроИнтерфейсы объектной модели ленты Оболочка активации Java (Java Activation Framework)
зависимостиТиповые зависимости для всех модулей  
расширенияРасширения протокола и синтаксиса лентыядро, протокол, json-1.0.jar
парсерStAX и основанная на Axiom реализация объектной модели ленты (FOM) ядро, axiom-api-1.0.jar, axiom-impl-1.0.jar, stax-1.1.2-dev.jar, stax-api-1.0.jar, jaxen-1.1-beta-7.jar, commons-logging-1.0.4.jar, log4j-1.2.12.jar, wstx-asl-2.0.5.jar
протоколСтандартный код протокола публикации Atom ядро, парсер
безопасностьПоддержка шифрования и цифровой подписи XML ядро, парсер, xmlsec-1.3.0.jar, реализация Bouncy Castle JCE
серверРеализация сервера протокола публикации Atom ядро, парсер, протокол, сервлет API

Базовый модуль (ядро), пакеты которого перечислены в нижеследующей таблице, определяет то, что Abdera вызывает "объектную модель ленты (Feed Object Model)", набор интерфейсов, применяемых для парсинга, создания и оперирования документами, который был смоделирован согласно спецификации формата синдикации Atom:

Таблица 3. Пакеты "базового" модуля (ядра) Abdera
ПакетОписание
org.apache.abderaГлавный пакет, содержащий один объект "Abdera"
org.apache.abdera.factoryОпределяет интерфейс Factory, создающий новые экземпляры объектов объектной модели ленты (Feed Object Model)
org.apache.abdera.filterОпределяет интерфейсы для фильтрации документов Atom во время парсинга
org.apache.abdera.modelОпределяет основные интерфейсы для работы с лентами и входными документами. Модель также поддерживает работу с типовыми и служебными документами протокола публикации Atom.
org.apache.abdera.parserОпределяет интерфейс Parser, который создает новые экземпляры объектов объектной модели ленты из XML-документов
org.apache.abdera.utilПредоставляет набор служебных классов, в первую очередь предназначенных для разработчиков, желающих расширить или заменить заводские реализации и парсер Abdera предоставляемый по умолчанию
org.apache.abdera.writerОпределяет интерфейсы Writer, применяемые для сериализации экземпляров объектов объектной модели ленты
org.apache.abdera.xpathОпределяет интерфейсы для использования XPath для перемещения по объектной модели ленты

После загрузки и компоновки исходника Abdera, при необходимости потратьте немного времени на знакомство с API и просмотрите документацию Javadoc, сгенерированную компоновкой (располагается в созданной директории $ABDERA_HOME/dist/docs).

Создание сообщений и лент

Две основные функции объектной модели ленты Abdera призваны облегчить и создание, и использование лент и входных документов Atom.

Создание документа Atom начинается с получения экземпляра org.apache.abdera.factory.Factory и задания значений ленты или сообщения. В листинге 1 показано создание простого входного документа Atom:


Листинг 1. Создание простого входного документа Atom
                
Abdera abdera = new Abdera();
Factory factory = abdera.getFactory();
    
Entry entry = factory.newEntry();
entry.setId("http://example.org/foo/entry");
entry.setUpdated(new java.util.Date());
entry.setTitle("This is an entry");
entry.setContentAsXhtml("This <b>is</b> <i>markup</i>");
entry.addAuthor("James");
entry.addLink("http://www.example.org");
    
entry.writeTo(System.out);
    

Данный пример отражает все ключевые особенности объектной модели ленты.

  • Сначала Вы создаете экземпляр org.apache.abdera.Abdera, который предоставляет точку входа верхнего уровня для инициализации и обращения к различным ключевым подкомпонентам, например, Abdera Factory и Parser.
  • Затем Вы получаете экземпляр org.apache.abdera.factory.Factory, представляющий собой интерфейс, который загружает создание всех объектов объектной модели ленты.
  • Далее, используя Factory, Вы создаете новый экземпляр org.apache.abdera.model.Entry. Двумя наиболее часто применяемыми методами в интерфейсе Factory являются методы newEntry() и newFeed().
  • И наконец, используя предоставляемый по умолчанию редактор Abdera, Вы сериализуете документ Atom в OutputStream.

Результат листинга 1 показан в листинге 2. Обратите внимание, что объявление областей имен, форматов даты и правильная сериализация элементов atom:content управляется реализацией объектной модели ленты автоматически. Однако сериализованный результат не легко прочитать из-за отсутствия переносов строк и отступов:


Листинг 2. Созданный входной документ Atom
                
<entry xmlns="http://www.w3.org/2005/Atom"><id>http://example.org/foo/entry</id><updated>
2006-09-04T19:27:01.068Z</updated><title type="text">This is an entry</title><content
type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">This <b>is</b> 
<i>markup</i></div></content>
<author><name>James</name></author><link href="http://www.example.org"/></entry>
    

Сериализация без пробелов и переносов строк - это результат оптимизации рассчитанной на более эффективную передачу документов. Как вариант, для добавления переносов строк и отступов, Вы можете использовать редактор prettyxml:


Листинг 3. Сериализация с помощью редактора prettyxml
                
Writer writer = abdera.getWriterFactory().getWriter("prettyxml");
writer.writeTo(entry, System.out);    
    

В этом случае результат будет более приятен для глаз:


Листинг 4. Красивый выходной документ XML
                
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>http://example.org/foo/entry</id>
  <updated>2006-09-04T19:28:58.237Z</updated>
  <title type="text">This is an entry</title>
  <content type="xhtml">
    <div xmlns="http://www.w3.org/1999/xhtml">This <b>is</b> <i>markup</i></div>
  </content>
  <author>
    <name>James</name>
  </author>
  <link href="http://www.example.org"/>
</entry>
    

Однако следует очень аккуратно использовать редактор prettyxml, так как это может привести к появлению побочных эффектов. Например, применение редактора для сериализации лент и входных документов Atom, содержащих цифровую подпись XML, может привести к тому, что подпись станет недействительной.

В листинге 5 показано создание документа ленты Atom. Как и ожидалось, данный процесс аналогичен созданию входного документа Atom:


Листинг 5. Создание простого документа ленты Atom
                
Abdera abdera = new Abdera();
Factory factory = abdera.getFactory();
    
Feed feed = factory.newFeed();
feed.setId("http://example.org/foo");
feed.setUpdated(new java.util.Date());
feed.setTitle("This is a feed");
feed.addLink("http://www.example.org");
feed.addLink("http://www.example.org/foo", "self");
    
Entry entry = factory.newEntry();
entry.setId("http://example.org/foo/entry");
entry.setUpdated(new java.util.Date());
entry.setTitle("This is an entry");
entry.setContentAsXhtml("This <b>is</b> <i>markup</i>");
entry.addAuthor("James");
entry.addLink("http://www.example.org");
    
feed.addEntry(entry);
  
Writer writer = abdera.getWriterFactory().getWriter("prettyxml");
writer.writeTo(feed, System.out);
    


Листинг 6. Созданный документ ленты Atom
                
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://example.org/foo</id>
  <updated>2006-09-04T19:31:45.286Z</updated>
  <title type="text">This is a feed</title>
  <link href="http://www.example.org"/>
  <link href="http://www.example.org/foo" rel="self"/>
  <entry>
    <id>http://example.org/foo/entry</id>
    <updated>2006-09-04T19:31:44.695Z</updated>
    <title type="text">This is an entry</title>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">This <b>is</b>
<i>markup</i></div>
    </content>
    <author>
      <name>James</name>
    </author>
    <link href="http://www.example.org"/>
  </entry>
</feed>
    

Интерфейсы объектной модели Abdera очень точно соответствуют схеме формата синдикации Atom и позволяют разработчикам, знакомым со спецификацией RFC 4287, создавать валидные документы Atom. Однако необходимо подчеркнуть, что реализация не выполняет валидации входной информации. Например, RFC 4287 выдвигает требование, чтобы во всех элементах atom:entry и atom:feed содержался только один элемент atom:id, значением которого является нормализованный IRI. Abdera, однако, не выдает сообщения об исключительной ситуации, если разработчик пытает создать или сериализовать сообщение или ленту, не содержащие atom:id или содержащие несколько элементов atom:id. Вся ответственность за валидность документов ложится на плечи разработчиков. Проверить валидность документов Atom можно при помощи FeedValidator.

Добавление расширений в документы

В объектной модели ленты присутствует возможность работы с расширениями формата Atom, не требующая от разработчиков написания модулей, реализующих данные расширения. Например, в листинге 7 показано как добавить элемент "foo" в область имен "tag:example.org,2006:/namespaces" сообщения. Листинг 8 отображает сериализованный результат:


Листинг 7. Добавление элемента расширения
                
QName extensionQName = 
  new QName("tag:example.org,2006:/namespaces", "foo", "f");
Element element = entry.addExtension(extensionQName);
element.setAttributeValue("foo", "bar");
element.setText("fooBar");
    


Листинг 8. Входной документ с элементом расширения
                
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>http://example.org/foo/entry</id>
  <updated>2006-09-04T19:34:10.322Z</updated>
  <title type="text">This is an entry</title>
  <content type="xhtml">
    <div xmlns="http://www.w3.org/1999/xhtml">This is markup</div>
  </content>
  <author>
    <name>James</name>
  </author>
  <link href="http://www.example.org"/>
  <f:foo xmlns:f="tag:example.org,2006:/namespaces" foo="bar">fooBar</f:foo>
</entry>
    

В листинге 9 показан более практический пример добавления в ленту элементов из Спецификации OpenSearch 1.1:


Листинг 9. Добавление в ленту Atom элементов OpenSearch 1.1
                
final String OSURI = "http://a9.com/-/spec/opensearch/1.1/";
final QName TOTALRESULTS = new QName(OSURI, "totalResults");
final QName STARTINDEX = new QName(OSURI, "startIndex");
final QName ITEMSPERPAGE = new QName(OSURI, "itemsPerPage");
final QName QUERY = new QName(OSURI, "Query");
    
Feed feed = factory.newFeed();    
feed.addExtension(TOTALRESULTS).setText("4230000");
feed.addExtension(STARTINDEX).setText("21");
feed.addExtension(ITEMSPERPAGE).setText("10");
Element query = feed.addExtension(QUERY);
query.setAttributeValue("role", "request");
query.setAttributeValue("searchTerms", "New York History");
query.setAttributeValue("startPage", "1");
    

Гибкость контента

Ключевым отличием формата Atom от других форматов синдикации является поддержка широкого и гибкого диапазона типов контента. Сообщения Atom могут содержать простой текст, устаревающий HTML, правильно построенный XHTML, XML, любые символьно-ориентированные данные и контент, закодированный на основе Base64. В сообщении Atom также присутствует возможность ссылаться на контент при помощи URI. Объектная модель ленты предоставляет простые средства работы с каждым из вариантов. В листингах 10 и 11 показано, как задать контент сообщения в виде простого текста:


Листинг 10. Задание контента в виде простого текста
                
Entry entry = factory.newEntry();
entry.setContent("This <b>is</b> not <i>markup</i>");
    


Листинг 11. Элемент контента в виде простого текста
                
<content type="text">This <b>is</b>not <i>markup</i></content>
    

Необходимо отметить, что при работе с простым текстом (листинг 10) и HTML (листинг 12), элементы сериализованного контента будут почти идентичными (листинги 11 и 13). Очень важно, чтобы обработчик уделял достаточно внимания атрибуту типа контента. При показе контента читателю ленты, простой текст из листинга 11 должен быть представлен как неформатированная текстовая строка "This <b>is</b> not <i>markup</i>", а HTML из листинга 13 должен быть представлен с форматированием: "This is markup".


Листинг 12. Задание контента в HTML
                
Entry entry = factory.newEntry();
entry.setContentAsHtml("This <b>is</b> <i>markup</i>");
    


Листинг 13. Элемент контента в HTML
                
<content type="html">This <b>is</b>
<i>markup</i></content> 
    

Как показано в листинге 14, для издателей ленты предпочтительной альтернативой HTML является использование в своих сообщениях правильно построенных фрагментов XHTML на основе метода setContentAsXhtml входного интерфейса:


Листинг 14. Задание контента в XHTML
                
Entry entry = factory.newEntry();
entry.setContentAsXhtml("This <b>is</b> <i>markup</i>");
    


Листинг 15. Элемент контента в XHTML
                
<content type="xhtml">
  <div xmlns="http://www.w3.org/1999/xhtml">
    This <b>is</b> <i>markup</i>
  </div>
</content>
    

Abdera анализирует входной документ XHTML, переданный методу setContextAsXHTML, с точки зрения правильного построения , но не проверяет валидность XHTML. Аналогичным образом, как показано в листингах 16 и 17, можно задать контент любого правильно построенного сообщения в XML:


Листинг 16. Задание контента в XML
                
Entry entry = factory.newEntry();
entry.setContent("<a><b><c><d>foo</d></c></b></a>", Content.Type.XML);
    


Листинг 17. Элемент контента в XML
                
<content type="application/xml">
  <a>
    <b>
      <c>
        <d>foo</d>
      </c>
    </b>
  </a>
</content>
    

Иногда простой разметки символьного контента, например, type="текста" или type="html" не достаточно. Например, когда сообщение Atom содержит целый HTML-документ. Для type="html", однако, разметка, содержащаяся в элементе контента, должна быть пригодна для нахождения в элементе DIV языка HTML . Как показано в листингах 18 и 19, чтобы включить целый документ, в атрибуте типа должен быть определен мультимедийный тип HTML:


Листинг 18. Использование мультимедийного контента основанного на тексте
                
Entry entry = factory.newEntry();
entry.setContent(
  "<html>
    <head>
      <title>Foo</title>
    </head>
    <body>This is new</body></html>", 
  "text/html");
    


Листинг 19: Элемент мультимедийного контента основанного на тексте
                

<content type="text/html">
<html>
  <head>
    <title>Foo</title>
  </head>
  <body>This is new</body> </html>
</content>

      

Если издатель ленты захочет синдицировать несимвольный контент, то он должен закодировать контент на основе Base64 и использовать атрибут типа контента для указания мультимедийного типа закодированной двоичной информации. Для реализации в Abdera, используйте интерфейс DataHandler оболочки активации Java (Java Activation Framework). Если DataHandler передается как часть контента сообщения, то Abdera автоматически кодирует контент на основе Base64:


Листинг 20. Задание двоичного контента, закодированного на основе Base64
                
Entry entry = factory.newEntry();
URL url = new URL("file:/home/jasnell/mozilla-firefox.png");
URLDataSource ds = new URLDataSource(url);
DataHandler dh = new DataHandler(ds);
entry.setContent(dh);
    


Листинг 21. Элемент контента с информацией, закодированной на основе Base64
                
<content type="image/png">iVBORw0KGgoAAAANSUhEUgAAA...</content>
    

Вследствие естественной неэффективности кодирования Base64 и так как бывают случаи, когда включение контента непосредственно в сообщение не подходит (например, при синдикации потокового воспроизведения аудио или видео), то можно организовать ссылку URI на контент (смотрите листинги 22 и 23):


Листинг 22. Задание атрибута src элементу контента
                
Entry entry = factory.newEntry();
URI uri = new URI("http://example.org");
entry.setContent(uri.toString(), "application/xhtml+xml");
    


Листинг 23. Элемент контента, использующий атрибут src
                
<content type="application/xhtml+xml" src="http://example.org" />
    

Парсинг лент и входных документов

Еще одной основной функцией Abdera является парсинг документов Atom. Процедура начинается с получения экземпляра от Parser и для выполнения парсинга документа передается в InputStream или Reader:


Листинг 24. Парсинг документа ленты Atom
                
Abdera abdera = new Abdera();
Parser parser = abdera.getParser();
URL url = Listing7.class.getResource("/example.xml");
    
Document<Feed> feed_doc = parser.parse(url.openStream());
Feed feed = feed_doc.getRoot();
    

Так как реализация парсера, используемого в Abdera по умолчанию, для парсинга XML применяет модель на основе выталкивания из стека, то вызов метода разбора для объекта Parser использует переданные методу InputStream или Reader не до конца. Поток используется по шагам по мере запроса информации в документе. Как и предполагается, вызов таких методов как, writeTo, clone, и так далее, приводит к полному использованию потока. Данное утверждение может быть ложным только для реализаций интерфейса Parser, задаваемых не по умолчанию.

После того, как документ прошел парсинг, разработчики могут обращаться к контенту ленты либо при помощи методов API объектной модели ленты, либо используя XPath:


Листинг 25. Навигация по объектной модели ленты
                
System.out.println(feed.getBaseUri());
System.out.println(feed.getLanguage());
System.out.println(feed.getId());
System.out.println(feed.getTitle());
System.out.println(feed.getTitleType());
System.out.println(feed.getUpdated());
System.out.println(feed.getAlternateLinkResolvedHref());
System.out.println(feed.getSelfLinkResolvedHref());
    
List<Entry> entries = feed.getEntries();
   
for (Entry entry : entries) {
  
  System.out.println(entry.getId());
  System.out.println(entry.getTitle());
  System.out.println(entry.getTitleType());
  System.out.println(entry.getUpdated());
  System.out.println(entry.getAlternateLinkResolvedHref());
  System.out.println(entry.getEnclosureLinkResolvedHref());
  System.out.println(entry.getContent());
  System.out.println(entry.getContentType());
      
  Element element = entry.getExtension(
    new QName("tag:example.org,2006:/namespaces", "foo"));
  
  System.out.println(element.getText());
  
}
    

Как показано в листинге 26, в качестве альтернативы хождению и вызову различных методов получения объектов сообщений и лент, разработчики могут использовать утверждения XPath для навигации по разобранному документу:


Листинг 26. Навигация по объектной модели ленты при помощи XPath
                
Abdera abdera = new Abdera();
XPath xpath = abdera.getXPath();
    
System.out.println(xpath.valueOf("/a:feed/a:id", feed));
System.out.println(xpath.valueOf("/a:feed/@xml:base", feed));
System.out.println(xpath.valueOf("/a:feed/@xml:lang", feed));
System.out.println(xpath.valueOf("/a:feed/a:title", feed));
System.out.println(xpath.valueOf("/a:feed/a:title/@type", feed));
System.out.println(xpath.valueOf("/a:feed/a:updated", feed));
System.out.println(xpath.valueOf("/a:feed/a:link[not(@rel)]/@href", feed));
System.out.println(xpath.valueOf("/a:feed/a:link[@rel='self']/@href", feed));
    

Помимо возможности выбора отдельных узлов, групп узлов, текста, логических выражений и числовых значений, также поддерживаются стандартные параметры XPath, например функции и оси:


Листинг 27. Использование стандартных функций XPath
                
System.out.println(xpath.valueOf("count(//a:entry)", feed) + " entry");
System.out.println(xpath.valueOf("name(//a:entry/ancestor::*)", feed));
    

Как показано в листинге 28, выбор узлов при помощи XPath возвращает объекты FOM, которые, в свою очередь, можно оценить с помощью XPath. Обратите внимание, что вместо передачи ленты в качестве второго аргумента функции valueOf, как было в предыдущих примерах, передается Div, выбранный из метода selectSingleNode. XPath оценивается относительно того, какой элемент FOM передается методу:


Листинг 28. Оценка утверждений XPath по сравнению с отдельными объектами FOM
                
Div div = (Div) xpath.selectSingleNode(
  "//a:entry/a:content/x:div", feed, namespaces);
System.out.println(xpath.valueOf("namespace-uri()", div));
System.out.println(xpath.valueOf("x:p", div, namespaces));
    

Использование XPath для навигации по документам Abdera предоставляет набор преимуществ тем разработчикам, которые работают с расширениями базового формата. Например, при помощи метода xpath.booleanValueOf можно быстро определить содержится ли определенный элемент расширения в данной ленте или записи. Такой подход является более эффективным по сравнению с хождением по структуре документа при помощи различных итераторов и методов получения.

Еще одной важной особенностью объектной модели ленты является способность применять преобразования XSLT к разобранным документам и элементам, используя стандартные Java API преобразования. Так же как и с поддержкой XPath, преобразования XSLT можно применять к любому разобранному документу:


Листинг 29. Преобразование документов Abdera с помощью XSLT
                
Abdera abdera = new Abdera();
Parser parser = abdera.getParser();
    
URL url = Listing8.class.getResource("/example.xml");
URL xslt = Listing8.class.getResource("/example.xslt");
    
Document<Feed> feed_doc = parser.parse(url.openStream());
Document<Element> xslt_doc = parser.parse(xslt.openStream());
    
Source feed_source = new AbderaSource(feed_doc);
Source xslt_source = new AbderaSource(xslt_doc);
    
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xslt_source);
    
Result result = new StreamResult(System.out);
transformer.transform(feed_source, result);
    

Результаты преобразования могут быть отправлены любой итоговой реализации, поддерживаемой API Java-преобразователя. В приведенном примере, результаты просто передаются на стандартный вывод. Для создания еще одного документа можно передать результаты прямо парсеру Abdera.

Поддержка публикации Atom

Когда проект Abdera только начинался, его целью было определено предоставление функционально законченных реализаций и формата синдикации Atom и протокола публикации Atom. К настоящему моменту в данной серии было достаточно много сказано о поддержке формата синдикации и продемонстрировано как можно создавать и использовать ленты. Следующий выпуск будет посвящен поддержке сервера и клиента протокола публикации Atom, которая в настоящее время находится в стадии разработки. В листинге 30 приведен пример простого клиента APP Abdera:


Листинг 30. Простой клиент протокола публикации Atom
                
Abdera abdera = new Abdera();
Client client = new CommonsClient(abdera);
RequestOptions options = client.getDefaultRequestOptions();
options.setIfModifiedSince(new java.util.Date());
options.setNoCache(true);
    
ClientResponse response = client.get("http://example.org/entries/1", options);
    
System.out.println(response.getStatus());
System.out.println(response.getStatusText());
System.out.println(response.getEntityTag());
System.out.println(response.getLastModified());
System.out.println(response.getContentType());
    
response.release();
    

Abdera и сохранность потоков

Прежде чем закончить, Вы должны знать, что базовые компоненты Abdera, например, объекты Abdera Factory, и Parser, являются поточно-ориентированными и не имеют состояния, позволяя эффективно распределять элементы по нескольким потокам. Однако создаваемые ими объекты FOM не являются поточно-ориентированными. По разным причинам практически ни один из объектов FOM не синхронизируется. И если Вы намереваетесь позволить нескольким потокам обращаться или изменять объекты Entry или Feed, то Вам необходимо организовать свою собственную синхронизацию:


Листинг 31. Несинхронизированное одновременное изменение объектов FOM приводит к непредсказуемым результатам
                
final Abdera abdera = new Abdera();
final Factory factory = abdera.getFactory();
final Entry entry = factory.newEntry();
    
final Thread[] threads = new Thread[100];
for (int n = 0; n < threads.length; n++) {
  final int i = n;
  threads[n] = new Thread(
    new Runnable() {
      public void run() {
        try {
          int s = (new java.util.Random(
            System.currentTimeMillis())).nextInt(10);
          Thread.sleep(s);
        } catch (InterruptedException e) {}
        try {
          IRI id = factory.newID();
          id.setValue("urn:thread:" + i);
          entry.setIdElement(id);
          System.out.println(i + "\t" + entry);  // непредсказуемые результаты
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  );
}
    
for (Thread t : threads) t.start();
    


Листинг 32. Пример невалидного результата листинга 31
                
85	urn:thread:85
86	urn:thread:99
91	urn:thread:91
org.apache.axiom.om.OMException
	at org.apache.axiom.om.impl.llom.OMNodeImpl.insertSiblingBefore(OMNodeImpl.java:232)
	at org.apache.abdera.parser.stax.FOMElement._setChild(Unknown Source)
	at org.apache.abdera.parser.stax.FOMEntry.setIdElement(Unknown Source)
	at abdera.examples.atom.Listing11$1.run(Listing11.java:29)
	at java.lang.Thread.run(Thread.java:788)
87	urn:thread:87
88	urn:thread:88
    

Для решения проблем достаточно заключить изменения входной информации в блок синхронизации. Однако рекомендуется, чтобы объекты FOM всегда создавались и использовались только одним потоком.

Поделиться...

digg Разместить данную историю на Digg
del.icio.us Разместить на del.icio.us
Slashdot Разместить на Slashdot!

Забегая вперед

В данной статье Вы познакомились с основными свойствами проекта Apache Abdera, включая поддержку объектной модели ленты (Feed Object Model), XPath и XSLT, обработки расширений и модели пошагового парсинга. В следующем выпуске данной серии будет представлен и описан разрабатываемый в настоящее время протокол публикации Atom.




В начало


Загрузка

ОписаниеИмяРазмерМетод загрузки
Sample Eclipse Project with the example codex-atompp3-code.zip39KBHTTP
Информация о методах загрузки


Ресурсы

Научиться

Получить продукты и технологии

Обсудить


Об авторе

Джеймс Снелл (James Snell) является членом исследовательской лаборатории IBM WebAhead, занимающейся разработкой опытных образцов стандартов и технологий программного обеспечения, находящегося в стадии создания, для собственных нужд IBM. Его научно-исследовательские интересы охватывают широкий круг направлений современных технологий, а именно Atom, AJAX, REST, Open Source, персональные издательские системы, семантические и ситуационные Web-приложения. Он является активным участником проекта Apache Abdera, находящегося в настоящее время на этапе разработки и нацеленного на создание высокоэффективной и функционально законченной реализации стандартов формата синдикации Atom и протокола публикации Atom.




Выскажите мнение об этой странице


Пожалуйста, найдите минутку и заполните форму, чтобы повысить уровень сервиса.



ДаНетНе знаю
 


 


12345
 


Поделиться этой статьей:

забобрить забобрить memori сохранить в memori




В начало


IBM обладает всеми авторскими правами касательно информации, расположенной на developerWorks. Использование информации приведенной на этом ресурсе без явного письменного разрешения от IBM или первоначального автора запрещены. Если Вы желаете использовать информацию с developerWorks, пожалуйста воспользуйтесь регистрационной формой для того, чтобы связаться с нами запрос на использование материалов developerWorks Россия.

    IBM в России Конфиденциальность Контакты