You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用getSlownikiOfflinePort触发WebServiceException问题求助

Fixing javax.xml.ws.WebServiceException for {http://gugik.gov.pl/...}teryt Property Issue

Alright, let's break down what's causing this error and walk through actionable solutions since you can't modify the generated library code.

The Root Cause

Looking at your code snippets, the key difference between the problematic PobierzPelne class and the working PobierzUlice class is the @XmlElement annotation on their fields:

  • For PobierzUlice, every field has @XmlElement(namespace = ""), explicitly specifying no namespace for the XML element.
  • For PobierzPelne, the teryt field only has @XmlElement(required = true)—no namespace specified.

JAXB defaults to using the target namespace of the WSDL/service (in your case, http://gugik.gov.pl/schemas/slowniki-offline-service/1.0) for elements without an explicit namespace. When your client sends the request, it's wrapping the teryt value in this namespace, but the server expects an element with no namespace. That's why you're getting the error saying the named property with the namespace doesn't exist.

The cleanest fix is to regenerate your Java classes from the WSDL using a JAXB external binding file that forces the teryt element to use an empty namespace.

Step 1: Create a Binding File (bindings.xjb)

Create this file in your project (e.g., src/main/resources/bindings.xjb):

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               jaxb:version="2.1">
    <!-- Target the schema from your WSDL -->
    <jaxb:bindings schemaLocation="path/to/your/slowniki-offline-schema.xsd" node="/xsd:schema">
        <!-- Target the pobierzPelne complex type -->
        <jaxb:bindings node="xsd:complexType[@name='pobierzPelne']">
            <!-- Force the teryt element to use an empty namespace -->
            <jaxb:bindings node="xsd:element[@name='teryt']">
                <jaxb:XmlElement namespace=""/>
            </jaxb:bindings>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

Replace path/to/your/slowniki-offline-schema.xsd with either the local path to your schema file or the direct URL from the WSDL.

Step 2: Regenerate Classes with the Binding File

If you're using Maven, configure the jaxws-maven-plugin to use this binding file:

<plugin>
    <groupId>org.jvnet.jax-ws-commons</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>2.3</version>
    <executions>
        <execution>
            <goals>
                <goal>wsimport</goal>
            </goals>
            <configuration>
                <wsdlUrls>
                    <wsdlUrl>http://gugik.gov.pl/your-service-endpoint?wsdl</wsdlUrl>
                </wsdlUrls>
                <bindingFiles>
                    <bindingFile>src/main/resources/bindings.xjb</bindingFile>
                </bindingFiles>
                <packageName>pl.package.OfflineService</packageName>
            </configuration>
        </execution>
    </executions>
</plugin>

Run mvn clean compile to regenerate the classes—this time, PobierzPelne's teryt field will have @XmlElement(namespace = "") just like the working classes.

Solution 2: Custom Service Class with Modified JAXB Context (No Regeneration)

If regenerating classes isn't an option, you can create a custom subclass of Service that overrides the port creation to use a JAXB context that maps the problematic namespace to an empty prefix.

Step 1: Create the Custom Service Class

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceException;
import java.util.HashMap;
import java.util.Map;

public class CustomSlownikiOfflineService extends Service {
    // Match the service name and namespace from your WSDL
    private static final QName SERVICE_QNAME = new QName(
        "http://gugik.gov.pl/schemas/slowniki-offline-service/1.0",
        "SlownikiOfflineService"
    );

    public CustomSlownikiOfflineService() {
        // Replace with your WSDL resource path or URL
        super(CustomSlownikiOfflineService.class.getResource("/wsdl/slowniki-offline.wsdl"), SERVICE_QNAME);
    }

    @WebEndpoint(name = "SlownikiOfflinePort")
    public SlownikiOffline getSlownikiOfflinePort() {
        try {
            // Configure JAXB to map the service namespace to an empty prefix
            Map<String, Object> jaxbProps = new HashMap<>();
            jaxbProps.put(JAXBContext.NAMESPACE_PREFIX_MAPPER, new CustomNamespaceMapper());

            // Create JAXB context with your generated classes' package
            JAXBContext customContext = JAXBContext.newInstance(
                "pl.package.OfflineService",
                CustomSlownikiOfflineService.class.getClassLoader(),
                jaxbProps
            );

            // Return the port with the custom JAXB context
            return super.getPort(
                new QName("http://gugik.gov.pl/schemas/slowniki-offline-service/1.0", "SlownikiOfflinePort"),
                SlownikiOffline.class,
                provider -> {
                    Map<String, Object> requestCtx = new HashMap<>();
                    requestCtx.put(javax.xml.ws.BindingProvider.JAXB_CONTEXT_PROPERTY, customContext);
                    return requestCtx;
                }
            );
        } catch (JAXBException e) {
            throw new WebServiceException("Failed to initialize custom JAXB context", e);
        }
    }

    // Custom mapper to empty the problematic namespace
    private static class CustomNamespaceMapper extends com.sun.xml.bind.marshaller.NamespacePrefixMapper {
        @Override
        public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
            if ("http://gugik.gov.pl/schemas/slowniki-offline-service/1.0".equals(namespaceUri)) {
                return ""; // Map the namespace to an empty prefix (no namespace)
            }
            return suggestion;
        }
    }
}

Step 2: Use the Custom Service

Instead of using the auto-generated service class, instantiate CustomSlownikiOfflineService to get your port:

CustomSlownikiOfflineService service = new CustomSlownikiOfflineService();
SlownikiOffline port = service.getSlownikiOfflinePort();
// Now use the port normally

If you're in a pinch and can't use the above methods, you can use reflection to modify the @XmlElement annotation's namespace value. Note: This is fragile and depends on JVM implementation—use only as a last resort.

try {
    Field terytField = PobierzPelne.class.getDeclaredField("teryt");
    XmlElement xmlElementAnno = terytField.getAnnotation(XmlElement.class);
    
    // Modify the annotation's namespace field (requires access to internal classes)
    Field namespaceField = xmlElementAnno.getClass().getDeclaredField("namespace");
    namespaceField.setAccessible(true);
    namespaceField.set(xmlElementAnno, "");
} catch (NoSuchFieldException | IllegalAccessException e) {
    e.printStackTrace();
}

Final Notes

The first solution (regenerating with a binding file) is the most maintainable, as it fixes the root issue at code generation time. The second solution works if you can't regenerate classes, and the third is a temporary workaround.

内容的提问来源于stack exchange,提问作者Karol Piaśnik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:15:59