ibm-messaging / mq-jms-spring

Components to assist MQ JMS integration with Spring frameworks
Apache License 2.0
190 stars 102 forks source link

Is it possible to create an IBM MQ broker in spring boot 3? #102

Closed sw-tracker closed 11 months ago

sw-tracker commented 11 months ago

We would like to create an embedded IBM MQ broker in our mock, so we can test our MQ code. We know that we could also do this with test containers, but embedded tends to be faster. Does your library support this?

ibmmqmet commented 11 months ago

This package doesn't provide any mock objects. Most people use a real queue manager for testing - a permanently-running container in the test infrastructure would be fast to connect to. So many object depend on other objects (like you can't get a Destination without having a Connection) that faking it is likely to be more trouble than it's worth.

sw-tracker commented 11 months ago

I ended up creating a testcontainer, however, if I create a docker container manually and then connect my application to it, it works. If I create the broker as a testcontainer, I get the following error:

Caused by: com.ibm.mq.MQException: JMSCMQ0001: IBM MQ call failed with compcode '2' ('MQCC_FAILED') reason '2035' ('MQRC_NOT_AUTHORIZED').

Test Container:

@Configuration
class ImbMqTestContainerConfig {

  @Bean
  fun ibmMqTestContainer(): GenericContainer<*> {
    val hostPort = 1414
    val containerExposedPort = 1414
    val portBinding =
        PortBinding(Ports.Binding.bindPort(hostPort), ExposedPort(containerExposedPort))

    val dockerfile =
        ImageFromDockerfile()
            .withFileFromClasspath("Dockerfile", "mq/Dockerfile")
            .withFileFromClasspath("20-config.mqsc", "mq/20-config.mqsc")

    return GenericContainer(dockerfile)
        .withExposedPorts(containerExposedPort)
        .withCreateContainerCmdModifier { cmd ->
          cmd.withHostConfig(HostConfig().withPortBindings(portBinding))
        }
        .withEnv("LICENSE", "accept")
        .withEnv("MQ_QMGR_NAME", "QM1")
  }
}

Listener:

@Service
class MqConsumer : SessionAwareMessageListener<ObjectMessage> {

    @JmsListener(destination = "MY.QUEUE")
    override fun onMessage(message: ObjectMessage, session: Session) {
        println("Received JMS Message <$message>")
    }
}

Configuration:

ibm:
  mq:
    queueManager: QM1
    connName: localhost(1414)
    channel: DEV.ADMIN.SVRCONN
    user: admin
    password: passw0rd

As mentioned above:

sw-tracker commented 11 months ago

Sorry my bad, the listener should have been configured like this:

    @JmsListener(destination = "MY.QUEUE")
    fun onMessage(message: String) {
        println("Received JMS Message <$message>")
    }