This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch fix/CAMEL-26927
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 304cd218496717f689075fa11dbc6df8a5cfc916
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Nov 13 15:32:55 2026 +0100

    CAMEL-26927: camel-wordpress - each endpoint uses its own site URL and 
credentials
    
    Each WordPress endpoint now creates its own WordpressServiceProvider from
    its url, apiVersion, user and password options, and its producers and
    consumers take their services from it. The endpoints no longer initialise
    WordpressServiceProvider.getInstance(), which is deprecated together with
    its init methods in favour of WordpressServiceProvider.create(...).
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../component/wordpress/WordpressEndpoint.java     |  17 +-
 .../wordpress/api/WordpressServiceProvider.java    |  63 ++++--
 .../wordpress/consumer/WordpressPostConsumer.java  |   5 +-
 .../wordpress/consumer/WordpressUserConsumer.java  |   5 +-
 .../producer/AbstractWordpressProducer.java        |   3 +-
 .../wordpress/producer/WordpressPostProducer.java  |   3 +-
 .../wordpress/producer/WordpressUserProducer.java  |   3 +-
 .../WordpressEndpointsUseTheirOwnSiteTest.java     | 213 +++++++++++++++++++++
 .../WordpressServiceCategoriesAdapterIT.java       |   7 +-
 .../ignored/WordpressServiceCommentsAdapterIT.java |   7 +-
 .../ignored/WordpressServicePagesAdapterIT.java    |   7 +-
 .../WordpressServicePostRevisionAdapterIT.java     |   3 +-
 .../ignored/WordpressServiceTagsAdapterIT.java     |   7 +-
 .../ignored/WordpressServiceTaxonomyAdapterIT.java |   7 +-
 .../api/test/WordpressMockServerTestSupport.java   |   6 +-
 .../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc    |   9 +
 16 files changed, 323 insertions(+), 42 deletions(-)

diff --git 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/WordpressEndpoint.java
 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/WordpressEndpoint.java
index d2877c0b6df0..2e3af5c12efb 100644
--- 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/WordpressEndpoint.java
+++ 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/WordpressEndpoint.java
@@ -83,6 +83,8 @@ public class WordpressEndpoint extends DefaultEndpoint 
implements EndpointServic
     @UriParam
     private WordpressConfiguration configuration;
 
+    private WordpressServiceProvider serviceProvider;
+
     public WordpressEndpoint(String uri, WordpressComponent component, 
WordpressConfiguration configuration) {
         super(uri, component);
         this.configuration = configuration;
@@ -110,6 +112,16 @@ public class WordpressEndpoint extends DefaultEndpoint 
implements EndpointServic
         return configuration;
     }
 
+    /**
+     * The WordPress services of this endpoint, for the site URL, API version 
and credentials of this endpoint.
+     */
+    public synchronized WordpressServiceProvider getServiceProvider() {
+        if (serviceProvider == null) {
+            serviceProvider = createServiceProvider();
+        }
+        return serviceProvider;
+    }
+
     public String getOperation() {
         return operation;
     }
@@ -181,10 +193,9 @@ public class WordpressEndpoint extends DefaultEndpoint 
implements EndpointServic
         }
         // validate configuration
         configuration.validate();
-        this.initServiceProvider();
     }
 
-    private void initServiceProvider() {
+    private WordpressServiceProvider createServiceProvider() {
         final WordpressAPIConfiguration apiConfiguration
                 = new WordpressAPIConfiguration(configuration.getUrl(), 
configuration.getApiVersion());
         // basic auth
@@ -193,7 +204,7 @@ public class WordpressEndpoint extends DefaultEndpoint 
implements EndpointServic
                     .setAuthentication(new 
WordpressBasicAuthentication(configuration.getUser(), 
configuration.getPassword()));
         }
 
-        WordpressServiceProvider.getInstance().init(apiConfiguration);
+        return WordpressServiceProvider.create(apiConfiguration);
     }
 
 }
diff --git 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/api/WordpressServiceProvider.java
 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/api/WordpressServiceProvider.java
index f6a50d25e4ba..20ff7af8e509 100644
--- 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/api/WordpressServiceProvider.java
+++ 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/api/WordpressServiceProvider.java
@@ -16,7 +16,7 @@
  */
 package org.apache.camel.component.wordpress.api;
 
-import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.camel.component.wordpress.api.service.WordpressService;
 import org.apache.camel.component.wordpress.api.service.WordpressServicePosts;
@@ -27,12 +27,18 @@ import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Gives access to the WordPress services (posts and users) of one WordPress 
site.
+ * <p>
+ * Use {@link #create(WordpressAPIConfiguration)} to get a provider of its own 
for a site. Each WordPress endpoint holds
+ * its own provider.
+ */
 public final class WordpressServiceProvider {
 
     private static final Logger LOGGER = 
LoggerFactory.getLogger(WordpressServiceProvider.class);
 
-    private HashMap<Class<? extends WordpressService>, WordpressService> 
services;
-    private WordpressAPIConfiguration configuration;
+    private volatile Map<Class<? extends WordpressService>, WordpressService> 
services;
+    private volatile WordpressAPIConfiguration configuration;
 
     private WordpressServiceProvider() {
 
@@ -42,19 +48,53 @@ public final class WordpressServiceProvider {
         private static final WordpressServiceProvider INSTANCE = new 
WordpressServiceProvider();
     }
 
+    /**
+     * Creates a new provider for the WordPress site of the given 
configuration.
+     *
+     * @param  config the site URL, API version and authentication
+     * @return        a provider that is not shared with anyone else
+     */
+    public static WordpressServiceProvider create(WordpressAPIConfiguration 
config) {
+        final WordpressServiceProvider provider = new 
WordpressServiceProvider();
+        provider.doInit(config);
+        return provider;
+    }
+
+    /**
+     * The provider shared by the whole JVM.
+     *
+     * @deprecated the WordPress endpoints do not use this instance; use 
{@link #create(WordpressAPIConfiguration)}
+     */
+    @Deprecated(since = "4.24")
     public static WordpressServiceProvider getInstance() {
         return ServiceProviderHolder.INSTANCE;
     }
 
+    /**
+     * @deprecated use {@link #create(WordpressAPIConfiguration)}
+     */
+    @Deprecated(since = "4.24")
     public void init(String wordpressApiUrl) {
-        this.init(wordpressApiUrl, WordpressConstants.API_VERSION);
+        this.doInit(new WordpressAPIConfiguration(wordpressApiUrl, 
WordpressConstants.API_VERSION));
     }
 
+    /**
+     * @deprecated use {@link #create(WordpressAPIConfiguration)}
+     */
+    @Deprecated(since = "4.24")
     public void init(String wordpressApiUrl, String apiVersion) {
-        this.init(new WordpressAPIConfiguration(wordpressApiUrl, apiVersion));
+        this.doInit(new WordpressAPIConfiguration(wordpressApiUrl, 
apiVersion));
     }
 
+    /**
+     * @deprecated use {@link #create(WordpressAPIConfiguration)}
+     */
+    @Deprecated(since = "4.24")
     public void init(WordpressAPIConfiguration config) {
+        this.doInit(config);
+    }
+
+    private void doInit(WordpressAPIConfiguration config) {
         ObjectHelper.notNullOrEmpty(config.getApiUrl(),
                 "Please inform the Wordpress API url , eg.: 
http://myblog.com/wp-json/wp";);
 
@@ -68,9 +108,7 @@ public final class WordpressServiceProvider {
         servicePosts.setWordpressAuthentication(config.getAuthentication());
         serviceUsers.setWordpressAuthentication(config.getAuthentication());
 
-        this.services = new HashMap<>();
-        this.services.put(WordpressServicePosts.class, servicePosts);
-        this.services.put(WordpressServiceUsers.class, serviceUsers);
+        this.services = Map.of(WordpressServicePosts.class, servicePosts, 
WordpressServiceUsers.class, serviceUsers);
         this.configuration = config;
 
         LOGGER.info("Wordpress Service Provider initialized using base URL: 
{}, API Version {}", config.getApiUrl(),
@@ -79,7 +117,8 @@ public final class WordpressServiceProvider {
 
     @SuppressWarnings("unchecked")
     public <T extends WordpressService> T getService(Class<T> 
wordpressServiceClazz) {
-        T service = (T) this.services.get(wordpressServiceClazz);
+        final Map<Class<? extends WordpressService>, WordpressService> current 
= this.services;
+        T service = current != null ? (T) current.get(wordpressServiceClazz) : 
null;
         if (service == null) {
             throw new IllegalArgumentException(String.format("Couldn't find a 
Wordpress Service '%s'", wordpressServiceClazz));
         }
@@ -87,10 +126,8 @@ public final class WordpressServiceProvider {
     }
 
     public boolean hasAuthentication() {
-        if (this.configuration != null) {
-            return this.configuration.getAuthentication() != null;
-        }
-        return false;
+        final WordpressAPIConfiguration current = this.configuration;
+        return current != null && current.getAuthentication() != null;
     }
 
 }
diff --git 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressPostConsumer.java
 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressPostConsumer.java
index 21d8b1e488d2..0c3b1616b2c3 100644
--- 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressPostConsumer.java
+++ 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressPostConsumer.java
@@ -21,7 +21,6 @@ import java.util.concurrent.ScheduledExecutorService;
 
 import org.apache.camel.Processor;
 import org.apache.camel.component.wordpress.WordpressEndpoint;
-import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.Post;
 import org.apache.camel.component.wordpress.api.model.PostSearchCriteria;
 import org.apache.camel.component.wordpress.api.service.WordpressServicePosts;
@@ -35,13 +34,13 @@ public class WordpressPostConsumer extends 
AbstractWordpressConsumer {
 
     public WordpressPostConsumer(WordpressEndpoint endpoint, Processor 
processor) {
         super(endpoint, processor);
-        servicePosts = 
WordpressServiceProvider.getInstance().getService(WordpressServicePosts.class);
+        servicePosts = 
endpoint.getServiceProvider().getService(WordpressServicePosts.class);
     }
 
     public WordpressPostConsumer(WordpressEndpoint endpoint, Processor 
processor,
                                  ScheduledExecutorService 
scheduledExecutorService) {
         super(endpoint, processor, scheduledExecutorService);
-        servicePosts = 
WordpressServiceProvider.getInstance().getService(WordpressServicePosts.class);
+        servicePosts = 
endpoint.getServiceProvider().getService(WordpressServicePosts.class);
     }
 
     @Override
diff --git 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressUserConsumer.java
 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressUserConsumer.java
index 5cc285f044a8..707f2fc43130 100644
--- 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressUserConsumer.java
+++ 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/consumer/WordpressUserConsumer.java
@@ -21,7 +21,6 @@ import java.util.concurrent.ScheduledExecutorService;
 
 import org.apache.camel.Processor;
 import org.apache.camel.component.wordpress.WordpressEndpoint;
-import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.User;
 import org.apache.camel.component.wordpress.api.model.UserSearchCriteria;
 import org.apache.camel.component.wordpress.api.service.WordpressServiceUsers;
@@ -32,13 +31,13 @@ public class WordpressUserConsumer extends 
AbstractWordpressConsumer {
 
     public WordpressUserConsumer(WordpressEndpoint endpoint, Processor 
processor) {
         super(endpoint, processor);
-        serviceUsers = 
WordpressServiceProvider.getInstance().getService(WordpressServiceUsers.class);
+        serviceUsers = 
endpoint.getServiceProvider().getService(WordpressServiceUsers.class);
     }
 
     public WordpressUserConsumer(WordpressEndpoint endpoint, Processor 
processor,
                                  ScheduledExecutorService 
scheduledExecutorService) {
         super(endpoint, processor, scheduledExecutorService);
-        serviceUsers = 
WordpressServiceProvider.getInstance().getService(WordpressServiceUsers.class);
+        serviceUsers = 
endpoint.getServiceProvider().getService(WordpressServiceUsers.class);
     }
 
     @Override
diff --git 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/AbstractWordpressProducer.java
 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/AbstractWordpressProducer.java
index 4f343c5e3289..1b637001fea0 100644
--- 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/AbstractWordpressProducer.java
+++ 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/AbstractWordpressProducer.java
@@ -24,7 +24,6 @@ import org.apache.camel.InvalidPayloadException;
 import org.apache.camel.Message;
 import org.apache.camel.component.wordpress.WordpressConfiguration;
 import org.apache.camel.component.wordpress.WordpressEndpoint;
-import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.support.DefaultProducer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,7 +40,7 @@ public abstract class AbstractWordpressProducer<T> extends 
DefaultProducer {
     protected AbstractWordpressProducer(WordpressEndpoint endpoint) {
         super(endpoint);
         this.configuration = endpoint.getConfiguration();
-        if (!WordpressServiceProvider.getInstance().hasAuthentication()) {
+        if (!endpoint.getServiceProvider().hasAuthentication()) {
             LOG.warn(
                     "Wordpress Producer hasn't authentication. This may lead 
to errors during route execution. Wordpress writing operations need 
authentication.");
         }
diff --git 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressPostProducer.java
 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressPostProducer.java
index dc0ed9de82c4..f6e344aa7b1d 100644
--- 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressPostProducer.java
+++ 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressPostProducer.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.wordpress.producer;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.component.wordpress.WordpressEndpoint;
-import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.Post;
 import org.apache.camel.component.wordpress.api.service.WordpressServicePosts;
 import org.slf4j.Logger;
@@ -34,7 +33,7 @@ public class WordpressPostProducer extends 
AbstractWordpressProducer<Post> {
 
     public WordpressPostProducer(WordpressEndpoint endpoint) {
         super(endpoint);
-        this.servicePosts = 
WordpressServiceProvider.getInstance().getService(WordpressServicePosts.class);
+        this.servicePosts = 
endpoint.getServiceProvider().getService(WordpressServicePosts.class);
     }
 
     @Override
diff --git 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressUserProducer.java
 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressUserProducer.java
index 4d573f2f54b4..6979d81a65a3 100644
--- 
a/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressUserProducer.java
+++ 
b/components/camel-wordpress/src/main/java/org/apache/camel/component/wordpress/producer/WordpressUserProducer.java
@@ -18,7 +18,6 @@ package org.apache.camel.component.wordpress.producer;
 
 import org.apache.camel.Exchange;
 import org.apache.camel.component.wordpress.WordpressEndpoint;
-import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.User;
 import org.apache.camel.component.wordpress.api.service.WordpressServiceUsers;
 import org.slf4j.Logger;
@@ -31,7 +30,7 @@ public class WordpressUserProducer extends 
AbstractWordpressProducer<User> {
 
     public WordpressUserProducer(WordpressEndpoint endpoint) {
         super(endpoint);
-        this.serviceUsers = 
WordpressServiceProvider.getInstance().getService(WordpressServiceUsers.class);
+        this.serviceUsers = 
endpoint.getServiceProvider().getService(WordpressServiceUsers.class);
     }
 
     @Override
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/WordpressEndpointsUseTheirOwnSiteTest.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/WordpressEndpointsUseTheirOwnSiteTest.java
new file mode 100644
index 000000000000..402ca24256f8
--- /dev/null
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/WordpressEndpointsUseTheirOwnSiteTest.java
@@ -0,0 +1,213 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.camel.component.wordpress;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.wordpress.api.model.Content;
+import org.apache.camel.component.wordpress.api.model.Post;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.apache.hc.core5.http.ClassicHttpRequest;
+import org.apache.hc.core5.http.ClassicHttpResponse;
+import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpStatus;
+import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
+import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
+import org.apache.hc.core5.http.io.HttpRequestHandler;
+import org.apache.hc.core5.http.io.entity.EntityUtils;
+import org.apache.hc.core5.http.io.entity.StringEntity;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.everyItem;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+
+/**
+ * Every WordPress endpoint talks to the site of its own url option, with its 
own user and password, whatever the order
+ * in which the endpoints and their producers and consumers are created.
+ */
+public class WordpressEndpointsUseTheirOwnSiteTest extends CamelTestSupport {
+
+    private static final String NO_USER = "none";
+
+    private static Site siteA;
+    private static Site siteB;
+
+    @BeforeAll
+    public static void startSites() throws IOException {
+        siteA = Site.start();
+        siteB = Site.start();
+    }
+
+    @AfterAll
+    public static void stopSites() {
+        siteA.stop();
+        siteB.stop();
+    }
+
+    @BeforeEach
+    public void clearRequests() {
+        siteA.requests.clear();
+        siteB.requests.clear();
+    }
+
+    @Test
+    public void testProducersUseTheirOwnSite() {
+        final String uriA = "wordpress:post?url=" + siteA.url() + 
"&user=alice&password=secretA";
+        final String uriB = "wordpress:post?url=" + siteB.url() + 
"&user=bob&password=secretB";
+        context.getEndpoint(uriA);
+        context.getEndpoint(uriB);
+
+        template.requestBody(uriA, newPost("from A"));
+        template.requestBody(uriB, newPost("from B"));
+
+        assertThat(siteA.requests, contains("POST /wp/v2/posts alice"));
+        assertThat(siteB.requests, contains("POST /wp/v2/posts bob"));
+    }
+
+    @Test
+    public void testProducersUseTheirOwnSiteInReverseCreationOrder() {
+        final String uriA = "wordpress:post?url=" + siteA.url() + 
"&user=alice&password=secretA";
+        final String uriB = "wordpress:post?url=" + siteB.url() + 
"&user=bob&password=secretB";
+        context.getEndpoint(uriB);
+        context.getEndpoint(uriA);
+
+        template.requestBody(uriA, newPost("from A"));
+        template.requestBody(uriB, newPost("from B"));
+
+        assertThat(siteA.requests, contains("POST /wp/v2/posts alice"));
+        assertThat(siteB.requests, contains("POST /wp/v2/posts bob"));
+    }
+
+    @Test
+    public void testConsumerWithoutUserSendsNoCredentials() throws Exception {
+        // one site: a consumer without user next to a producer with a user, 
the consumer endpoint created first
+        final String readUri = "wordpress:post?url=" + siteA.url() + "&id=1";
+        final String writeUri = "wordpress:post?url=" + siteA.url() + 
"&user=alice&password=secretA";
+        context.getEndpoint(readUri);
+        context.getEndpoint(writeUri);
+
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from(readUri).to("mock:read");
+            }
+        });
+        MockEndpoint mock = getMockEndpoint("mock:read");
+        mock.expectedMinimumMessageCount(1);
+        mock.allMessages().body().isInstanceOf(Post.class);
+        MockEndpoint.assertIsSatisfied(context);
+
+        template.requestBody(writeUri, newPost("from A"));
+
+        final List<String> reads = siteA.requests.stream().filter(r -> 
r.startsWith("GET")).toList();
+        assertThat(reads, everyItem(is("GET /wp/v2/posts/1 " + NO_USER)));
+        assertThat(siteA.requests, hasItem("POST /wp/v2/posts alice"));
+        assertThat(siteB.requests.isEmpty(), is(true));
+    }
+
+    private static Post newPost(String title) {
+        final Post post = new Post();
+        post.setAuthor(2);
+        post.setTitle(new Content(title));
+        return post;
+    }
+
+    /**
+     * A local WordPress site that answers posts requests and records each one 
as "METHOD path user".
+     */
+    private static final class Site implements HttpRequestHandler {
+
+        private final List<String> requests = new CopyOnWriteArrayList<>();
+        private final Map<String, String> responses;
+        private HttpServer server;
+
+        private Site(Map<String, String> responses) {
+            this.responses = responses;
+        }
+
+        static Site start() throws IOException {
+            final Site site = new Site(
+                    Map.of(
+                            "GET /wp/v2/posts", "/data/posts/list.json",
+                            "POST /wp/v2/posts", "/data/posts/create.json",
+                            "GET /wp/v2/posts/1", "/data/posts/single.json"));
+            site.server = 
ServerBootstrap.bootstrap().setCanonicalHostName("localhost").setListenerPort(0)
+                    .register("/wp/v2/posts", site)
+                    .register("/wp/v2/posts/*", site)
+                    .create();
+            site.server.start();
+            return site;
+        }
+
+        String url() {
+            return "http://localhost:"; + server.getLocalPort();
+        }
+
+        void stop() {
+            if (server != null) {
+                server.stop();
+            }
+        }
+
+        @Override
+        public void handle(ClassicHttpRequest request, ClassicHttpResponse 
response, HttpContext context)
+                throws IOException {
+            final String path = request.getPath().split("\\?", 2)[0];
+            final String key = request.getMethod() + " " + path;
+            requests.add(key + " " + user(request));
+            if (request.getEntity() != null) {
+                EntityUtils.consume(request.getEntity());
+            }
+            final String resource = responses.get(key);
+            if (resource == null) {
+                response.setCode(HttpStatus.SC_NOT_FOUND);
+                return;
+            }
+            try (InputStream is = 
WordpressEndpointsUseTheirOwnSiteTest.class.getResourceAsStream(resource)) {
+                response.setCode(HttpStatus.SC_OK);
+                response.setEntity(new StringEntity(
+                        new String(is.readAllBytes(), StandardCharsets.UTF_8), 
ContentType.APPLICATION_JSON));
+            }
+        }
+
+        private static String user(ClassicHttpRequest request) {
+            final Header header = request.getFirstHeader("Authorization");
+            if (header == null) {
+                return NO_USER;
+            }
+            final String encoded = 
header.getValue().substring("Basic".length()).trim();
+            final String credentials = new 
String(Base64.getDecoder().decode(encoded), StandardCharsets.UTF_8);
+            return credentials.split(":", 2)[0];
+        }
+    }
+}
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCategoriesAdapterIT.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCategoriesAdapterIT.java
index 7bb666099e5e..9904113c3029 100644
--- 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCategoriesAdapterIT.java
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCategoriesAdapterIT.java
@@ -19,6 +19,8 @@ package 
org.apache.camel.component.wordpress.api.service.impl.ignored;
 import java.util.List;
 
 import org.apache.camel.component.wordpress.WordpressTestConstants;
+import org.apache.camel.component.wordpress.api.WordpressAPIConfiguration;
+import org.apache.camel.component.wordpress.api.WordpressConstants;
 import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.Category;
 import org.apache.camel.component.wordpress.api.model.CategorySearchCriteria;
@@ -41,8 +43,9 @@ public class WordpressServiceCategoriesAdapterIT {
 
     @BeforeAll
     public static void before() {
-        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider.getInstance();
-        serviceProvider.init(WordpressTestConstants.WORDPRESS_DEMO_URL);
+        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider
+                .create(new WordpressAPIConfiguration(
+                        WordpressTestConstants.WORDPRESS_DEMO_URL, 
WordpressConstants.API_VERSION));
         serviceCategories = 
serviceProvider.getService(WordpressServiceCategories.class);
     }
 
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCommentsAdapterIT.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCommentsAdapterIT.java
index 7cf577ac5c93..11057765356c 100644
--- 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCommentsAdapterIT.java
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceCommentsAdapterIT.java
@@ -19,6 +19,8 @@ package 
org.apache.camel.component.wordpress.api.service.impl.ignored;
 import java.util.List;
 
 import org.apache.camel.component.wordpress.WordpressTestConstants;
+import org.apache.camel.component.wordpress.api.WordpressAPIConfiguration;
+import org.apache.camel.component.wordpress.api.WordpressConstants;
 import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.Category;
 import org.apache.camel.component.wordpress.api.model.CategorySearchCriteria;
@@ -41,8 +43,9 @@ public class WordpressServiceCommentsAdapterIT {
 
     @BeforeAll
     public static void before() {
-        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider.getInstance();
-        serviceProvider.init(WordpressTestConstants.WORDPRESS_DEMO_URL);
+        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider
+                .create(new WordpressAPIConfiguration(
+                        WordpressTestConstants.WORDPRESS_DEMO_URL, 
WordpressConstants.API_VERSION));
         serviceCategories = 
serviceProvider.getService(WordpressServiceCategories.class);
     }
 
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePagesAdapterIT.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePagesAdapterIT.java
index 407d06e932e0..5deb74d5fe5f 100644
--- 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePagesAdapterIT.java
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePagesAdapterIT.java
@@ -19,6 +19,8 @@ package 
org.apache.camel.component.wordpress.api.service.impl.ignored;
 import java.util.List;
 
 import org.apache.camel.component.wordpress.WordpressTestConstants;
+import org.apache.camel.component.wordpress.api.WordpressAPIConfiguration;
+import org.apache.camel.component.wordpress.api.WordpressConstants;
 import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.Page;
 import org.apache.camel.component.wordpress.api.model.PageSearchCriteria;
@@ -40,8 +42,9 @@ public class WordpressServicePagesAdapterIT {
 
     @BeforeAll
     public static void before() {
-        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider.getInstance();
-        serviceProvider.init(WordpressTestConstants.WORDPRESS_DEMO_URL);
+        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider
+                .create(new WordpressAPIConfiguration(
+                        WordpressTestConstants.WORDPRESS_DEMO_URL, 
WordpressConstants.API_VERSION));
         servicePages = serviceProvider.getService(WordpressServicePages.class);
     }
 
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePostRevisionAdapterIT.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePostRevisionAdapterIT.java
index fcf40e255f52..ac0675df842d 100644
--- 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePostRevisionAdapterIT.java
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServicePostRevisionAdapterIT.java
@@ -50,13 +50,12 @@ public class WordpressServicePostRevisionAdapterIT extends 
WordpressMockServerTe
 
     @BeforeAll
     public static void before() {
-        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider.getInstance();
         final WordpressAuthentication authentication
                 = new WordpressBasicAuthentication("integration_test", 
"JD)e)Ox)z@HyDF*Dv4aWszm*");
         final WordpressAPIConfiguration configuration
                 = new 
WordpressAPIConfiguration(WordpressTestConstants.WORDPRESS4J_URL, 
WordpressConstants.API_VERSION);
         configuration.setAuthentication(authentication);
-        serviceProvider.init(configuration);
+        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider.create(configuration);
         servicePostRevision = 
serviceProvider.getService(WordpressServicePostRevision.class);
     }
 
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTagsAdapterIT.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTagsAdapterIT.java
index a65c0d20405b..bfd05bc0dd11 100644
--- 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTagsAdapterIT.java
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTagsAdapterIT.java
@@ -19,6 +19,8 @@ package 
org.apache.camel.component.wordpress.api.service.impl.ignored;
 import java.util.List;
 
 import org.apache.camel.component.wordpress.WordpressTestConstants;
+import org.apache.camel.component.wordpress.api.WordpressAPIConfiguration;
+import org.apache.camel.component.wordpress.api.WordpressConstants;
 import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.Tag;
 import org.apache.camel.component.wordpress.api.model.TagSearchCriteria;
@@ -41,8 +43,9 @@ public class WordpressServiceTagsAdapterIT {
 
     @BeforeAll
     public static void before() {
-        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider.getInstance();
-        serviceProvider.init(WordpressTestConstants.WORDPRESS_DEMO_URL);
+        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider
+                .create(new WordpressAPIConfiguration(
+                        WordpressTestConstants.WORDPRESS_DEMO_URL, 
WordpressConstants.API_VERSION));
         serviceTags = serviceProvider.getService(WordpressServiceTags.class);
     }
 
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTaxonomyAdapterIT.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTaxonomyAdapterIT.java
index d59b98549d47..c36f3347e364 100644
--- 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTaxonomyAdapterIT.java
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/service/impl/ignored/WordpressServiceTaxonomyAdapterIT.java
@@ -19,6 +19,8 @@ package 
org.apache.camel.component.wordpress.api.service.impl.ignored;
 import java.util.Map;
 
 import org.apache.camel.component.wordpress.WordpressTestConstants;
+import org.apache.camel.component.wordpress.api.WordpressAPIConfiguration;
+import org.apache.camel.component.wordpress.api.WordpressConstants;
 import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.camel.component.wordpress.api.model.Taxonomy;
 import 
org.apache.camel.component.wordpress.api.service.WordpressServiceTaxonomy;
@@ -39,8 +41,9 @@ public class WordpressServiceTaxonomyAdapterIT {
 
     @BeforeAll
     public static void before() {
-        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider.getInstance();
-        serviceProvider.init(WordpressTestConstants.WORDPRESS_DEMO_URL);
+        final WordpressServiceProvider serviceProvider = 
WordpressServiceProvider
+                .create(new WordpressAPIConfiguration(
+                        WordpressTestConstants.WORDPRESS_DEMO_URL, 
WordpressConstants.API_VERSION));
         serviceTaxonomy = 
serviceProvider.getService(WordpressServiceTaxonomy.class);
     }
 
diff --git 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/test/WordpressMockServerTestSupport.java
 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/test/WordpressMockServerTestSupport.java
index 40af1e59f3e9..9df852dd855c 100644
--- 
a/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/test/WordpressMockServerTestSupport.java
+++ 
b/components/camel-wordpress/src/test/java/org/apache/camel/component/wordpress/api/test/WordpressMockServerTestSupport.java
@@ -21,6 +21,8 @@ import java.net.BindException;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.camel.component.wordpress.api.WordpressAPIConfiguration;
+import org.apache.camel.component.wordpress.api.WordpressConstants;
 import org.apache.camel.component.wordpress.api.WordpressServiceProvider;
 import org.apache.hc.core5.http.impl.bootstrap.HttpServer;
 import org.apache.hc.core5.http.impl.bootstrap.ServerBootstrap;
@@ -55,8 +57,8 @@ public abstract class WordpressMockServerTestSupport {
                 i++;
             }
         }
-        serviceProvider = WordpressServiceProvider.getInstance();
-        serviceProvider.init(getServerBaseUrl());
+        serviceProvider = WordpressServiceProvider
+                .create(new WordpressAPIConfiguration(getServerBaseUrl(), 
WordpressConstants.API_VERSION));
         // @formatter:on
         LOGGER.info("Local server up and running on address {} and port {}", 
localServer.getInetAddress(),
                 localServer.getLocalPort());
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index eb1094feafd4..e8519588d729 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -217,6 +217,15 @@ now reject the invocation before the tool route runs. 
Previously, these argument
 required-argument check and then be discarded by the reserved-name filter, 
leaving the route without
 a required value. Rename these parameters and update their `parameter.*` or 
`argSchema` declarations.
 
+=== camel-wordpress - each endpoint uses its own site URL and credentials
+
+Each WordPress endpoint now has a client of its own, set up from the `url`, 
`apiVersion`, `user` and `password`
+options of that endpoint, and the producers and consumers of the endpoint use 
that client. The endpoints no longer
+initialise the `WordpressServiceProvider.getInstance()` singleton, which is 
deprecated together with its `init`
+methods. Code that read services from `WordpressServiceProvider.getInstance()` 
after Camel created a WordPress endpoint
+must now use `WordpressEndpoint.getServiceProvider()`, or create a provider 
with
+`WordpressServiceProvider.create(WordpressAPIConfiguration)`.
+
 === camel-azure-functions - invokeFunction checks the function app and the 
function name
 
 The `invokeFunction` operation now checks the function app and the function 
name, from the endpoint or from the

Reply via email to