All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.solace.spring.cloud.stream.binder.config.JCSMPSessionConfiguration Maven / Gradle / Ivy

The newest version!
package com.solace.spring.cloud.stream.binder.config;

import com.solace.spring.cloud.stream.binder.health.contributors.SolaceBinderHealthContributor;
import com.solace.spring.cloud.stream.binder.health.handlers.SolaceSessionEventHandler;
import com.solace.spring.cloud.stream.binder.health.indicators.SessionHealthIndicator;
import com.solace.spring.cloud.stream.binder.provisioning.SolaceEndpointProvisioner;
import com.solace.spring.cloud.stream.binder.util.JCSMPSessionEventHandler;
import com.solacesystems.jcsmp.*;
import com.solacesystems.jcsmp.impl.JCSMPBasicSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import java.io.ByteArrayOutputStream;
import java.util.*;

import static com.solacesystems.jcsmp.XMLMessage.Outcome.*;

@Slf4j
@RequiredArgsConstructor
@Configuration
@Import(SolaceHealthIndicatorsConfiguration.class)
@ConditionalOnProperty(name = "solace.java.host")
public class JCSMPSessionConfiguration {
    private final static Map SESSION_CACHE = new HashMap<>();

    @Bean
    JCSMPSessionEventHandler jcsmpSessionEventHandler(JCSMPProperties jcsmpProperties, Optional sessionHealthIndicator, Optional solaceSessionEventHandler) {
        return ensureSessionCache(jcsmpProperties, sessionHealthIndicator, solaceSessionEventHandler).jcsmpSessionEventHandler();
    }

    @Bean
    JCSMPSession jcsmpSession(JCSMPProperties jcsmpProperties, Optional sessionHealthIndicator, Optional solaceSessionEventHandler) {
        return ensureSessionCache(jcsmpProperties, sessionHealthIndicator, solaceSessionEventHandler).jcsmpSession();
    }

    @Bean
    Context jcsmpContext(JCSMPProperties jcsmpProperties, Optional sessionHealthIndicator, Optional solaceSessionEventHandler) {
        return ensureSessionCache(jcsmpProperties, sessionHealthIndicator, solaceSessionEventHandler).context();
    }

    @Bean
    SolaceEndpointProvisioner jcsmpProvisioningProvider(JCSMPProperties jcsmpProperties, Optional sessionHealthIndicator, Optional solaceSessionEventHandler) {
        return ensureSessionCache(jcsmpProperties, sessionHealthIndicator, solaceSessionEventHandler).solaceEndpointProvisioner();
    }

    private SessionCacheEntry ensureSessionCache(JCSMPProperties jcsmpProperties, Optional sessionHealthIndicator, Optional solaceSessionEventHandler) {
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Properties properties = jcsmpProperties.toProperties();
            properties.setProperty("jcsmp.CLIENT_NAME", "ignored"); // dont create a new connection if only the clientname changed
            properties.storeToXML(os, "cached");
            os.close();
            String configAsString = os.toString();
            return SESSION_CACHE.computeIfAbsent(configAsString, (key) -> createSession(jcsmpProperties, sessionHealthIndicator, solaceSessionEventHandler));
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    private static SessionCacheEntry createSession(JCSMPProperties jcsmpProperties, Optional sessionHealthIndicator, Optional solaceSessionEventHandler) {
        JCSMPProperties properties = (JCSMPProperties) jcsmpProperties.clone();
        properties.setProperty(JCSMPProperties.CLIENT_INFO_PROVIDER, new SolaceBinderClientInfoProvider());
        properties.setProperty(JCSMPProperties.REAPPLY_SUBSCRIPTIONS, true);

        final JCSMPSessionEventHandler jcsmpSessionEventHandler = new JCSMPSessionEventHandler();
        JCSMPSession jcsmpSession;
        Context context = null;
        try {
            context = JCSMPFactory.onlyInstance().createContext(new ContextProperties());
            jcsmpSession = JCSMPFactory.onlyInstance().createSession(properties, context, jcsmpSessionEventHandler);
            log.info(String.format("Connecting JCSMP session %s", jcsmpSession.getSessionName()));
            jcsmpSession.connect();
            // after setting the session health indicator status to UP,
            // we should not be worried about setting its status to DOWN,
            // as the call closing JCSMP session also delete the context
            // and terminates the application
            sessionHealthIndicator.map(SolaceBinderHealthContributor::getSolaceSessionHealthIndicator).ifPresent(SessionHealthIndicator::up);
            solaceSessionEventHandler.ifPresent(jcsmpSessionEventHandler::addSessionEventHandler);
            if (jcsmpSession instanceof JCSMPBasicSession session && !session.isRequiredSettlementCapable(Set.of(ACCEPTED, FAILED, REJECTED))) {
                log.warn("The connected Solace PubSub+ Broker is not compatible. It doesn't support message NACK capability. Consumer bindings will fail to start.");
            }
        } catch (Exception e) {
            if (context != null) {
                context.destroy();
            }
            throw new RuntimeException(e);
        }
        SolaceEndpointProvisioner solaceEndpointProvisioner = new SolaceEndpointProvisioner(jcsmpSession);
        return new SessionCacheEntry(properties, jcsmpSessionEventHandler, jcsmpSession, context, solaceEndpointProvisioner);
    }

    private record SessionCacheEntry(JCSMPProperties jcsmpProperties, JCSMPSessionEventHandler jcsmpSessionEventHandler, JCSMPSession jcsmpSession, Context context, SolaceEndpointProvisioner solaceEndpointProvisioner) {
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy