ElasticSearch in-memory for testing
Based on the second link you provided, I created this abstract test class:
@RunWith(SpringJUnit4ClassRunner.class)public abstract class AbstractElasticsearchTest { private static final String HTTP_PORT = "9205"; private static final String HTTP_TRANSPORT_PORT = "9305"; private static final String ES_WORKING_DIR = "target/es"; private static Node node; @BeforeClass public static void startElasticsearch() throws Exception { removeOldDataDir(ES_WORKING_DIR + "/" + clusterName); Settings settings = Settings.builder() .put("path.home", ES_WORKING_DIR) .put("path.conf", ES_WORKING_DIR) .put("path.data", ES_WORKING_DIR) .put("path.work", ES_WORKING_DIR) .put("path.logs", ES_WORKING_DIR) .put("http.port", HTTP_PORT) .put("transport.tcp.port", HTTP_TRANSPORT_PORT) .put("index.number_of_shards", "1") .put("index.number_of_replicas", "0") .put("discovery.zen.ping.multicast.enabled", "false") .build(); node = nodeBuilder().settings(settings).clusterName("monkeys.elasticsearch").client(false).node(); node.start(); } @AfterClass public static void stopElasticsearch() { node.close(); } private static void removeOldDataDir(String datadir) throws Exception { File dataDir = new File(datadir); if (dataDir.exists()) { FileSystemUtils.deleteRecursively(dataDir); } } }
In the production code, I configured an Elasticsearch client as follows. The integration test extends the above defined abstract class and configures property elasticsearch.port
as 9305
and elasticsearch.host
as localhost
.
@Configurationpublic class ElasticsearchConfiguration { @Bean(destroyMethod = "close") public Client elasticsearchClient(@Value("${elasticsearch.clusterName}") String clusterName, @Value("${elasticsearch.host}") String elasticsearchClusterHost, @Value("${elasticsearch.port}") Integer elasticsearchClusterPort) throws UnknownHostException { Settings settings = Settings.settingsBuilder().put("cluster.name", clusterName).build(); InetSocketTransportAddress transportAddress = new InetSocketTransportAddress(InetAddress.getByName(elasticsearchClusterHost), elasticsearchClusterPort); return TransportClient.builder().settings(settings).build().addTransportAddress(transportAddress); }}
That's it. The integration test will run the production code which is configured to connect to the node started in the AbstractElasticsearchTest.startElasticsearch()
.
In case you want to use the elasticsearch REST api, use port 9205. E.g. with Apache HttpComponents:
HttpClient httpClient = HttpClients.createDefault();HttpPut httpPut = new HttpPut("http://localhost:9205/_template/" + templateName);httpPut.setEntity(new FileEntity(new File("template.json")));httpClient.execute(httpPut);
Here is my implementation
import java.io.File;import java.io.IOException;import java.nio.file.Files;import java.util.UUID;import org.elasticsearch.client.Client;import org.elasticsearch.common.settings.ImmutableSettings;import org.elasticsearch.node.Node;import org.elasticsearch.node.NodeBuilder;/** * * @author Raghu Nair */public final class ElasticSearchInMemory { private static Client client = null; private static File tempDir = null; private static Node elasticSearchNode = null; public static Client getClient() { return client; } public static void setUp() throws Exception { tempDir = File.createTempFile("elasticsearch-temp", Long.toString(System.nanoTime())); tempDir.delete(); tempDir.mkdir(); System.out.println("writing to: " + tempDir); String clusterName = UUID.randomUUID().toString(); elasticSearchNode = NodeBuilder .nodeBuilder() .local(false) .clusterName(clusterName) .settings( ImmutableSettings.settingsBuilder() .put("script.disable_dynamic", "false") .put("gateway.type", "local") .put("index.number_of_shards", "1") .put("index.number_of_replicas", "0") .put("path.data", new File(tempDir, "data").getAbsolutePath()) .put("path.logs", new File(tempDir, "logs").getAbsolutePath()) .put("path.work", new File(tempDir, "work").getAbsolutePath()) ).node(); elasticSearchNode.start(); client = elasticSearchNode.client(); } public static void tearDown() throws Exception { if (client != null) { client.close(); } if (elasticSearchNode != null) { elasticSearchNode.stop(); elasticSearchNode.close(); } if (tempDir != null) { removeDirectory(tempDir); } } public static void removeDirectory(File dir) throws IOException { if (dir.isDirectory()) { File[] files = dir.listFiles(); if (files != null && files.length > 0) { for (File aFile : files) { removeDirectory(aFile); } } } Files.delete(dir.toPath()); }}
You can start ES on your local machine using:
Settings settings = Settings.settingsBuilder() .put("path.home", ".") .build();NodeBuilder.nodeBuilder().settings(settings).node();
When ES started, fill free to access to it over REST using curl or other tools:
curl http://localhost:9200/_cat/health?v