Java tutorial
/* * Copyright 2015 EMBL-European Bioinformatics Institute * * Licensed 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.ensembl.gti.seqstore.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; import java.util.Properties; import javax.sql.DataSource; import org.ensembl.gti.seqstore.database.HybridEnaCramSeqStore; import org.ensembl.gti.seqstore.database.cramstore.EnaCramSubmissionHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; public class MetaDataServer { public static class MetaDataServerOptions { @Parameter(names = { "-ena_ftp" }, description = "ENA FTP URI") private String ftpUri = "webin.ebi.ac.uk"; @Parameter(names = { "-ena_submit" }, description = "ENA Submit URI") private String submitUri = "https://www-test.ebi.ac.uk/ena/submit/drop-box/submit/?auth=ENA%20USERNAME%20PASSWORD"; @Parameter(names = { "-ena_centre" }, description = "ENA centre") private String centre = "EBI-GTI"; @Parameter(names = { "-ena_user" }, description = "ENA user") private String submitUser; @Parameter(names = { "-ena_pass" }, description = "ENA password") private String submitPass; @Parameter(names = { "-uri", "-U" }, description = "Database URI") private String dbUri; @Parameter(names = { "-user", "-u" }, description = "Database username") private String dbUser; @Parameter(names = { "-pass", "-p" }, description = "Database password") private String dbPass; @Parameter(names = { "-port", "-P" }, description = "Server port") private int port; public MetaDataServerOptions() { } public MetaDataServerOptions(Properties properties) { this(properties.getProperty("db_uri"), properties.getProperty("db_user"), properties.getProperty("db_pass"), Integer.parseInt(properties.getProperty("server_port"))); } public MetaDataServerOptions(String uri, String user, String pass, int port) { this.setDbUri(uri); this.setDbUser(user); this.setDbPass(pass); this.setPort(port); } public String getCentre() { return centre; } public String getDbPass() { return dbPass; } public String getDbUri() { return dbUri; } public String getDbUser() { return dbUser; } public String getFtpUri() { return ftpUri; } public int getPort() { return port; } public String getSubmitPass() { return submitPass; } public String getSubmitUri() { return submitUri; } public String getSubmitUser() { return submitUser; } public void setCentre(String centre) { this.centre = centre; } public void setDbPass(String dbPass) { this.dbPass = dbPass; } public void setDbUri(String dbUri) { this.dbUri = dbUri; } public void setDbUser(String dbUser) { this.dbUser = dbUser; } public void setFtpUri(String ftpUri) { this.ftpUri = ftpUri; } public void setPort(int port) { this.port = port; } public void setSubmitPass(String submitPass) { this.submitPass = submitPass; } public void setSubmitUri(String submitUri) { this.submitUri = submitUri; } public void setSubmitUser(String submitUser) { this.submitUser = submitUser; } } public static DataSource buildDataSource(String dbUri, String dbUser, String dbPass) { HikariConfig config = new HikariConfig(); config.setJdbcUrl(dbUri); config.setUsername(dbUser); config.setPassword(dbPass); config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); return new HikariDataSource(config); } public static void main(String[] args) throws Exception { final Logger log = LoggerFactory.getLogger(MetaDataServer.class); Properties properties = new Properties(); properties.load(new ClassPathResource("metadata_server.properties").getInputStream()); MetaDataServerOptions opts = new MetaDataServerOptions(properties); new JCommander(opts, args); log.info("Starting ENA submission handler"); EnaCramSubmissionHandler enaHandler = new EnaCramSubmissionHandler(opts.getFtpUri(), opts.getSubmitUri(), opts.getCentre(), opts.getSubmitUser(), opts.getSubmitPass()); log.info("Starting server on " + opts.getPort()); new MetaDataServer(opts.getPort(), buildDataSource(opts.getDbUri(), opts.getDbUser(), opts.getDbPass()), enaHandler).run(); } private final int port; private final Logger log = LoggerFactory.getLogger(this.getClass()); private final DataSource ds; private final EnaCramSubmissionHandler handler; public MetaDataServer(int port, DataSource ds, EnaCramSubmissionHandler handler) { this.port = port; this.ds = ds; this.handler = handler; } protected ChannelHandlerAdapter getHandler() { return new RequestResponseServerHandler(new HybridEnaCramSeqStore(ds, handler)); } public void run() throws Exception { log.info("Starting server"); EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4), getHandler()); } }).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true); // Bind and start to accept incoming connections. log.info("Binding to port " + port); ChannelFuture f = b.bind(port).sync(); // Wait until the server socket is closed. // In this example, this does not happen, but you can do that to // gracefully shut down your server. log.info("Syncing future"); f.channel().closeFuture().sync(); } finally { log.info("Shutting server server"); workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }