public class ScenarioConnectionFactoryProducer extends java.lang.Object implements MatsProfiles
MatsTestProfileyou will most probably want an in-vm setup (typically mocking up the project-external Mats endpoints that the tested endpoints collaborate with). In the in-vm broker situations, the JMS ConnectionFactory instantiation lambda you provide for what will be used in the production setup will not be invoked, but instead an in-vm ActiveMQ Broker will be started, and an ActiveMQ ConnectionFactory will be produced.
Note: The actual decision logic and "Spring interfacing" is done in
is the actual class of instances that will end up as Spring beans - this class is a producer of such instances,
simplifying the configuration, providing sane defaults.
Do note that this is purely a convenience functionality, and is in no way required for the Mats system to work.
As a matter of fact, you can achieve the exact same with Spring's Profiles (or any other "switch configuration based
on some property or state"-logic you can cook up), but this class effectively represents an opinionated
implementation of the config switching that will be needed in most scenarios working with Mats, and will probably
yield less configuration overall. Moreover, Mats will most probably be employed in a micro/multiple service
architecture, and in such situations, it is nice to make some in-house library that constitute basic building blocks
that all the services will need. With that in mind, this class also facilitates so you can easily construct an
@CompanyMatsSetup-type annotation which alone will pull up both the needed ConnectionFactory (with URL
and whatever needed already set) and MatsFactory, which handles all the mentioned scenarios, by merely placing that
annotation on the main config class of your service.
The point is this: If you are new to Message Queue based development, you will probably soon sit with the problem of how to create a code base that efficiently lets you run it in production, while also is easy to develop on, and being simple to perform integration test on your endpoints - the problem being that you need different types of ConnectionFactories for the different scenarios, and in some cases also needing an in-vm MQ Broker.
There are typically four different scenarios that you need to juggle between, the two latter being identical wrt. the
Mats setup (which is the reason that
MatsScenario only has three scenarios defined):
MatsProfilesand its enum values!
For the localhost and localVM scenarios, this class by default utilizes the ActiveMQ Broker and ConnectionFactory. For all scenarios, but in particular for the "regular" (production-like), you can provide whatever ConnectionFactory you want (configured as you desire) - this class will just wrap it.
PROFILE_MATS_LOCALHOST, PROFILE_MATS_LOCALVM, PROFILE_MATS_MOCKS, PROFILE_MATS_REGULAR, PROFILE_MATS_TEST, PROFILE_PRODUCTION, PROFILE_STAGING
|Constructor and Description|
|Modifier and Type||Method and Description|
Creates the appropriate
Very optional: If you do not set the
Optional: Provide a ConnectionFactoryProvider lambda for the
Very optional: Provide a ConnectionFactoryProvider lambda for the
Can optionally be overridden should you decide to use a different decision-scheme than the
public static ScenarioConnectionFactoryProducer withRegularConnectionFactory(ScenarioConnectionFactoryWrapper.ConnectionFactoryProvider regularConnectionFactoryProvider)
ScenarioConnectionFactoryProducer, where you need to provide the
ScenarioConnectionFactoryWrapper.ConnectionFactoryProvider. This is the one that will be used in Production and Production-like environments, e.g. Staging, Acceptance Testing, Pre-Prod or whatever you call those environments. You may invoke the other "withXXX" methods to tailor further, but this is optional. After finished setup, invoke
build()to get the
ScenarioConnectionFactoryWrapperthat you then can feed to a
Notice that deciding between Production and e.g. Staging and which corresponding ConnectionFactory URL or even type of ConnectionFactory you should employ here, is up to you: You might be using configuration properties, Spring's Profile concept, System Properties (java cmd line "-D"-properties), or system environment variables - only you know how you differentiate between these environments.
Notice: You are required to set up this provider lambda. However, if you are just setting up your project,
wanting to start writing tests, or otherwise only use the
LocalVM scenario, and thus
will not utilize the "regular" scenario just yet, you could just supply a lambda here that throws e.g. an
IllegalStateException or somesuch - which probably will remind you to fix this before going into production!
regularConnectionFactoryProvider- a provider for the ConnectionFactory to use in the
ScenarioConnectionFactoryProduceron which you then optionally can invoke
#withScenarioDecider(ScenarioDecider), before invoking
public ScenarioConnectionFactoryProducer withLocalhostConnectionFactory(ScenarioConnectionFactoryWrapper.ConnectionFactoryProvider localhostConnectionFactoryProvider)
LOCALHOSTscenario (which only is meant to be used for development and possibly testing). If this is not provided, it will be a somewhat specially tailored ActiveMQ ConnectionFactory with the URL
"tcp://localhost:61616", read more in the ActiveMQ documentation. The tailoring entails DLQ after 1 retry, and 100 ms delay between delivery and the sole redelivery attempt.
localhostConnectionFactoryProvider- a provider for the ConnectionFactory to use in the
this, for chaining.
public ScenarioConnectionFactoryProducer withLocalVmConnectionFactory(ScenarioConnectionFactoryWrapper.ConnectionFactoryProvider localVmConnectionFactoryProvider)
LOCALVMscenario (which only is meant to be used for development and testing). The implementation of the lambda is expected to return a ConnectionFactory to an in-vm MQ Broker. You probably want to have this ConnectionFactory wrapped in your own extension of
ConnectionFactoryWithStartStopWrapper, which provide a way to start and stop the in-vm MQ Broker. If this configuration is not provided (and not having to handle this mess is a big point of this class, so do not provide this unless you want a different broker entirely!), the class
MatsTestBrokerwill be instantiated by invoking
MatsTestBroker.createUniqueInVmActiveMq(). From the instance of
ConnectionFactory will be gotten.
Notice that the
MatsTestBroker has a small extra feature, where you can have it produce a
ConnectionFactory to localhost or a specific URL instead of the in-vm MQ Broker it otherwise produces, by means
of specifying a special system property ("-D" options) (In this case, it does not create the in-vm MQ Broker
either). The rationale for this extra feature is if you wonder how big a difference it makes to run your tests
against a proper MQ Broker instead of the in-vm and fully non-persistent MQ Broker you by default get. Read
localVmConnectionFactoryProvider- a provider for the ConnectionFactory to use in the
this, for chaining.
public ScenarioConnectionFactoryProducer withDefaultScenario(MatsScenario defaultScenario)
#withScenarioDecider(ScenarioDecider)method, you get a
ConfigurableScenarioDecider.createDefaultScenarioDecider(). This default is configured to throw
IllegalStateExceptionif none of the
MatsScenarios are chosen. This method can override that by invoking the
ConfigurableScenarioDecider.setDefaultScenario(Supplier)method for you. Note: This should not be used in conjunction with invoking the
#withScenarioDecider(ScenarioDecider), as you should have handled the default scenario situation in the ScenarioDecider you provide!
MatsScenarioshould be chosen if the
ScenarioConnectionFactoryWrapper.ScenarioDeciderdoes not choose one.
this, for chaining.
public ScenarioConnectionFactoryProducer withScenarioDecider(ScenarioConnectionFactoryWrapper.ScenarioDecider scenarioDecider)
default. We need a decision for which MatsScenario is in effect for this JVM, and you can override the standard here. (Do note that if you want to run integration tests against a specific Active MQ Broker, e.g. on your localhost, there is already a feature for that in
MatsTestBroker, as mentioned in the JavaDoc of
localVmConnectionFactory(..)). How you otherwise decide between
LOCALVMis up to you. (For REGULAR, you will again have to decide whether you are in Production or Staging or whatever, if this e.g. gives different URLs or changes which ConnectionFactory class to instantiate - read more at
#withRegularConnectionFactory(ConnectionFactoryProvider). Note: This method should not be used in conjunction with invoking the
withDefaultScenario(MatsScenario)method, as you should have handled the default scenario situation in the ScenarioDecider you provide!
ScenarioConnectionFactoryWrapper.ScenarioDeciderthat should decide between the three
this, for chaining.
public ScenarioConnectionFactoryWrapper build()
ConnectionFactory, which is a wrapper integrating with Spring - the decision between the configured scenarios is done after all Spring beans are defined.
ConnectionFactory, which is a wrapper integrating with Spring.