001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase; 019 020import java.io.IOException; 021import java.util.concurrent.CompletableFuture; 022import java.util.function.Supplier; 023import org.apache.hadoop.hbase.client.AsyncConnection; 024import org.apache.hadoop.hbase.client.Connection; 025import org.junit.ClassRule; 026import org.junit.Rule; 027import org.junit.rules.ExternalResource; 028 029/** 030 * A {@link Rule} that manages the lifecycle of an instance of {@link AsyncConnection}. Can be used 031 * in either the {@link Rule} or {@link ClassRule} positions. 032 * </p> 033 * Use in combination with {@link MiniClusterRule}, for example: 034 * 035 * <pre> 036 * { 037 * @code 038 * public class TestMyClass { 039 * private static final MiniClusterRule miniClusterRule = MiniClusterRule.newBuilder().build(); 040 * private static final ConnectionRule connectionRule = 041 * ConnectionRule.createAsyncConnectionRule(miniClusterRule::createConnection); 042 * 043 * @ClassRule 044 * public static final TestRule rule = 045 * RuleChain.outerRule(miniClusterRule).around(connectionRule); 046 * } 047 * } 048 * </pre> 049 * 050 * @deprecated Use {@link ConnectionExtension} instead, once we finish the migration of JUnit5, 051 * which means we do not need {@link ConnectionRule} any more, we can remove these 052 * dependencies, see 053 * <a href="https://issues.apache.org/jira/browse/HBASE-23671">HBASE-23671</a> for more 054 * details. 055 */ 056@Deprecated 057public final class ConnectionRule extends ExternalResource { 058 059 private final Supplier<Connection> connectionSupplier; 060 private final Supplier<CompletableFuture<AsyncConnection>> asyncConnectionSupplier; 061 062 private Connection connection; 063 private AsyncConnection asyncConnection; 064 065 public static ConnectionRule createConnectionRule(final Supplier<Connection> connectionSupplier) { 066 return new ConnectionRule(connectionSupplier, null); 067 } 068 069 public static ConnectionRule createAsyncConnectionRule( 070 final Supplier<CompletableFuture<AsyncConnection>> asyncConnectionSupplier) { 071 return new ConnectionRule(null, asyncConnectionSupplier); 072 } 073 074 public static ConnectionRule createConnectionRule(final Supplier<Connection> connectionSupplier, 075 final Supplier<CompletableFuture<AsyncConnection>> asyncConnectionSupplier) { 076 return new ConnectionRule(connectionSupplier, asyncConnectionSupplier); 077 } 078 079 private ConnectionRule(final Supplier<Connection> connectionSupplier, 080 final Supplier<CompletableFuture<AsyncConnection>> asyncConnectionSupplier) { 081 this.connectionSupplier = connectionSupplier; 082 this.asyncConnectionSupplier = asyncConnectionSupplier; 083 } 084 085 public Connection getConnection() { 086 if (connection == null) { 087 throw new IllegalStateException( 088 "ConnectionRule not initialized with a synchronous connection."); 089 } 090 return connection; 091 } 092 093 public AsyncConnection getAsyncConnection() { 094 if (asyncConnection == null) { 095 throw new IllegalStateException( 096 "ConnectionRule not initialized with an asynchronous connection."); 097 } 098 return asyncConnection; 099 } 100 101 @Override 102 protected void before() throws Throwable { 103 if (connectionSupplier != null) { 104 this.connection = connectionSupplier.get(); 105 } 106 if (asyncConnectionSupplier != null) { 107 this.asyncConnection = asyncConnectionSupplier.get().join(); 108 } 109 if (connection == null && asyncConnection != null) { 110 this.connection = asyncConnection.toConnection(); 111 } 112 } 113 114 @Override 115 protected void after() { 116 CompletableFuture<Void> closeConnection = CompletableFuture.runAsync(() -> { 117 if (this.connection != null) { 118 try { 119 connection.close(); 120 } catch (IOException e) { 121 throw new RuntimeException(e); 122 } 123 } 124 }); 125 CompletableFuture<Void> closeAsyncConnection = CompletableFuture.runAsync(() -> { 126 if (this.asyncConnection != null) { 127 try { 128 asyncConnection.close(); 129 } catch (IOException e) { 130 throw new RuntimeException(e); 131 } 132 } 133 }); 134 CompletableFuture.allOf(closeConnection, closeAsyncConnection).join(); 135 } 136}