/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.fabric.netty.repository;
import com.liferay.portal.fabric.netty.codec.serialization.AnnotatedObjectDecoder;
import com.liferay.portal.fabric.netty.fileserver.FileHelperUtil;
import com.liferay.portal.fabric.netty.fileserver.FileResponse;
import com.liferay.portal.fabric.netty.fileserver.handlers.FileResponseChannelHandler;
import com.liferay.portal.fabric.netty.fileserver.handlers.FileServerTestUtil;
import com.liferay.portal.fabric.netty.util.NettyUtilAdvice;
import com.liferay.portal.kernel.concurrent.AsyncBroker;
import com.liferay.portal.kernel.concurrent.NoticeableFuture;
import com.liferay.portal.kernel.test.CaptureHandler;
import com.liferay.portal.kernel.test.JDKLoggerTestUtil;
import com.liferay.portal.kernel.test.rule.AggregateTestRule;
import com.liferay.portal.kernel.test.rule.CodeCoverageAssertor;
import com.liferay.portal.kernel.test.rule.NewEnv;
import com.liferay.portal.test.rule.AdviseWith;
import com.liferay.portal.test.rule.AspectJNewEnvTestRule;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import io.netty.channel.embedded.EmbeddedChannel;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
/**
* @author Shuyang Zhou
*/
@NewEnv(type = NewEnv.Type.CLASSLOADER)
public class NettyRepositoryTest {
@ClassRule
@Rule
public static final AggregateTestRule aggregateTestRule =
new AggregateTestRule(
CodeCoverageAssertor.INSTANCE, AspectJNewEnvTestRule.INSTANCE);
@Before
public void setUp() throws IOException {
_channelPipeline = _embeddedChannel.pipeline();
_repositoryPath = Paths.get("repository");
FileHelperUtil.delete(_repositoryPath);
FileServerTestUtil.registerForCleanUp(
Files.createDirectory(_repositoryPath));
_nettyRepository = new NettyRepository(_repositoryPath, Long.MAX_VALUE);
_asyncBroker = _nettyRepository.getAsyncBroker();
_channelPipeline.addLast(
new FileResponseChannelHandler(
_asyncBroker, _embeddedChannel.eventLoop()));
}
@After
public void tearDown() {
FileServerTestUtil.cleanUp();
}
@NewEnv(type = NewEnv.Type.NONE)
@Test
public void testConstructor() {
try {
new NettyRepository(null, Long.MAX_VALUE);
Assert.fail();
}
catch (NullPointerException npe) {
Assert.assertEquals("Repository path is null", npe.getMessage());
}
try {
new NettyRepository(Paths.get("Unknown"), Long.MAX_VALUE);
Assert.fail();
}
catch (IllegalArgumentException iae) {
}
NettyRepository nettyRepository = new NettyRepository(
_repositoryPath, Long.MAX_VALUE);
_channelPipeline.addLast(
new FileResponseChannelHandler(
nettyRepository.getAsyncBroker(),
_embeddedChannel.eventLoop()));
Assert.assertSame(_repositoryPath, nettyRepository.getRepositoryPath());
Assert.assertEquals(Long.MAX_VALUE, nettyRepository.getFileTimeout);
Assert.assertNotNull(nettyRepository.pathMap);
Assert.assertTrue(
_annotatedObjectDecoder.removeFirst() instanceof
FileResponseChannelHandler);
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testDispose() throws Exception {
Path remoteFilePath = Paths.get("remoteFile");
Path tempFilePath = FileServerTestUtil.createFileWithData(
Paths.get("tempFile"));
Map<Path, Path> pathMap = _nettyRepository.pathMap;
FileServerTestUtil.createFileWithData(tempFilePath);
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.OFF)) {
NoticeableFuture<Path> noticeableFuture = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, null, false);
FileResponse fileResponse = new FileResponse(
remoteFilePath, System.currentTimeMillis(), 0, false);
fileResponse.setLocalFile(tempFilePath);
_asyncBroker.takeWithResult(remoteFilePath, fileResponse);
Path localFilePath = noticeableFuture.get();
Assert.assertNotNull(localFilePath);
Assert.assertTrue(Files.notExists(tempFilePath));
Assert.assertTrue(Files.exists(localFilePath));
Assert.assertEquals(pathMap.toString(), 1, pathMap.size());
Assert.assertSame(localFilePath, pathMap.get(remoteFilePath));
_nettyRepository.dispose(false);
Assert.assertTrue(Files.notExists(localFilePath));
Assert.assertTrue(pathMap.isEmpty());
Assert.assertTrue(Files.exists(_repositoryPath));
_nettyRepository.dispose(true);
Assert.assertTrue(Files.notExists(_repositoryPath));
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertTrue(logRecords.isEmpty());
}
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFile() throws Exception {
// With log, populate cache
Path remoteFilePath = Paths.get("remoteFile");
Path tempFilePath = FileServerTestUtil.createFileWithData(
Paths.get("tempFile"));
Map<Path, Path> pathMap = _nettyRepository.pathMap;
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.FINEST)) {
NoticeableFuture<Path> noticeableFuture1 = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, null, false);
NoticeableFuture<Path> noticeableFuture2 = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, null, false);
Assert.assertNotSame(noticeableFuture1, noticeableFuture2);
FileResponse fileResponse = new FileResponse(
remoteFilePath, System.currentTimeMillis(), 0, false);
fileResponse.setLocalFile(tempFilePath);
_asyncBroker.takeWithResult(remoteFilePath, fileResponse);
Path localFilePath = FileServerTestUtil.registerForCleanUp(
noticeableFuture1.get());
Assert.assertSame(localFilePath, noticeableFuture2.get());
Assert.assertSame(localFilePath, fileResponse.getLocalFile());
Assert.assertNotNull(localFilePath);
Assert.assertTrue(Files.notExists(tempFilePath));
Assert.assertTrue(Files.exists(localFilePath));
Assert.assertEquals(pathMap.toString(), 1, pathMap.size());
Assert.assertSame(localFilePath, pathMap.get(remoteFilePath));
Files.delete(localFilePath);
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertEquals(logRecords.toString(), 4, logRecords.size());
LogRecord logRecord = logRecords.get(0);
Assert.assertEquals(
"Fetching remote file " + remoteFilePath,
logRecord.getMessage());
logRecord = logRecords.get(1);
Assert.assertEquals(
"Fetching remote file " + remoteFilePath,
logRecord.getMessage());
logRecord = logRecords.get(2);
Assert.assertEquals(
"Fetched remote file " + remoteFilePath + " to " +
localFilePath,
logRecord.getMessage());
logRecord = logRecords.get(3);
Assert.assertEquals(
"Fetched remote file " + remoteFilePath + " to " +
localFilePath,
logRecord.getMessage());
}
finally {
pathMap.clear();
}
// Without log, not populate cacge
FileServerTestUtil.createFileWithData(tempFilePath);
Path localFilePath1 = FileServerTestUtil.registerForCleanUp(
_repositoryPath.resolve("localFile1"));
Path localFilePath2 = FileServerTestUtil.registerForCleanUp(
_repositoryPath.resolve("localFile2"));
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.OFF)) {
NoticeableFuture<Path> noticeableFuture1 = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, localFilePath1, false);
NoticeableFuture<Path> noticeableFuture2 = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, localFilePath2, false);
Assert.assertNotSame(noticeableFuture1, noticeableFuture2);
FileResponse fileResponse = new FileResponse(
remoteFilePath, System.currentTimeMillis(), 0, false);
fileResponse.setLocalFile(tempFilePath);
_asyncBroker.takeWithResult(remoteFilePath, fileResponse);
Assert.assertSame(localFilePath1, noticeableFuture1.get());
Assert.assertSame(localFilePath2, noticeableFuture2.get());
Assert.assertSame(localFilePath2, fileResponse.getLocalFile());
Assert.assertTrue(Files.notExists(tempFilePath));
Assert.assertTrue(Files.exists(localFilePath1));
Assert.assertTrue(Files.exists(localFilePath2));
Assert.assertTrue(pathMap.isEmpty());
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertTrue(logRecords.isEmpty());
}
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFileChannelCancellation() {
_channelPipeline.addFirst(
new ChannelOutboundHandlerAdapter() {
@Override
public void write(
ChannelHandlerContext channelHandlerContext, Object object,
ChannelPromise channelPromise) {
channelPromise.cancel(true);
}
});
try {
NoticeableFuture<Path> noticeableFuture = _nettyRepository.getFile(
_embeddedChannel, Paths.get("remoteFile"),
Paths.get("localFile"), false, false);
Assert.assertTrue(noticeableFuture.isDone());
Assert.assertTrue(noticeableFuture.isCancelled());
}
finally {
_channelPipeline.removeFirst();
}
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFileChannelFailure() throws InterruptedException {
doTestGetFileChannelFailure(false, false);
doTestGetFileChannelFailure(false, true);
doTestGetFileChannelFailure(true, false);
doTestGetFileChannelFailure(true, true);
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFileFileNotFound() throws Exception {
// With log
Path remoteFilePath = Paths.get("remoteFile");
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.WARNING)) {
NoticeableFuture<Path> noticeableFuture = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, Paths.get("localFile"), false,
false);
_asyncBroker.takeWithResult(
remoteFilePath,
new FileResponse(
remoteFilePath, FileResponse.FILE_NOT_FOUND, 0, false));
Assert.assertNull(noticeableFuture.get());
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertEquals(logRecords.toString(), 1, logRecords.size());
LogRecord logRecord = logRecords.get(0);
Assert.assertEquals(
"Remote file " + remoteFilePath + " is not found",
logRecord.getMessage());
}
// Without log
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.OFF)) {
NoticeableFuture<Path> noticeableFuture = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, Paths.get("localFile"), false,
false);
_asyncBroker.takeWithResult(
remoteFilePath,
new FileResponse(
remoteFilePath, FileResponse.FILE_NOT_FOUND, 0, false));
Assert.assertNull(noticeableFuture.get());
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertTrue(logRecords.isEmpty());
}
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFileFileNotModified() throws Exception {
// With log
Path remoteFilePath = Paths.get("remoteFile");
Path cachedLocalFilePath = Paths.get("cacheLocalFile");
Map<Path, Path> pathMap = _nettyRepository.pathMap;
pathMap.put(remoteFilePath, cachedLocalFilePath);
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.FINEST)) {
NoticeableFuture<Path> noticeableFuture = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, Paths.get("localFile"), false,
false);
_asyncBroker.takeWithResult(
remoteFilePath,
new FileResponse(
remoteFilePath, FileResponse.FILE_NOT_MODIFIED, 0, false));
Assert.assertSame(cachedLocalFilePath, noticeableFuture.get());
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertEquals(logRecords.toString(), 2, logRecords.size());
LogRecord logRecord = logRecords.get(0);
Assert.assertEquals(
"Fetching remote file " + remoteFilePath,
logRecord.getMessage());
logRecord = logRecords.get(1);
Assert.assertEquals(
"Remote file " + remoteFilePath +
" is not modified, use cached local file " +
cachedLocalFilePath,
logRecord.getMessage());
}
// Without log
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.OFF)) {
NoticeableFuture<Path> noticeableFuture = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, Paths.get("localFile"), false,
false);
_asyncBroker.takeWithResult(
remoteFilePath,
new FileResponse(
remoteFilePath, FileResponse.FILE_NOT_MODIFIED, 0, false));
Assert.assertSame(cachedLocalFilePath, noticeableFuture.get());
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertTrue(logRecords.isEmpty());
}
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFiles() throws Exception {
Map<Path, Path> pathMap = new HashMap<>();
Path remoteFilePath1 = Paths.get("remoteFile1");
Path remoteFilePath2 = Paths.get("remoteFile2");
Path localFilePath = FileServerTestUtil.registerForCleanUp(
Paths.get("localFile1"));
pathMap.put(remoteFilePath1, localFilePath);
pathMap.put(remoteFilePath2, Paths.get("localFile2"));
NoticeableFuture<Map<Path, Path>> noticeableFuture =
_nettyRepository.getFiles(_embeddedChannel, pathMap, true);
Path tempFilePath = FileServerTestUtil.createFileWithData(
Paths.get("tempFile"));
FileResponse fileResponse1 = new FileResponse(
remoteFilePath1, Files.size(tempFilePath), -1, false);
fileResponse1.setLocalFile(tempFilePath);
Assert.assertTrue(
_asyncBroker.takeWithResult(remoteFilePath1, fileResponse1));
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.WARNING)) {
Assert.assertTrue(
_asyncBroker.takeWithResult(
remoteFilePath2,
new FileResponse(
remoteFilePath2, FileResponse.FILE_NOT_FOUND, -1,
false)));
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertEquals(logRecords.toString(), 1, logRecords.size());
LogRecord logRecord = logRecords.get(0);
Assert.assertEquals(
"Remote file remoteFile2 is not found", logRecord.getMessage());
}
Map<Path, Path> resultPathMap = noticeableFuture.get();
Assert.assertEquals(resultPathMap.toString(), 1, resultPathMap.size());
Assert.assertEquals(localFilePath, resultPathMap.get(remoteFilePath1));
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFilesCancelled() {
Map<Path, Path> pathMap = new HashMap<>();
Path remoteFilePath1 = Paths.get("remoteFile1");
pathMap.put(remoteFilePath1, Paths.get("localFile1"));
pathMap.put(Paths.get("remoteFile2"), Paths.get("requestFile2"));
NoticeableFuture<Map<Path, Path>> noticeableFuture =
_nettyRepository.getFiles(_embeddedChannel, pathMap, true);
Map<Path, NoticeableFuture<FileResponse>> openBids =
_asyncBroker.getOpenBids();
NoticeableFuture<FileResponse> fileGetNoticeableFuture = openBids.get(
remoteFilePath1);
Assert.assertNotNull(fileGetNoticeableFuture);
fileGetNoticeableFuture.cancel(true);
Assert.assertTrue(noticeableFuture.isCancelled());
}
@AdviseWith(
adviceClasses = {
NettyUtilAdvice.class, DefaultNoticeableFutureAdvice.class
}
)
@Test
public void testGetFilesCovertCausedException() throws Exception {
Map<Path, Path> pathMap = new HashMap<>();
Path remoteFilePath = Paths.get("remoteFile");
pathMap.put(remoteFilePath, Paths.get("localFile"));
NoticeableFuture<Map<Path, Path>> noticeableFuture =
_nettyRepository.getFiles(_embeddedChannel, pathMap, true);
Exception exception = new Exception();
DefaultNoticeableFutureAdvice.setConvertThrowable(exception);
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), Level.WARNING)) {
Assert.assertTrue(
_asyncBroker.takeWithResult(
remoteFilePath,
new FileResponse(
_repositoryPath, FileResponse.FILE_NOT_FOUND, -1,
false)));
List<LogRecord> logRecords = captureHandler.getLogRecords();
Assert.assertEquals(logRecords.toString(), 1, logRecords.size());
LogRecord logRecord = logRecords.get(0);
Assert.assertEquals(
"Remote file remoteFile is not found", logRecord.getMessage());
}
try {
noticeableFuture.get();
Assert.fail();
}
catch (ExecutionException ee) {
Assert.assertSame(exception, ee.getCause());
}
}
@NewEnv(type = NewEnv.Type.NONE)
@Test
public void testGetFilesEmptyMap() throws Exception {
NoticeableFuture<Map<Path, Path>> noticeableFuture =
_nettyRepository.getFiles(
_embeddedChannel, Collections.<Path, Path>emptyMap(), true);
Assert.assertSame(
Collections.<Path, Path>emptyMap(), noticeableFuture.get());
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFilesExecutionException() throws Exception {
Map<Path, Path> pathMap = new HashMap<>();
Path remoteFilePath1 = Paths.get("remoteFile1");
pathMap.put(remoteFilePath1, Paths.get("requestFile1"));
pathMap.put(Paths.get("remoteFile2"), Paths.get("requestFile2"));
NoticeableFuture<Map<Path, Path>> noticeableFuture =
_nettyRepository.getFiles(_embeddedChannel, pathMap, true);
Exception exception = new Exception();
Assert.assertTrue(
_asyncBroker.takeWithException(remoteFilePath1, exception));
try {
noticeableFuture.get();
Assert.fail();
}
catch (ExecutionException ee) {
Assert.assertSame(exception, ee.getCause());
}
}
@AdviseWith(adviceClasses = NettyUtilAdvice.class)
@Test
public void testGetFileTimeoutCancellation() {
NettyRepository nettyRepository = new NettyRepository(
_repositoryPath, 0);
_channelPipeline.addLast(
new FileResponseChannelHandler(
nettyRepository.getAsyncBroker(),
_embeddedChannel.eventLoop()));
NoticeableFuture<Path> noticeableFuture = nettyRepository.getFile(
_embeddedChannel, Paths.get("remoteFile"), Paths.get("localFile"),
false, false);
Assert.assertTrue(noticeableFuture.isDone());
Assert.assertTrue(noticeableFuture.isCancelled());
}
@NewEnv(type = NewEnv.Type.NONE)
@Test
public void testGetLastModifiedTime() throws IOException {
Assert.assertEquals(
Long.MIN_VALUE, NettyRepository.getLastModifiedTime(null));
Assert.assertEquals(
Long.MIN_VALUE,
NettyRepository.getLastModifiedTime(Paths.get("Unknown")));
FileTime fileTime = Files.getLastModifiedTime(_repositoryPath);
Assert.assertEquals(
fileTime.toMillis(),
NettyRepository.getLastModifiedTime(_repositoryPath));
}
@Aspect
public static class DefaultNoticeableFutureAdvice {
public static void setConvertThrowable(Throwable convertThrowable) {
_convertThrowable = convertThrowable;
}
@Around(
"execution(public void com.liferay.portal.kernel.concurrent." +
"DefaultNoticeableFuture.set(Object))"
)
public void set(ProceedingJoinPoint proceedingJoinPoint)
throws Throwable {
Object[] args = proceedingJoinPoint.getArgs();
if ((args.length == 1) && (args[0] instanceof Map)) {
throw _convertThrowable;
}
proceedingJoinPoint.proceed();
}
private static Throwable _convertThrowable;
}
protected void doTestGetFileChannelFailure(
final boolean asyncBrokerFailure, boolean logging)
throws InterruptedException {
final Exception exception = new Exception();
final Path remoteFilePath = Paths.get("remoteFile");
_channelPipeline.addLast(
new ChannelOutboundHandlerAdapter() {
@Override
public void write(
ChannelHandlerContext channelHandlerContext, Object message,
ChannelPromise channelPromise) {
if (asyncBrokerFailure) {
_asyncBroker.takeWithException(
remoteFilePath, exception);
}
channelPromise.setFailure(exception);
}
});
Level level = Level.OFF;
if (logging) {
level = Level.ALL;
}
try (CaptureHandler captureHandler =
JDKLoggerTestUtil.configureJDKLogger(
NettyRepository.class.getName(), level)) {
NoticeableFuture<Path> noticeableFuture = _nettyRepository.getFile(
_embeddedChannel, remoteFilePath, Paths.get("localFile"), false,
false);
try {
noticeableFuture.get();
}
catch (ExecutionException ee) {
Throwable throwable = ee.getCause();
if (!asyncBrokerFailure) {
Assert.assertEquals(
"Unable to fetch remote file " + remoteFilePath,
throwable.getMessage());
throwable = throwable.getCause();
}
Assert.assertSame(exception, throwable);
}
if (logging) {
List<LogRecord> logRecords = captureHandler.getLogRecords();
LogRecord logRecord = logRecords.remove(0);
Assert.assertEquals(
"Fetching remote file " + remoteFilePath,
logRecord.getMessage());
if (asyncBrokerFailure) {
logRecord = logRecords.remove(0);
Assert.assertEquals(
"Unable to place exception because no future exists " +
"with ID " + remoteFilePath,
logRecord.getMessage());
Throwable throwable = logRecord.getThrown();
Assert.assertEquals(
"Unable to fetch remote file " + remoteFilePath,
throwable.getMessage());
Assert.assertSame(exception, throwable.getCause());
}
Assert.assertTrue(logRecords.isEmpty());
}
}
}
private final AnnotatedObjectDecoder _annotatedObjectDecoder =
new AnnotatedObjectDecoder();
private AsyncBroker<Path, FileResponse> _asyncBroker;
private ChannelPipeline _channelPipeline;
private final EmbeddedChannel _embeddedChannel = new EmbeddedChannel(
new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
ChannelPipeline channelPipeline = channel.pipeline();
channelPipeline.addLast(
AnnotatedObjectDecoder.NAME, _annotatedObjectDecoder);
}
});
private NettyRepository _nettyRepository;
private Path _repositoryPath;
}