Repository: nifi
Updated Branches:
  refs/heads/master a5fecda5a -> c120c4982


http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
new file mode 100644
index 0000000..6457067
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/api/TestSiteToSiteResource.java
@@ -0,0 +1,516 @@
+/*
+ * 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.nifi.web.api;
+
+import org.apache.nifi.remote.HttpRemoteSiteListener;
+import org.apache.nifi.remote.Peer;
+import org.apache.nifi.remote.RootGroupPort;
+import org.apache.nifi.remote.VersionNegotiator;
+import org.apache.nifi.remote.exception.HandshakeException;
+import org.apache.nifi.remote.io.http.HttpServerCommunicationsSession;
+import org.apache.nifi.remote.protocol.ResponseCode;
+import org.apache.nifi.remote.protocol.http.HttpFlowFileServerProtocol;
+import org.apache.nifi.remote.protocol.http.HttpHeaders;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.web.NiFiServiceFacade;
+import org.apache.nifi.web.api.dto.ControllerDTO;
+import org.apache.nifi.web.api.entity.ControllerEntity;
+import org.apache.nifi.web.api.entity.PeersEntity;
+import org.apache.nifi.web.api.entity.TransactionResultEntity;
+import org.apache.nifi.web.api.request.ClientIdParameter;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+public class TestSiteToSiteResource {
+
+    @BeforeClass
+    public static void setup() throws Exception {
+        final URL resource = 
TestSiteToSiteResource.class.getResource("/site-to-site/nifi.properties");
+        final String propertiesFile = resource.toURI().getPath();
+        System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, 
propertiesFile);
+    }
+
+    @Test
+    public void testGetControllerForOlderVersion() throws Exception {
+        final HttpServletRequest req = mock(HttpServletRequest.class);
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+        final ControllerEntity controllerEntity = new ControllerEntity();
+        final ControllerDTO controller = new ControllerDTO();
+        controllerEntity.setController(controller);
+
+        controller.setRemoteSiteHttpListeningPort(8080);
+        controller.setRemoteSiteListeningPort(9990);
+
+        doReturn(controller).when(serviceFacade).getController();
+
+        final SiteToSiteResource resource = new SiteToSiteResource();
+        resource.setProperties(NiFiProperties.getInstance());
+        resource.setServiceFacade(serviceFacade);
+        final Response response = resource.getController(req);
+
+        ControllerEntity resultEntity = (ControllerEntity)response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertNull("remoteSiteHttpListeningPort should be null since older 
version doesn't recognize this field" +
+                " and throws JSON mapping exception.", 
resultEntity.getController().getRemoteSiteHttpListeningPort());
+        assertEquals("Other fields should be retained.", new Integer(9990), 
controllerEntity.getController().getRemoteSiteListeningPort());
+    }
+
+    @Test
+    public void testGetController() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+        final ControllerEntity controllerEntity = new ControllerEntity();
+        final ControllerDTO controller = new ControllerDTO();
+        controllerEntity.setController(controller);
+
+        controller.setRemoteSiteHttpListeningPort(8080);
+        controller.setRemoteSiteListeningPort(9990);
+
+        doReturn(controller).when(serviceFacade).getController();
+
+        final SiteToSiteResource resource = new SiteToSiteResource();
+        resource.setProperties(NiFiProperties.getInstance());
+        resource.setServiceFacade(serviceFacade);
+        final Response response = resource.getController(req);
+
+        ControllerEntity resultEntity = (ControllerEntity)response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals("remoteSiteHttpListeningPort should be retained", new 
Integer(8080), resultEntity.getController().getRemoteSiteHttpListeningPort());
+        assertEquals("Other fields should be retained.", new Integer(9990), 
controllerEntity.getController().getRemoteSiteListeningPort());
+    }
+
+    private HttpServletRequest createCommonHttpServletRequest() {
+        final HttpServletRequest req = mock(HttpServletRequest.class);
+        doReturn("1").when(req).getHeader(eq(HttpHeaders.PROTOCOL_VERSION));
+        return req;
+    }
+
+    @Test
+    public void testPeers() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = new SiteToSiteResource();
+        resource.setProperties(NiFiProperties.getInstance());
+        resource.setServiceFacade(serviceFacade);
+
+        final Response response = resource.getPeers(null, req);
+
+        PeersEntity resultEntity = (PeersEntity) response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(1, resultEntity.getPeers().size());
+    }
+
+
+    @Test
+    public void testPeersVersionWasNotSpecified() throws Exception {
+        final HttpServletRequest req = mock(HttpServletRequest.class);
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = new SiteToSiteResource();
+        resource.setProperties(NiFiProperties.getInstance());
+        resource.setServiceFacade(serviceFacade);
+
+        final Response response = resource.getPeers(null, req);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+        assertEquals(400, response.getStatus());
+        assertEquals(ResponseCode.ABORT.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testPeersVersionNegotiationDowngrade() throws Exception {
+        final HttpServletRequest req = mock(HttpServletRequest.class);
+        doReturn("999").when(req).getHeader(eq(HttpHeaders.PROTOCOL_VERSION));
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = new SiteToSiteResource();
+        resource.setProperties(NiFiProperties.getInstance());
+        resource.setServiceFacade(serviceFacade);
+
+        final Response response = resource.getPeers(null, req);
+
+        PeersEntity resultEntity = (PeersEntity) response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(1, resultEntity.getPeers().size());
+        assertEquals(new Integer(1), 
response.getMetadata().getFirst(HttpHeaders.PROTOCOL_VERSION));
+    }
+
+    @Test
+    public void testCreateTransactionPortNotFound() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        final HttpFlowFileServerProtocol serverProtocol = 
mockHttpFlowFileServerProtocol(resource);
+
+        doThrow(new HandshakeException(ResponseCode.UNKNOWN_PORT, "Not 
found.")).when(serverProtocol).handshake(any());
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final UriInfo uriInfo = null;
+        final InputStream inputStream = null;
+
+        final Response response = resource.createPortTransaction(clientId, 
"input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(404, response.getStatus());
+        assertEquals(ResponseCode.UNKNOWN_PORT.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testCreateTransactionPortNotInValidState() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        final HttpFlowFileServerProtocol serverProtocol = 
mockHttpFlowFileServerProtocol(resource);
+
+        doThrow(new HandshakeException(ResponseCode.PORT_NOT_IN_VALID_STATE, 
"Not in valid state.")).when(serverProtocol).handshake(any());
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final UriInfo uriInfo = null;
+        final InputStream inputStream = null;
+
+        final Response response = resource.createPortTransaction(clientId, 
"input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(503, response.getStatus());
+        assertEquals(ResponseCode.PORT_NOT_IN_VALID_STATE.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testCreateTransactionUnauthorized() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        final HttpFlowFileServerProtocol serverProtocol = 
mockHttpFlowFileServerProtocol(resource);
+
+        doThrow(new HandshakeException(ResponseCode.UNAUTHORIZED, 
"Unauthorized.")).when(serverProtocol).handshake(any());
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final UriInfo uriInfo = null;
+        final InputStream inputStream = null;
+
+        final Response response = resource.createPortTransaction(clientId, 
"input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(401, response.getStatus());
+        assertEquals(ResponseCode.UNAUTHORIZED.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    private UriInfo mockUriInfo(final String locationUriStr) throws 
URISyntaxException {
+        final UriInfo uriInfo = mock(UriInfo.class);
+        final UriBuilder uriBuilder = mock(UriBuilder.class);
+
+        final URI locationUri = new URI(locationUriStr);
+        doReturn(uriBuilder).when(uriInfo).getBaseUriBuilder();
+        doReturn(uriBuilder).when(uriBuilder).path(any(String.class));
+        doReturn(locationUri).when(uriBuilder).build();
+        return uriInfo;
+    }
+
+    @Test
+    public void testCreateTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        mockHttpFlowFileServerProtocol(resource);
+
+        final String locationUriStr = 
"http://localhost:8080/nifi-api/site-to-site/input-ports/port-id/transactions/transaction-id";;
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final UriInfo uriInfo = mockUriInfo(locationUriStr);
+        final InputStream inputStream = null;
+
+       final Response response = resource.createPortTransaction(clientId, 
"input-ports", "port-id", req, context, uriInfo, inputStream);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(201, response.getStatus());
+        assertEquals(ResponseCode.PROPERTIES_OK.getCode(), 
resultEntity.getResponseCode());
+        assertEquals(locationUriStr, 
response.getMetadata().getFirst(HttpHeaders.LOCATION_HEADER_NAME).toString());
+    }
+
+    @Test
+    public void testExtendTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        mockHttpFlowFileServerProtocol(resource);
+
+        final String locationUriStr = 
"http://localhost:8080/nifi-api/site-to-site/input-ports/port-id/transactions/transaction-id";;
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final HttpServletResponse res = null;
+        final UriInfo uriInfo = mockUriInfo(locationUriStr);
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = 
HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.extendPortTransactionTTL(clientId, 
"input-ports", "port-id", transactionId, req, res, context, uriInfo, 
inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(ResponseCode.CONTINUE_TRANSACTION.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testReceiveFlowFiles() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        final HttpFlowFileServerProtocol serverProtocol = 
mockHttpFlowFileServerProtocol(resource);
+
+        final RootGroupPort port = mock(RootGroupPort.class);
+        doReturn(port).when(serverProtocol).getPort();
+        doAnswer(invocation -> {
+            Peer peer = (Peer) invocation.getArguments()[0];
+            
((HttpServerCommunicationsSession)peer.getCommunicationsSession()).setChecksum("server-checksum");
+            return 7;
+        }).when(port).receiveFlowFiles(any(Peer.class), any());
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = 
HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.receiveFlowFiles(clientId, 
"port-id", transactionId, req, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        final Object entity = response.getEntity();
+
+        assertEquals(202, response.getStatus());
+        assertEquals("server-checksum", entity);
+    }
+
+    @Test
+    public void testReceiveZeroFlowFiles() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        final HttpFlowFileServerProtocol serverProtocol = 
mockHttpFlowFileServerProtocol(resource);
+
+        final RootGroupPort port = mock(RootGroupPort.class);
+        doReturn(port).when(serverProtocol).getPort();
+        doAnswer(invocation -> 0).when(port).receiveFlowFiles(any(Peer.class), 
any());
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = 
HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.receiveFlowFiles(clientId, 
"port-id", transactionId, req, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        assertEquals(400, response.getStatus());
+    }
+
+    @Test
+    public void testCommitInputPortTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        mockHttpFlowFileServerProtocol(resource);
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = 
HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = 
resource.commitInputPortTransaction(clientId, 
ResponseCode.CONFIRM_TRANSACTION.getCode(), "port-id", transactionId, req, 
context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(ResponseCode.CONFIRM_TRANSACTION.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testTransferFlowFiles() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        mockHttpFlowFileServerProtocol(resource);
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final HttpServletResponse res = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = 
HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = resource.transferFlowFiles(clientId, 
"port-id", transactionId, req, res, context, inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        final Object entity = response.getEntity();
+
+        assertEquals(202, response.getStatus());
+        assertTrue(entity instanceof StreamingOutput);
+    }
+
+    @Test
+    public void testCommitOutputPortTransaction() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        mockHttpFlowFileServerProtocol(resource);
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = 
HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = 
resource.commitOutputPortTransaction(clientId, 
ResponseCode.CONFIRM_TRANSACTION.getCode(),
+                "client-checksum", "port-id", transactionId, req, context, 
inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(200, response.getStatus());
+        assertEquals(ResponseCode.CONFIRM_TRANSACTION.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    @Test
+    public void testCommitOutputPortTransactionBadChecksum() throws Exception {
+        final HttpServletRequest req = createCommonHttpServletRequest();
+
+        final NiFiServiceFacade serviceFacade = mock(NiFiServiceFacade.class);
+
+        final SiteToSiteResource resource = 
spySiteToSiteResource(serviceFacade);
+
+        final HttpFlowFileServerProtocol serverProtocol = 
mockHttpFlowFileServerProtocol(resource);
+        doThrow(new HandshakeException(ResponseCode.BAD_CHECKSUM, "Bad 
checksum.")).when(serverProtocol).commitTransferTransaction(any(), any());
+
+        final ClientIdParameter clientId = new ClientIdParameter("client-id");
+        final ServletContext context = null;
+        final InputStream inputStream = null;
+
+        final HttpRemoteSiteListener transactionManager = 
HttpRemoteSiteListener.getInstance();
+        final String transactionId = transactionManager.createTransaction();
+
+        final Response response = 
resource.commitOutputPortTransaction(clientId, 
ResponseCode.CONFIRM_TRANSACTION.getCode(),
+                "client-checksum", "port-id", transactionId, req, context, 
inputStream);
+
+        transactionManager.cancelTransaction(transactionId);
+
+        TransactionResultEntity resultEntity = (TransactionResultEntity) 
response.getEntity();
+
+        assertEquals(400, response.getStatus());
+        assertEquals(ResponseCode.BAD_CHECKSUM.getCode(), 
resultEntity.getResponseCode());
+    }
+
+    private HttpFlowFileServerProtocol 
mockHttpFlowFileServerProtocol(SiteToSiteResource resource) {
+        final HttpFlowFileServerProtocol serverProtocol = 
mock(HttpFlowFileServerProtocol.class);
+        
doReturn(serverProtocol).when(resource).getHttpFlowFileServerProtocol(any(VersionNegotiator.class));
+        return serverProtocol;
+    }
+
+    private SiteToSiteResource spySiteToSiteResource(NiFiServiceFacade 
serviceFacade) {
+        final SiteToSiteResource resource = spy(SiteToSiteResource.class);
+        resource.setProperties(NiFiProperties.getInstance());
+        resource.setServiceFacade(serviceFacade);
+        return resource;
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
index e655f06..a41e3b1 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/access-control/nifi.properties
@@ -73,7 +73,7 @@ nifi.components.status.snapshot.frequency=10 secs
 
 # Site to Site properties
 #For testing purposes. Default value should actually be empty!
-nifi.remote.input.socket.host=
+nifi.remote.input.host=
 nifi.remote.input.socket.port=
 nifi.remote.input.secure=false
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/site-to-site/nifi.properties
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/site-to-site/nifi.properties
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/site-to-site/nifi.properties
new file mode 100644
index 0000000..3d7d0e8
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/resources/site-to-site/nifi.properties
@@ -0,0 +1,174 @@
+# 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.
+
+# Core Properties #
+nifi.version=${nifi.version}
+nifi.flow.configuration.file=${nifi.flow.configuration.file}
+nifi.flow.configuration.archive.dir=${nifi.flow.configuration.archive.dir}
+nifi.flowcontroller.autoResumeState=${nifi.flowcontroller.autoResumeState}
+nifi.flowcontroller.graceful.shutdown.period=${nifi.flowcontroller.graceful.shutdown.period}
+nifi.flowservice.writedelay.interval=${nifi.flowservice.writedelay.interval}
+nifi.administrative.yield.duration=${nifi.administrative.yield.duration}
+# If a component has no work to do (is "bored"), how long should we wait 
before checking again for work?
+nifi.bored.yield.duration=${nifi.bored.yield.duration}
+
+nifi.authorizer.configuration.file=${nifi.authorizer.configuration.file}
+nifi.login.identity.provider.configuration.file=${nifi.login.identity.provider.configuration.file}
+nifi.templates.directory=${nifi.templates.directory}
+nifi.ui.banner.text=${nifi.ui.banner.text}
+nifi.ui.autorefresh.interval=${nifi.ui.autorefresh.interval}
+nifi.nar.library.directory=${nifi.nar.library.directory}
+nifi.nar.working.directory=${nifi.nar.working.directory}
+nifi.documentation.working.directory=${nifi.documentation.working.directory}
+
+####################
+# State Management #
+####################
+nifi.state.management.configuration.file=${nifi.state.management.configuration.file}
+# The ID of the local state provider
+nifi.state.management.provider.local=${nifi.state.management.provider.local}
+# The ID of the cluster-wide state provider. This will be ignored if NiFi is 
not clustered but must be populated if running in a cluster.
+nifi.state.management.provider.cluster=${nifi.state.management.provider.cluster}
+# Specifies whether or not this instance of NiFi should run an embedded 
ZooKeeper server
+nifi.state.management.embedded.zookeeper.start=${nifi.state.management.embedded.zookeeper.start}
+# Properties file that provides the ZooKeeper properties to use if 
<nifi.state.management.embedded.zookeeper.start> is set to true
+nifi.state.management.embedded.zookeeper.properties=${nifi.state.management.embedded.zookeeper.properties}
+
+
+# H2 Settings
+nifi.database.directory=${nifi.database.directory}
+nifi.h2.url.append=${nifi.h2.url.append}
+
+# FlowFile Repository
+nifi.flowfile.repository.implementation=${nifi.flowfile.repository.implementation}
+nifi.flowfile.repository.directory=${nifi.flowfile.repository.directory}
+nifi.flowfile.repository.partitions=${nifi.flowfile.repository.partitions}
+nifi.flowfile.repository.checkpoint.interval=${nifi.flowfile.repository.checkpoint.interval}
+nifi.flowfile.repository.always.sync=${nifi.flowfile.repository.always.sync}
+
+nifi.swap.manager.implementation=${nifi.swap.manager.implementation}
+nifi.queue.swap.threshold=${nifi.queue.swap.threshold}
+nifi.swap.in.period=${nifi.swap.in.period}
+nifi.swap.in.threads=${nifi.swap.in.threads}
+nifi.swap.out.period=${nifi.swap.out.period}
+nifi.swap.out.threads=${nifi.swap.out.threads}
+
+# Content Repository
+nifi.content.repository.implementation=${nifi.content.repository.implementation}
+nifi.content.claim.max.appendable.size=${nifi.content.claim.max.appendable.size}
+nifi.content.claim.max.flow.files=${nifi.content.claim.max.flow.files}
+nifi.content.repository.directory.default=${nifi.content.repository.directory.default}
+nifi.content.repository.archive.max.retention.period=${nifi.content.repository.archive.max.retention.period}
+nifi.content.repository.archive.max.usage.percentage=${nifi.content.repository.archive.max.usage.percentage}
+nifi.content.repository.archive.enabled=${nifi.content.repository.archive.enabled}
+nifi.content.repository.always.sync=${nifi.content.repository.always.sync}
+nifi.content.viewer.url=${nifi.content.viewer.url}
+
+# Provenance Repository Properties
+nifi.provenance.repository.implementation=${nifi.provenance.repository.implementation}
+
+# Persistent Provenance Repository Properties
+nifi.provenance.repository.directory.default=${nifi.provenance.repository.directory.default}
+nifi.provenance.repository.max.storage.time=${nifi.provenance.repository.max.storage.time}
+nifi.provenance.repository.max.storage.size=${nifi.provenance.repository.max.storage.size}
+nifi.provenance.repository.rollover.time=${nifi.provenance.repository.rollover.time}
+nifi.provenance.repository.rollover.size=${nifi.provenance.repository.rollover.size}
+nifi.provenance.repository.query.threads=${nifi.provenance.repository.query.threads}
+nifi.provenance.repository.index.threads=${nifi.provenance.repository.index.threads}
+nifi.provenance.repository.compress.on.rollover=${nifi.provenance.repository.compress.on.rollover}
+nifi.provenance.repository.always.sync=${nifi.provenance.repository.always.sync}
+nifi.provenance.repository.journal.count=${nifi.provenance.repository.journal.count}
+# Comma-separated list of fields. Fields that are not indexed will not be 
searchable. Valid fields are: 
+# EventType, FlowFileUUID, Filename, TransitURI, ProcessorID, 
AlternateIdentifierURI, Relationship, Details
+nifi.provenance.repository.indexed.fields=${nifi.provenance.repository.indexed.fields}
+# FlowFile Attributes that should be indexed and made searchable.  Some 
examples to consider are filename, uuid, mime.type
+nifi.provenance.repository.indexed.attributes=${nifi.provenance.repository.indexed.attributes}
+# Large values for the shard size will result in more Java heap usage when 
searching the Provenance Repository
+# but should provide better performance
+nifi.provenance.repository.index.shard.size=${nifi.provenance.repository.index.shard.size}
+# Indicates the maximum length that a FlowFile attribute can be when 
retrieving a Provenance Event from
+# the repository. If the length of any attribute exceeds this value, it will 
be truncated when the event is retrieved.
+nifi.provenance.repository.max.attribute.length=${nifi.provenance.repository.max.attribute.length}
+
+# Volatile Provenance Respository Properties
+nifi.provenance.repository.buffer.size=${nifi.provenance.repository.buffer.size}
+
+# Component Status Repository
+nifi.components.status.repository.implementation=${nifi.components.status.repository.implementation}
+nifi.components.status.repository.buffer.size=${nifi.components.status.repository.buffer.size}
+nifi.components.status.snapshot.frequency=${nifi.components.status.snapshot.frequency}
+
+# Site to Site properties
+nifi.remote.input.host=
+nifi.remote.input.secure=false
+nifi.remote.input.socket.port=
+nifi.remote.input.http.enabled=true
+nifi.remote.input.http.transaction.ttl=30 sec
+
+# web properties #
+nifi.web.war.directory=${nifi.web.war.directory}
+nifi.web.http.host=${nifi.web.http.host}
+nifi.web.http.port=8080
+nifi.web.https.host=${nifi.web.https.host}
+nifi.web.https.port=${nifi.web.https.port}
+nifi.web.jetty.working.directory=${nifi.jetty.work.dir}
+nifi.web.jetty.threads=${nifi.web.jetty.threads}
+
+# security properties #
+nifi.sensitive.props.key=
+nifi.sensitive.props.algorithm=${nifi.sensitive.props.algorithm}
+nifi.sensitive.props.provider=${nifi.sensitive.props.provider}
+
+nifi.security.keystore=${nifi.security.keystore}
+nifi.security.keystoreType=${nifi.security.keystoreType}
+nifi.security.keystorePasswd=${nifi.security.keystorePasswd}
+nifi.security.keyPasswd=${nifi.security.keyPasswd}
+nifi.security.truststore=${nifi.security.truststore}
+nifi.security.truststoreType=${nifi.security.truststoreType}
+nifi.security.truststorePasswd=${nifi.security.truststorePasswd}
+nifi.security.needClientAuth=${nifi.security.needClientAuth}
+nifi.security.user.authorizer=${nifi.security.user.authorizer}
+nifi.security.user.login.identity.provider=${nifi.security.user.login.identity.provider}
+nifi.security.ocsp.responder.url=${nifi.security.ocsp.responder.url}
+nifi.security.ocsp.responder.certificate=${nifi.security.ocsp.responder.certificate}
+
+# cluster common properties (all nodes must have same values) #
+nifi.cluster.protocol.heartbeat.interval=${nifi.cluster.protocol.heartbeat.interval}
+nifi.cluster.protocol.is.secure=${nifi.cluster.protocol.is.secure}
+
+# cluster node properties (only configure for cluster nodes) #
+nifi.cluster.is.node=${nifi.cluster.is.node}
+nifi.cluster.node.address=${nifi.cluster.node.address}
+nifi.cluster.node.protocol.port=${nifi.cluster.node.protocol.port}
+nifi.cluster.node.protocol.threads=${nifi.cluster.node.protocol.threads}
+nifi.cluster.node.event.history.size=${nifi.cluster.node.event.history.size}
+nifi.cluster.node.connection.timeout=${nifi.cluster.node.connection.timeout}
+nifi.cluster.node.read.timeout=${nifi.cluster.node.read.timeout}
+nifi.cluster.firewall.file=${nifi.cluster.firewall.file}
+
+# How long a request should be allowed to hold a 'lock' on a component. #
+nifi.cluster.request.replication.claim.timeout=${nifi.cluster.request.replication.claim.timeout}
+
+# zookeeper properties, used for cluster management #
+nifi.zookeeper.connect.string=${nifi.zookeeper.connect.string}
+nifi.zookeeper.connect.timeout=${nifi.zookeeper.connect.timeout}
+nifi.zookeeper.session.timeout=${nifi.zookeeper.session.timeout}
+nifi.zookeeper.root.node=${nifi.zookeeper.root.node}
+
+# kerberos #
+nifi.kerberos.krb5.file=${nifi.kerberos.krb5.file}
+nifi.kerberos.service.principal=${nifi.kerberos.service.principal}
+nifi.kerberos.keytab.location=${nifi.kerberos.keytab.location}
+nifi.kerberos.authentication.expiration=${nifi.kerberos.authentication.expiration}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-remote-process-group-dialog.jsp
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-remote-process-group-dialog.jsp
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-remote-process-group-dialog.jsp
index 7f73572..6d256d8 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-remote-process-group-dialog.jsp
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/new-remote-process-group-dialog.jsp
@@ -23,5 +23,77 @@
                 <input id="new-remote-process-group-uri" type="text" 
placeholder="https://remotehost:8080/nifi"/>
             </div>
         </div>
+        <div class="setting">
+            <div class="remote-process-group-timeout-setting">
+                <div class="setting-name">
+                    Communications timeout
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="When communication with this remote 
process group takes longer than this amount of time, it will timeout."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="new-remote-process-group-timeout"/>
+                </div>
+            </div>
+            <div class="remote-process-group-yield-duration-setting">
+                <div class="setting-name">
+                    Yield duration
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="When communication with this remote 
process group fails, it will not be scheduled again until this amount of time 
elapses."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="new-remote-process-group-yield-duration"/>
+                </div>
+            </div>
+            <div class="clear"></div>
+        </div>
+        <div class="setting">
+            <div class="setting-name">
+                Transport Protocol
+                <img class="setting-icon icon-info" src="images/iconInfo.png" 
alt="Info" title="Specify the transport protocol to use for this Remote Process 
Group communication."/>
+            </div>
+            <div class="setting-field">
+                <div 
id="new-remote-process-group-transport-protocol-combo"></div>
+            </div>
+        </div>
+        <div class="setting">
+            <div class="remote-process-group-proxy-host-setting">
+                <div class="setting-name">
+                    HTTP Proxy server hostname
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify the proxy server's hostname 
to use. If not specified, HTTP traffics are sent directly to the target NiFi 
instance."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="new-remote-process-group-proxy-host"/>
+                </div>
+            </div>
+            <div class="remote-process-group-proxy-port-setting">
+                <div class="setting-name">
+                    HTTP Proxy server port
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify the proxy server's port 
number, optional. If not specified, default port 80 will be used."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="new-remote-process-group-proxy-port"/>
+                </div>
+            </div>
+            <div class="clear"></div>
+        </div>
+        <div class="setting">
+            <div class="remote-process-group-proxy-user-setting">
+                <div class="setting-name">
+                    HTTP Proxy user
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify an user name to connect to 
the proxy server, optional."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="new-remote-process-group-proxy-user"/>
+                </div>
+            </div>
+            <div class="remote-process-group-proxy-password-setting">
+                <div class="setting-name">
+                    HTTP Proxy password
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify an user password to connect 
to the proxy server, optional."/>
+                </div>
+                <div class="setting-field">
+                    <input type="password" class="small-setting-input" 
id="new-remote-process-group-proxy-password"/>
+                </div>
+            </div>
+            <div class="clear"></div>
+        </div>
     </div>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-configuration.jsp
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-configuration.jsp
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-configuration.jsp
index 8995dbe..c54874a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-configuration.jsp
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-configuration.jsp
@@ -36,19 +36,76 @@
             </div>
         </div>
         <div class="setting">
-            <div class="setting-name">Communications timeout</div>
-            <div class="setting-field">
-                <input type="text" id="remote-process-group-timeout"/>
+            <div class="remote-process-group-timeout-setting">
+                <div class="setting-name">
+                    Communications timeout
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="When communication with this remote 
process group takes longer than this amount of time, it will timeout."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="remote-process-group-timeout"/>
+                </div>
+            </div>
+            <div class="remote-process-group-yield-duration-setting">
+                <div class="setting-name">
+                    Yield duration
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="When communication with this remote 
process group fails, it will not be scheduled again until this amount of time 
elapses."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="remote-process-group-yield-duration"/>
+                </div>
             </div>
+            <div class="clear"></div>
         </div>
         <div class="setting">
             <div class="setting-name">
-                Yield duration
-                <img class="setting-icon icon-info" src="images/iconInfo.png" 
alt="Info" title="When communication with this remote process group fails, it 
will not be scheduled again until this amount of time elapses."/>
+                Transport Protocol
+                <img class="setting-icon icon-info" src="images/iconInfo.png" 
alt="Info" title="Specify the transport protocol to use for this Remote Process 
Group communication."/>
             </div>
             <div class="setting-field">
-                <input type="text" id="remote-process-group-yield-duration"/>
+                <div id="remote-process-group-transport-protocol-combo"></div>
+            </div>
+        </div>
+        <div class="setting">
+            <div class="remote-process-group-proxy-host-setting">
+                <div class="setting-name">
+                    HTTP Proxy server hostname
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify the proxy server's hostname 
to use. If not specified, HTTP traffics are sent directly to the target NiFi 
instance."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="remote-process-group-proxy-host"/>
+                </div>
+            </div>
+            <div class="remote-process-group-proxy-port-setting">
+                <div class="setting-name">
+                    HTTP Proxy server port
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify the proxy server's port 
number, optional. If not specified, default port 80 will be used."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="remote-process-group-proxy-port"/>
+                </div>
+            </div>
+            <div class="clear"></div>
+        </div>
+        <div class="setting">
+            <div class="remote-process-group-proxy-user-setting">
+                <div class="setting-name">
+                    HTTP Proxy user
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify an user name to connect to 
the proxy server, optional."/>
+                </div>
+                <div class="setting-field">
+                    <input type="text" class="small-setting-input" 
id="remote-process-group-proxy-user"/>
+                </div>
+            </div>
+            <div class="remote-process-group-proxy-password-setting">
+                <div class="setting-name">
+                    HTTP Proxy password
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify an user password to connect 
to the proxy server, optional."/>
+                </div>
+                <div class="setting-field">
+                    <input type="password" class="small-setting-input" 
id="remote-process-group-proxy-password"/>
+                </div>
             </div>
+            <div class="clear"></div>
         </div>
     </div>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-details.jsp
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-details.jsp
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-details.jsp
index b74fab4..2f27987 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-details.jsp
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/partials/canvas/remote-process-group-details.jsp
@@ -36,19 +36,76 @@
             </div>
         </div>
         <div class="setting">
-            <div class="setting-name">Communications timeout</div>
-            <div class="setting-field">
-                <span id="read-only-remote-process-group-timeout"></span>
+            <div class="remote-process-group-timeout-setting">
+                <div class="setting-name">
+                    Communications timeout
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="When communication with this remote 
process group takes longer than this amount of time, it will timeout."/>
+                </div>
+                <div class="setting-field">
+                    <span id="read-only-remote-process-group-timeout"></span>
+                </div>
+            </div>
+            <div class="remote-process-group-yield-duration-setting">
+                <div class="setting-name">
+                    Yield duration
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="When communication with this remote 
process group fails, it will not be scheduled again until this amount of time 
elapses."/>
+                </div>
+                <div class="setting-field">
+                    <span 
id="read-only-remote-process-group-yield-duration"></span>
+                </div>
             </div>
+            <div class="clear"></div>
         </div>
         <div class="setting">
             <div class="setting-name">
-                Yield duration
-                <img class="setting-icon icon-info" src="images/iconInfo.png" 
alt="Info" title="When communication with this remote process group fails, it 
will not be scheduled again until this amount of time elapses."/>
+                Transport Protocol
+                <img class="setting-icon icon-info" src="images/iconInfo.png" 
alt="Info" title="Transport protocol to use for this Remote Process Group 
communication."/>
             </div>
             <div class="setting-field">
-                <span 
id="read-only-remote-process-group-yield-duration"></span>
+                <div 
id="read-only-remote-process-group-transport-protocol"></div>
+            </div>
+        </div>
+        <div class="setting">
+            <div class="remote-process-group-proxy-host-setting">
+                <div class="setting-name">
+                    HTTP Proxy server hostname
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify the proxy server's hostname 
to use. If not specified, HTTP traffics are sent directly to the target NiFi 
instance."/>
+                </div>
+                <div class="setting-field">
+                    <span 
id="read-only-remote-process-group-proxy-host"></span>
+                </div>
+            </div>
+            <div class="remote-process-group-proxy-port-setting">
+                <div class="setting-name">
+                    HTTP Proxy server port
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify the proxy server's port 
number, optional. If not specified, default port 80 will be used."/>
+                </div>
+                <div class="setting-field">
+                    <span 
id="read-only-remote-process-group-proxy-port"></span>
+                </div>
+            </div>
+            <div class="clear"></div>
+        </div>
+        <div class="setting">
+            <div class="remote-process-group-proxy-user-setting">
+                <div class="setting-name">
+                    HTTP Proxy user
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify an user name to connect to 
the proxy server, optional."/>
+                </div>
+                <div class="setting-field">
+                    <span 
id="read-only-remote-process-group-proxy-user"></span>
+                </div>
+            </div>
+            <div class="remote-process-group-proxy-password-setting">
+                <div class="setting-name">
+                    HTTP Proxy password
+                    <img class="setting-icon icon-info" 
src="images/iconInfo.png" alt="Info" title="Specify an user password to connect 
to the proxy server, optional."/>
+                </div>
+                <div class="setting-field">
+                    <span 
id="read-only-remote-process-group-proxy-password"></span>
+                </div>
             </div>
+            <div class="clear"></div>
         </div>
     </div>
 </div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
index 86d52fe..b338120 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/dialog.css
@@ -43,14 +43,25 @@
 #new-remote-process-group-dialog {
     z-index: 1301;
     display: none;
-    width: 350px;
-    height: 150px;
+    width: 400px;
+    height: 370px;
+}
+
+#new-remote-process-group-dialog .small-setting-input {
+    width: 160px;
+}
+
+#new-remote-process-group-transport-protocol-combo {
+    width: 160px;
+    height: 18px;
+    line-height: 18px;
 }
 
 #new-remote-process-group-uri {
-    width: 320px;
+    width: 370px;
 }
 
+
 #new-template-dialog {
     z-index: 1301;
     display: none;

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/remote-process-group-configuration.css
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/remote-process-group-configuration.css
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/remote-process-group-configuration.css
index ca0a5dc..a72e060 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/remote-process-group-configuration.css
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/css/remote-process-group-configuration.css
@@ -22,7 +22,7 @@
     position: absolute;
     overflow: hidden;
     width: 400px;
-    height: 315px;
+    height: 435px;
     font-size: 10px;
     z-index: 1201;
     display: none;
@@ -32,7 +32,7 @@
     position: absolute;
     overflow: hidden;
     width: 400px;
-    height: 315px;
+    height: 435px;
     font-size: 10px;
     z-index: 1201;
     display: none;
@@ -65,10 +65,34 @@
     margin-right: 20px;
 }
 
+#remote-process-group-transport-protocol-combo {
+    width: 160px;
+    height: 18px;
+    line-height: 18px;
+}
+
+div.remote-process-group-timeout-setting, 
div.remote-process-group-yield-duration-setting,
+div.remote-process-group-proxy-host-setting, 
div.remote-process-group-proxy-port-setting,
+div.remote-process-group-proxy-user-setting, 
div.remote-process-group-proxy-password-setting {
+    float: left;
+    width: 170px;
+}
+
+div.remote-process-group-yield-duration-setting,
+div.remote-process-group-proxy-port-setting,
+div.remote-process-group-proxy-password-setting {
+    margin-left: 36px;
+}
+
+#remote-process-group-configuration .small-setting-input {
+    width: 160px;
+}
+
 #remote-process-group-configuration input {
     width: 370px;
 }
 
+
 /* remote process group port configuration */
 
 div.remote-port-header {

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-remote-process-group-component.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-remote-process-group-component.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-remote-process-group-component.js
index 276b616..7e07552 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-remote-process-group-component.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/header/components/nf-ng-remote-process-group-component.js
@@ -23,17 +23,24 @@ nf.ng.RemoteProcessGroupComponent = function 
(serviceProvider) {
     /**
      * Create the controller and add to the graph.
      *
-     * @argument {string} remoteProcessGroupUri         The remote group uri.
      * @argument {object} pt                            The point that the 
remote group was dropped.
      */
-    var createRemoteProcessGroup = function (remoteProcessGroupUri, pt) {
+    var createRemoteProcessGroup = function (pt) {
+
         var remoteProcessGroupEntity = {
             'component': {
-                'targetUri': remoteProcessGroupUri,
+                'targetUri': $('#new-remote-process-group-uri').val(),
                 'position': {
                     'x': pt.x,
                     'y': pt.y
-                }
+                },
+                'communicationsTimeout': 
$('#new-remote-process-group-timeout').val(),
+                'yieldDuration': 
$('#new-remote-process-group-yield-duration').val(),
+                'transportProtocol': 
$('#new-remote-process-group-transport-protocol-combo').combo('getSelectedOption').value,
+                'proxyHost': $('#new-remote-process-group-proxy-host').val(),
+                'proxyPort': $('#new-remote-process-group-proxy-port').val(),
+                'proxyUser': $('#new-remote-process-group-proxy-user').val(),
+                'proxyPassword': 
$('#new-remote-process-group-proxy-password').val()
             }
         };
 
@@ -53,13 +60,35 @@ nf.ng.RemoteProcessGroupComponent = function 
(serviceProvider) {
                     'selectAll': true
                 });
 
+                // hide the dialog
+                $('#new-remote-process-group-dialog').modal('hide');
+
                 // update component visibility
                 nf.Canvas.View.updateVisibility();
 
                 // update the birdseye
                 nf.Birdseye.refresh();
             }
-        }).fail(nf.Common.handleAjaxError);
+        }).fail(function (xhr, status, error) {
+            if (xhr.status === 400) {
+                var errors = xhr.responseText.split('\n');
+
+                var content;
+                if (errors.length === 1) {
+                    content = $('<span></span>').text(errors[0]);
+                } else {
+                    content = nf.Common.formatUnorderedList(errors);
+                }
+
+                nf.Dialog.showOkDialog({
+                    dialogContent: content,
+                    overlayBackground: false,
+                    headerText: 'Configuration Error'
+                });
+            } else {
+                nf.Common.handleAjaxError(xhr, status, error);
+            }
+        });
     };
 
     function RemoteProcessGroupComponent() {
@@ -82,6 +111,8 @@ nf.ng.RemoteProcessGroupComponent = function 
(serviceProvider) {
              * Initialize the modal.
              */
             init: function () {
+                var defaultTimeout = "30 sec";
+                var defaultYieldDuration = "10 sec";
                 // configure the new remote process group dialog
                 this.getElement().modal({
                     headerText: 'Add Remote Process Group',
@@ -89,9 +120,31 @@ nf.ng.RemoteProcessGroupComponent = function 
(serviceProvider) {
                     handler: {
                         close: function () {
                             $('#new-remote-process-group-uri').val('');
+                            
$('#new-remote-process-group-timeout').val(defaultTimeout);
+                            
$('#new-remote-process-group-yield-duration').val(defaultYieldDuration);
+                            
$('#new-remote-process-group-transport-protocol-combo').combo('setSelectedOption',
 {
+                                value: 'RAW'
+                            });
+                            $('#new-remote-process-group-proxy-host').val('');
+                            $('#new-remote-process-group-proxy-port').val('');
+                            $('#new-remote-process-group-proxy-user').val('');
+                            
$('#new-remote-process-group-proxy-password').val('');
                         }
                     }
                 });
+                // set default values
+                $('#new-remote-process-group-timeout').val(defaultTimeout);
+                
$('#new-remote-process-group-yield-duration').val(defaultYieldDuration);
+                // initialize the transport protocol combo
+                $('#new-remote-process-group-transport-protocol-combo').combo({
+                    options: [{
+                            text: 'RAW',
+                            value: 'RAW'
+                        }, {
+                            text: 'HTTP',
+                            value: 'HTTP'
+                        }]
+                });
             },
 
             /**
@@ -162,14 +215,8 @@ nf.ng.RemoteProcessGroupComponent = function 
(serviceProvider) {
         promptForRemoteProcessGroupUri: function(pt) {
             var self = this;
             var addRemoteProcessGroup = function () {
-                // get the uri of the controller and clear the textfield
-                var remoteProcessGroupUri = 
$('#new-remote-process-group-uri').val();
-
-                // hide the dialog
-                self.modal.hide();
-
                 // create the remote process group
-                createRemoteProcessGroup(remoteProcessGroupUri, pt);
+                createRemoteProcessGroup(pt);
             };
 
             this.modal.update('setButtonModel', [{

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js
index f30faa8..1a0d9db 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-configuration.js
@@ -36,7 +36,12 @@ nf.RemoteProcessGroupConfiguration = (function () {
                                     'component': {
                                         id: remoteProcessGroupId,
                                         communicationsTimeout: 
$('#remote-process-group-timeout').val(),
-                                        yieldDuration: 
$('#remote-process-group-yield-duration').val()
+                                        yieldDuration: 
$('#remote-process-group-yield-duration').val(),
+                                        transportProtocol: 
$('#remote-process-group-transport-protocol-combo').combo('getSelectedOption').value,
+                                        proxyHost: 
$('#remote-process-group-proxy-host').val(),
+                                        proxyPort: 
$('#remote-process-group-proxy-port').val(),
+                                        proxyUser: 
$('#remote-process-group-proxy-user').val(),
+                                        proxyPassword: 
$('#remote-process-group-proxy-password').val()
                                     }
                                 };
 
@@ -91,9 +96,26 @@ nf.RemoteProcessGroupConfiguration = (function () {
                         $('#remote-process-group-url').text('');
                         $('#remote-process-group-timeout').val('');
                         $('#remote-process-group-yield-duration').val('');
+                        
$('#remote-process-group-transport-protocol-combo').combo('setSelectedOption', {
+                            value: 'RAW'
+                        });
+                        $('#remote-process-group-proxy-host').val('');
+                        $('#remote-process-group-proxy-port').val('');
+                        $('#remote-process-group-proxy-user').val('');
+                        $('#remote-process-group-proxy-password').val('');
                     }
                 }
             });
+            // initialize the transport protocol combo
+            $('#remote-process-group-transport-protocol-combo').combo({
+                options: [{
+                        text: 'RAW',
+                        value: 'RAW'
+                    }, {
+                        text: 'HTTP',
+                        value: 'HTTP'
+                    }]
+            });
         },
         
         /**
@@ -114,6 +136,15 @@ nf.RemoteProcessGroupConfiguration = (function () {
                 // populate the text fields
                 
$('#remote-process-group-timeout').val(selectionData.component.communicationsTimeout);
                 
$('#remote-process-group-yield-duration').val(selectionData.component.yieldDuration);
+                
$('#remote-process-group-proxy-host').val(selectionData.component.proxyHost);
+                
$('#remote-process-group-proxy-port').val(selectionData.component.proxyPort);
+                
$('#remote-process-group-proxy-user').val(selectionData.component.proxyUser);
+                
$('#remote-process-group-proxy-password').val(selectionData.component.proxyPassword);
+
+                // select the appropriate transport-protocol
+                
$('#remote-process-group-transport-protocol-combo').combo('setSelectedOption', {
+                    value: selectionData.component.transportProtocol
+                });
 
                 // show the details
                 $('#remote-process-group-configuration').modal('show');

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js
index bdc5679..8b2c28e 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-details.js
@@ -39,6 +39,11 @@ nf.RemoteProcessGroupDetails = (function () {
                         
nf.Common.clearField('read-only-remote-process-group-url');
                         
nf.Common.clearField('read-only-remote-process-group-timeout');
                         
nf.Common.clearField('read-only-remote-process-group-yield-duration');
+                        
nf.Common.clearField('read-only-remote-process-group-transport-protocol');
+                        
nf.Common.clearField('read-only-remote-process-group-proxy-host');
+                        
nf.Common.clearField('read-only-remote-process-group-proxy-port');
+                        
nf.Common.clearField('read-only-remote-process-group-proxy-user');
+                        
nf.Common.clearField('read-only-remote-process-group-proxy-password');
                     }
                 }
             });
@@ -60,6 +65,11 @@ nf.RemoteProcessGroupDetails = (function () {
                 nf.Common.populateField('read-only-remote-process-group-url', 
selectionData.component.targetUri);
                 
nf.Common.populateField('read-only-remote-process-group-timeout', 
selectionData.component.communicationsTimeout);
                 
nf.Common.populateField('read-only-remote-process-group-yield-duration', 
selectionData.component.yieldDuration);
+                
nf.Common.populateField('read-only-remote-process-group-transport-protocol', 
selectionData.component.transportProtocol);
+                
nf.Common.populateField('read-only-remote-process-group-proxy-host', 
selectionData.component.proxyHost);
+                
nf.Common.populateField('read-only-remote-process-group-proxy-port', 
selectionData.component.proxyPort);
+                
nf.Common.populateField('read-only-remote-process-group-proxy-user', 
selectionData.component.proxyUser);
+                
nf.Common.populateField('read-only-remote-process-group-proxy-password', 
selectionData.component.proxyPassword);
 
                 // show the details
                 $('#remote-process-group-details').modal('show');

http://git-wip-us.apache.org/repos/asf/nifi/blob/c120c498/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
index c264588..baeed4c 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-remote-process-group-ports.js
@@ -43,6 +43,7 @@ nf.RemoteProcessGroupPorts = (function () {
                                     'revision': 
nf.Client.getRevision(remoteProcessGroupData),
                                     'remoteProcessGroupPort': {
                                         id: remotePortId,
+                                        groupId: remoteProcessGroupId,
                                         useCompression: 
$('#remote-port-use-compression').hasClass('checkbox-checked'),
                                         concurrentlySchedulableTaskCount: 
remotePortConcurrentTasks
                                     }
@@ -454,7 +455,7 @@ nf.RemoteProcessGroupPorts = (function () {
                     },
                     dataType: 'json'
                 }).done(function (response) {
-                    var remoteProcessGroup = response.remoteProcessGroup;
+                    var remoteProcessGroup = response.component;
 
                     // set the model locally
                     nf.RemoteProcessGroup.set(response);

Reply via email to