/* * 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.activemq.artemis.tests.integration.jms.cluster; import javax.jms.BytesMessage; import javax.jms.Connection; import javax.jms.MapMessage; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; import java.util.Arrays; import java.util.Collection; import org.apache.activemq.artemis.api.core.TransportConfiguration; import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient; import org.apache.activemq.artemis.api.jms.JMSFactoryType; import org.apache.activemq.artemis.core.config.ClusterConnectionConfiguration; import org.apache.activemq.artemis.core.config.Configuration; import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl; import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory; import org.apache.activemq.artemis.tests.util.JMSClusteredTestBase; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(value = Parameterized.class) public class LargeMessageOverBridgeTest extends JMSClusteredTestBase { // TODO: find a solution to this // the "jms." prefix is needed because the cluster connection is matching on this public static final String QUEUE = "jms.Q1"; private final boolean persistent; @Override protected boolean enablePersistence() { return persistent; } @Parameterized.Parameters(name = "persistent={0}") public static Collection getParameters() { return Arrays.asList(new Object[][]{{true}, {false}}); } @Override protected final ConfigurationImpl createBasicConfig(final int serverID) { ConfigurationImpl configuration = super.createBasicConfig(serverID); configuration.setJournalFileSize(1024 * 1024); return configuration; } public LargeMessageOverBridgeTest(boolean persistent) { this.persistent = persistent; } /** * This was causing a text message to ber eventually converted into large message when sent over the bridge * * @throws Exception */ @Test public void testSendHalfLargeTextMessage() throws Exception { createQueue(QUEUE); Queue queue = (Queue) context1.lookup("queue/" + QUEUE); Connection conn1 = cf1.createConnection(); Session session1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod1 = session1.createProducer(queue); Connection conn2 = cf2.createConnection(); Session session2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons2 = session2.createConsumer(queue); conn2.start(); StringBuffer buffer = new StringBuffer(); for (int i = 0; i < 51180; i++) { buffer.append('a'); } for (int i = 0; i < 10; i++) { TextMessage msg = session1.createTextMessage(buffer.toString()); prod1.send(msg); } TextMessage msg2 = (TextMessage) cons2.receive(5000); assertNotNull(msg2); assertEquals(buffer.toString(), msg2.getText()); conn1.close(); conn2.close(); } /** * This was causing a text message to ber eventually converted into large message when sent over the bridge * * @throws Exception */ @Test public void testSendMapMessageOverCluster() throws Exception { createQueue("jms." + QUEUE); Queue queue = (Queue) context1.lookup("queue/jms." + QUEUE); Connection conn1 = cf1.createConnection(); Session session1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer prod1 = session1.createProducer(queue); Connection conn2 = cf2.createConnection(); Session session2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons2 = session2.createConsumer(queue); conn2.start(); StringBuffer buffer = new StringBuffer(); for (int i = 0; i < 3810002; i++) { buffer.append('a'); } final int NUMBER_OF_MESSAGES = 1; for (int i = 0; i < NUMBER_OF_MESSAGES; i++) { MapMessage msg = session1.createMapMessage(); msg.setString("str", buffer.toString()); msg.setIntProperty("i", i); prod1.send(msg); } for (int i = 0; i < NUMBER_OF_MESSAGES; i++) { MapMessage msg = (MapMessage) cons2.receive(5000); assertEquals(buffer.toString(), msg.getString("str")); } assertNull(cons2.receiveNoWait()); conn1.close(); conn2.close(); } /** * the hack to create the failing condition in certain tests * * @param config */ private void installHack(Configuration config) { if (this.getName().equals("testSendBytesAsLargeOnBridgeOnly")) { for (ClusterConnectionConfiguration conn : config.getClusterConfigurations()) { conn.setMinLargeMessageSize(1000); } } } @Override protected Configuration createConfigServer(final int source, final int destination) throws Exception { Configuration config = super.createConfigServer(source, destination); installHack(config); return config; } /** * This was causing a text message to ber eventually converted into large message when sent over the bridge * * @throws Exception */ @Test public void testSendBytesAsLargeOnBridgeOnly() throws Exception { createQueue(QUEUE); Queue queue = (Queue) context1.lookup("queue/" + QUEUE); Connection conn1 = cf1.createConnection(); Session session1 = conn1.createSession(true, Session.SESSION_TRANSACTED); MessageProducer prod1 = session1.createProducer(queue); Connection conn2 = cf2.createConnection(); Session session2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons2 = session2.createConsumer(queue); conn2.start(); byte[] bytes = new byte[10 * 1024]; for (int i = 0; i < bytes.length; i++) { bytes[i] = getSamplebyte(i); } for (int i = 0; i < 10; i++) { BytesMessage msg = session1.createBytesMessage(); msg.writeBytes(bytes); prod1.send(msg); } session1.commit(); for (int i = 0; i < 5; i++) { BytesMessage msg2 = (BytesMessage) cons2.receive(5000); assertNotNull(msg2); msg2.acknowledge(); for (int j = 0; j < bytes.length; j++) { assertEquals("Position " + i, msg2.readByte(), bytes[j]); } } conn1.close(); conn2.close(); } /** * The message won't be large to the client while it will be considered large through the bridge * * @throws Exception */ @Test public void testSendLargeForBridge() throws Exception { createQueue(QUEUE); Queue queue = (Queue) context1.lookup("queue/" + QUEUE); ActiveMQConnectionFactory cf1 = ActiveMQJMSClient.createConnectionFactoryWithHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY, generateInVMParams(1))); cf1.setMinLargeMessageSize(200 * 1024); Connection conn1 = cf1.createConnection(); Session session1 = conn1.createSession(true, Session.SESSION_TRANSACTED); MessageProducer prod1 = session1.createProducer(queue); Connection conn2 = cf2.createConnection(); Session session2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer cons2 = session2.createConsumer(queue); conn2.start(); byte[] bytes = new byte[150 * 1024]; for (int i = 0; i < bytes.length; i++) { bytes[i] = getSamplebyte(i); } for (int i = 0; i < 10; i++) { BytesMessage msg = session1.createBytesMessage(); msg.writeBytes(bytes); prod1.send(msg); } session1.commit(); for (int i = 0; i < 5; i++) { BytesMessage msg2 = (BytesMessage) cons2.receive(5000); assertNotNull(msg2); msg2.acknowledge(); for (int j = 0; j < bytes.length; j++) { assertEquals("Position " + i, msg2.readByte(), bytes[j]); } } conn1.close(); conn2.close(); } }