/*
* Copyright 2014 Avanza Bank AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.avanza.astrix.netty;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avanza.astrix.beans.service.BoundServiceBeanInstance;
import com.avanza.astrix.beans.service.ServiceComponent;
import com.avanza.astrix.beans.service.ServiceDefinition;
import com.avanza.astrix.beans.service.ServiceProperties;
import com.avanza.astrix.beans.service.SimpleBoundServiceBeanInstance;
import com.avanza.astrix.core.remoting.RoutingStrategy;
import com.avanza.astrix.netty.client.NettyRemotingClient;
import com.avanza.astrix.netty.server.NettyRemotingServer;
import com.avanza.astrix.remoting.client.RemotingProxyFactory;
import com.avanza.astrix.remoting.server.AstrixServiceActivator;
import com.avanza.astrix.versioning.core.AstrixObjectSerializer;
import com.avanza.astrix.versioning.core.ObjectSerializerFactory;
/**
* This component is in a (very) experimental state.
*
* @author Elias Lindholm
*
*/
public class NettyRemotingComponent implements ServiceComponent {
private Logger log = LoggerFactory.getLogger(NettyRemotingComponent.class);
private static final String NETTY_PORT = "astrix.netty.port";
private static final String NETTY_HOST = "astrix.netty.host";
public static final String NAME = "netty-remoting";
private final RemotingProxyFactory remotingProxyFactory;
private final AstrixServiceActivator serviceActivator;
private final ObjectSerializerFactory objectSerializerFactory;
private final NettyRemotingServer remotingServer;
public NettyRemotingComponent(RemotingProxyFactory remotingProxyFactory, AstrixServiceActivator serviceActivator,
ObjectSerializerFactory objectSerializerFactory, NettyRemotingServer remotingServer) {
this.remotingProxyFactory = remotingProxyFactory;
this.serviceActivator = serviceActivator;
this.objectSerializerFactory = objectSerializerFactory;
this.remotingServer = remotingServer;
}
@Override
public <T> BoundServiceBeanInstance<T> bind(ServiceDefinition<T> serviceDefinition, ServiceProperties serviceProperties) {
String host = serviceProperties.getProperty(NETTY_HOST);
int port = Integer.valueOf(serviceProperties.getProperty(NETTY_PORT));
log.info("Connecting to: {}:{}", host, port);
NettyRemotingClient remotingClient = new NettyRemotingClient();
remotingClient.connect(host, port);
NettyRemotingTransport nettyRemotingTransport = new NettyRemotingTransport(remotingClient);
T serviceProxy = remotingProxyFactory.create(serviceDefinition, serviceProperties, nettyRemotingTransport, new RoutingStrategy.RoundRobin());
return new SimpleBoundServiceBeanInstance<T>(serviceProxy); // TODO: proper lifecycle-management of remotingClient instance
}
@Override
public ServiceProperties parseServiceProviderUri(String serviceProviderUri) {
String[] hostAndPort = serviceProviderUri.split(":");
ServiceProperties result = new ServiceProperties();
result.getProperties().put(NETTY_HOST, hostAndPort[0]);
result.getProperties().put(NETTY_PORT, hostAndPort[1]);
return result;
}
@Override
public <T> ServiceProperties createServiceProperties(ServiceDefinition<T> exportedServiceDefinition) {
ServiceProperties properties = new ServiceProperties();
properties.getProperties().put(NETTY_HOST, getHostName()); // TODO
properties.getProperties().put(NETTY_PORT, Integer.toString(remotingServer.getPort()));
return properties;
}
private String getHostName() {
try {
InetAddress localHost = java.net.InetAddress.getLocalHost();
return localHost.getHostName();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
@Override
public String getName() {
return NAME;
}
@Override
public boolean canBindType(Class<?> type) {
return true;
}
@Override
public <T> void exportService(Class<T> providedApi, T provider, ServiceDefinition<T> serviceDefinition) {
// TODO: this responsibility does not belong in service component. Introduce RemotingServer abstraction
AstrixObjectSerializer objectSerializer = objectSerializerFactory.create(serviceDefinition.getObjectSerializerDefinition());
this.serviceActivator.register(provider, objectSerializer, providedApi);
this.remotingServer.verifyStarted();
}
@Override
public boolean requiresProviderInstance() {
return true;
}
}