Avatar ·

Ошибка "Access restriction on class due to restriction on required library rt.jar" в Eclipse при работе с WSDL

Всем привет! Я начинающий Java-разработчик, пишу клиент для веб-сервиса на основе WSDL. Использую Eclipse (последняя версия) и сгенерировал классы-заглушки (stubs) через wsdl2java из Axis2. Всё скомпилировалось нормально, но когда я пытаюсь использовать один из классов (например, `javax.xml.soap.SOAPConnection` или `com.sun.xml.internal.messaging.saaj.soap.MessageImpl`), Eclipse выдаёт ошибку: ``` Access restriction on class 'javax.xml.soap.SOAPConnection' due to restriction on required library rt.jar ``` Я проверил: в проекте стоит JRE System Library [JavaSE-1.8] (jre1.8.0_281). В папке lib ничего лишнего нет. В интернете советуют убрать галочку "Access Rules" в настройках Eclipse — но это как-то неправильно, ведь это может сломать другие проекты. Вот пример кода, который вызывает ошибку: ```java import javax.xml.soap.SOAPConnection; import javax.xml.soap.SOAPConnectionFactory; import javax.xml.soap.SOAPMessage; public class SoapClient { public static void main(String[] args) { try { SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance(); SOAPConnection connection = factory.createConnection(); // ... отправка сообщения } catch (Exception e) { e.printStackTrace(); } } } ``` Ошибка появляется на строке `import javax.xml.soap.SOAPConnection;`. Что делать? Может, нужно добавить какую-то библиотеку? Или это баг Eclipse? Помогите, пожалуйста, уже третий день мучаюсь. <<>>

Причина ошибки

Ошибка "Access restriction on class due to restriction on required library rt.jar" возникает в Eclipse, когда вы пытаетесь использовать классы, которые находятся в rt.jar (или jrt-fs.jar в Java 9+), но Eclipse считает, что эти классы являются внутренними (implementation-specific) и не предназначены для прямого использования разработчиками. В вашем случае — это классы из пакета javax.xml.soap, который в Java 8 и старше действительно находится в rt.jar, но официально является частью Java EE, а не Java SE. Eclipse по умолчанию блокирует доступ к таким классам, чтобы предупредить о потенциальной несовместимости.

Основные причины:

  • Вы используете Java 8 или более старую версию, где SAAJ (SOAP with Attachments API for Java) входит в rt.jar как внутренний API.
  • Eclipse применяет "Access Rules" (правила доступа) к библиотеке JRE, которые скрывают "запрещённые" пакеты.
  • Вы генерируете заглушки с помощью wsdl2java, который может импортировать классы из com.sun.* (например, com.sun.xml.internal.messaging.saaj) — это явно внутренние классы Oracle JDK.

Решение 1: Изменить Access Rules в Eclipse (рекомендуется для разработки)

Это локальное изменение для конкретного проекта, которое не повлияет на другие проекты:

  1. Кликните правой кнопкой мыши на вашем проекте в Eclipse → выберите Properties (или Alt+Enter).
  2. Перейдите в Java Build Path → вкладка Libraries.
  3. Разверните JRE System Library [JavaSE-1.8] → выберите Access rules → нажмите Edit.
  4. Нажмите Add → в поле Resolution выберите Accessible → в поле Rule Pattern введите javax/xml/soap/** → OK.
  5. Повторите шаг 4 для com/sun/xml/internal/** (если используете классы из com.sun).
  6. Нажмите Apply and Close → пересоберите проект (Ctrl+B).

После этого Eclipse перестанет блокировать эти пакеты, и ошибка исчезнет. Однако помните: это временное решение для разработки. Для production-сборки лучше не использовать внутренние классы Oracle JDK.

Решение 2: Перейти на Java 11+ и использовать отдельную библиотеку SAAJ (правильный путь)

Начиная с Java 11, модуль java.xml.ws (который содержит SAAJ) был удалён из JDK. Теперь нужно явно подключать библиотеку. Это решает проблему и делает код переносимым:

  1. Удалите из проекта все импорты com.sun.* — они нестандартны.
  2. Добавьте в pom.xml (Maven) зависимость:
    <dependency>
        <groupId>javax.xml.soap</groupId>
        <artifactId>javax.xml.soap-api</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.messaging.saaj</groupId>
        <artifactId>saaj-impl</artifactId>
        <version>1.5.3</version>
    </dependency>
  3. Если используете Gradle:
    implementation 'javax.xml.soap:javax.xml.soap-api:1.4.0'
    implementation 'com.sun.xml.messaging.saaj:saaj-impl:1.5.3'
  4. В Eclipse обновите проект: клик правой кнопкой → Maven → Update Project (или Gradle → Refresh).
  5. Убедитесь, что в Java Build Path нет Access Rules, которые блокируют эти библиотеки (они должны быть в отдельном classpath, а не в rt.jar).

После этого ваш код будет работать на любой версии Java (8, 11, 17+), и вы избавитесь от ошибок доступа. Для WSDL-заглушек, сгенерированных wsdl2java, этот подход также корректен — он будет использовать внешнюю библиотеку SAAJ вместо встроенной.

Решение 3: Быстрый хак (не рекомендую для production)

Если вам нужно срочно собрать проект без изменения настроек Eclipse, можно отключить все Access Rules глобально:

  • В Eclipse: Window → Preferences → Java → Compiler → Errors/Warnings → Deprecated and Restricted API → установите Forbidden reference (access rules) в Warning или Ignore.

Но это опасно — вы можете случайно использовать внутренние классы, которые исчезнут в следующей версии JDK.

Итог

Лучшее решение — перейти на Java 11+ и подключить отдельную библиотеку SAAJ. Это современно, безопасно и избавит от головной боли в будущем. Если проект завязан на Java 8 — используйте настройку Access Rules в Eclipse для конкретного проекта, но избегайте com.sun.* импортов.

<<>>

Альтернативный подход: Использовать другой генератор WSDL-заглушек

Проблема может быть связана не только с Eclipse, но и с тем, как wsdl2java из Axis2 генерирует код. Он часто импортирует внутренние классы Oracle JDK (например, com.sun.xml.internal.messaging.saaj), которые недоступны в других реализациях Java (например, OpenJDK или IBM J9).

Попробуйте переключиться на генератор из Apache CXF или Spring Web Services. Они генерируют более чистый код, который использует только стандартные API (например, javax.xml.ws для JAX-WS или javax.xml.soap из внешней библиотеки).

  1. Скачайте Apache CXF (https://cxf.apache.org/download.html).
  2. Запустите генератор:
    wsdl2java -d src -client your-service.wsdl
  3. Сгенерированные классы будут использовать javax.xml.ws.Service и javax.xml.soap.SOAPMessage из стандартного API.
  4. Добавьте в проект зависимость (для Java 11+):
    <dependency>
        <groupId>javax.xml.ws</groupId>
        <artifactId>jaxws-api</artifactId>
        <version>2.3.1</version>
    </dependency>

Этот подход полностью устраняет проблему с rt.jar, так как код не использует внутренние классы. Для Java 8 всё будет работать из коробки, для Java 11+ — потреб