Re: Select the output-network-interface to call an axis-webservice
Hi Alain, Hi Rodrigo, that's great! Your solution-samples are looking incredible. I hope, I'll find time to realise it the next days. I'm just a bit confused about the client-config.wsdd-file because I don't have such a file right now. Sure I know the server-config.wsdd, but a clientprogram will not be deployed, or will it? And if the program never used this wsdd before, how can I tell it to do so? My experiences with axis are quite simple yet, so I am not sure I haven't overlooked something important about this. BTW: At the moment I'm using libraries from axis 1.3 (Download archive from october 05). Anyway, let me tell you I really appreciate to your support so far. Carsten Am Dienstag, den 16.05.2006, 16:47 +0200 schrieb Rodrigo Ruiz: CommonsHTTPSender is easier to subclass and modify. I pass you a simple subclass that could do the trick :-) HTH, Rodrigo package org.rodrisoft; import java.io.FileInputStream; import java.io.InputStream; import java.net.InetAddress; import java.net.URL; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.Properties; import org.apache.axis.MessageContext; import org.apache.axis.transport.http.CommonsHTTPSender; import org.apache.commons.httpclient.HostConfiguration; import org.apache.commons.httpclient.HttpClient; /** * Sender implementation that uses Jakarta Commons HTTP for transmission, and * implements a routing map table to select a local address depending on the * remote address to connect to. * p * This sender can be configured in the client-config.wsdd file like this: * pre * lt;transport name=http * pivot=java:org.rodrisoft.RoutedCommonsHTTPSender * lt;parameter name=map-file value=path/to/map/file.properties/ * lt;parameter name=map:remote-addr value=10.33.5.67/ * lt;/transport * /pre * p * The first parameter specifies a .properties file containing pairs in * the form: * * pre * remote-addr=remote-addr * /pre * * The second parameter is an example of how to specify a single route * table entry directly in the .wsdd file. * p * The first parameter allows to share the route table among several * protocols. * p * The local binding address can also be specified through the message * context. This allows services and handlers set the local address, and * provide smarter routing algorithms. * p * Original work from Davanum Srinivas. * * @author Davanum Srinivas ([EMAIL PROTECTED]) * @author Rodrigo Ruiz ([EMAIL PROTECTED]) * @version 1.0 */ public class RoutedCommonsHTTPSender extends CommonsHTTPSender { /** * codeserialVersionUID/code attribute. */ private static final long serialVersionUID = -8610352356067978620L; /** * MessageContext Property name for setting the local bind address. */ public static final String LOCAL_BIND_ADDRESS = local.bind.address; /** * Local Bind Address Route Map. */ private final Map routeTable = new HashMap(); /** * Flag that controls bindMap synchronization. */ private boolean dirty = true; public synchronized void setOption(String name, Object value) { this.dirty = true; super.setOption(name, value); } public synchronized boolean setOptionDefault(String name, Object value) { this.dirty = true; return super.setOptionDefault(name, value); } public synchronized void setOptions(Hashtable options) { this.dirty = true; super.setOptions(options); } protected HostConfiguration getHostConfiguration(HttpClient client, MessageContext context, URL targetURL) { HostConfiguration config = super.getHostConfiguration(client, context, targetURL); if (targetURL != null) { String remoteHost = targetURL.getHost(); InetAddress localAddr = getRouteFor(context, remoteHost); if (localAddr != null) { config.setLocalAddress(localAddr); } } return config; } /** * This utility method allows to force the route table to be rebuilt. * It can be useful if the route table file is modified, and we can * manage to get the instance of this handler. */ public void rebuildTable() { this.dirty = true; } /** * Gets a route for the specified remote address, allowing it to be * specified through a Message Context parameter. * * @param ctx The message context * @param host The remote host to map * @return The mapped address, or null if none found
Re: Select the output-network-interface to call an axis-webservice
Hi Rodrigo, these ideas are very interesting. First of all, thanks a lot for that. But for the first way of making the host address configurable, I still have to ask you, how to do that in detail? I don't mean how to read the address from a properties file, but how can I set the value? Carsten Am Montag, den 15.05.2006, 17:28 +0200 schrieb Rodrigo Ruiz: Carsten, In fact, there are several ways to handle your situation, but I guess almost none of them is as simple as adding some lines to your client code. The ones I know are: - Make the host address configurable. That is, read the host address from a configuration file. I know this is not what you are asking for, but it is probably the only easy workaround to your problem. In fact, I think it will be the only one that will work if you want to test your client application from the same host, and manually select the adapter to use. - You may use DNS to provide a common name to your server, and access it through host name, instead of host address. This probably means some work to get your client domain name, in order to build the complete host name in each subnetwork, or be sure that using the host name without a domain name will return you the correct host address in all cases. - In a more complicated fashion, you could decide to convert your service in a standard service, and register it into your DNS servers. DNS protocol allows to register the addresses for standard services, providing a simplistic discovery service, and allowing you to ask for a service name, instead of a host name. AFAIK, this option is not usual, but it should work. I am not sure, but you may probably need to use Jakarta commons-net library to perform such kind of queries to your DNS server. - You can delegate the problem to a well-known UDDI server. Anyway, if you use TCP/IP, this will just move your problem from one host to another, as this UDDI server/s will probably also have different addresses in each sub-network. - You might use some UDP based discovery service. The idea in this case would be to send a broadcast message, and receive the appropriate address from some arbitrary point on your network. If you implement such a service in your own server, you will probably be able to get the host address from the response message meta-data itself. There are some standard libraries for achieving this out there, or you could try to implement your own, as it is plenty of examples on Google ;-) Hope this helps, Rodrigo Carsten Schmidt wrote: Hi Alain, thanks for your answer, but it seems as if the NetworkInterface-class would just be able to give you information about the interfaces. For me, it is important to tell the program which Interface to use, because the webserver I'm working on got different IP's in different sub-networks. So, I am looking for a method like setHostAdress(foo). Maybe this is more a part of java than axis, but the Axis-Call-class seems to handle the whole hardware/network-stuff on it's own. I can't believe that there is no smart way to handle this. Carsten Am Montag, den 15.05.2006, 16:28 +0200 schrieb Pannetier Alain: Hi Carsten, Here is an example I use to know whether I'm in the office or at home : try { Enumeration myInterfaces = NetworkInterface.getNetworkInterfaces(); interfaceEnum: while ( myInterfaces.hasMoreElements()) { NetworkInterface netInterf = (NetworkInterface) myInterfaces.nextElement(); Enumeration addresses = netInterf.getInetAddresses() ; while (addresses.hasMoreElements()) { InetAddress address = (InetAddress) addresses.nextElement(); if ( address.getHostAddress().startsWith( OFFICE_PREFIX ) ) { isAtTheOffice = true ; break interfaceEnum ; } } } } catch (SocketException e) { e.printStackTrace(); } ... It shows how to loop on all your interfaces and select one (according to its address prefix...). That's probably close to what your're after. Alain -Original Message- From: Schmidt, Carsten -81.01- [mailto:[EMAIL PROTECTED] Sent: 15 May 2006 16:17 To: axis-user@ws.apache.org Subject: RE: Select the output-network-interface to call an axis-webservice Hi, did really no one every had a problem like that? This problem can not be so special, can it? But maybe you know another mailinglist or a book, which might be able to help me? It is really important for me to find a solution for that, and meanwhile I ain't got no more idea where to look at. Regards, Carsten Hi
Re: Select the output-network-interface to call an axis-webservice
Hi, oh, maybe we missunderstood each other. There is no problem with the IP the service is running on. On another machine a servlet is calling this service. For this call I have to determine a special outgoing-IP, because it is a webserver on which each webapp has it's own virtual-IP. Only the IP from the app has the necessary permissions to pass the firewall correctly. By default the axis-call doesn't use the virtual-IP from the webapp-context, but the IP from the server itself. In detail: Webserver with the IP 10.33.5.1 Virtual IP for the webapp 10.33.5.67 Carsten Am Dienstag, den 16.05.2006, 09:47 +0200 schrieb Rodrigo Ruiz: Ok, If you look at the very first example in the users guide: 1 import org.apache.axis.client.Call; 2 import org.apache.axis.client.Service; 3 import javax.xml.namespace.QName; 4 5 public class TestClient { 6 public static void main(String [] args) { 7 try { 8 String endpoint = 9 http://ws.apache.org:5049/axis/services/echo;; 10 11Service service = new Service(); 12Call call= (Call) service.createCall(); 13 14call.setTargetEndpointAddress( new java.net.URL(endpoint) ); 15call.setOperationName(new QName(http://soapinterop.org/;, echoString)); 16 17String ret = (String) call.invoke( new Object[] { Hello! } ); 18 19System.out.println(Sent 'Hello!', got ' + ret + '); 20 } catch (Exception e) { 21System.err.println(e.toString()); 22 } 23} 24 } You can see that the service endpoint is a URL declared at lines 8-9. You simply have to build this URL using the host you have read from your configuration file. If you are working with generated stubs, you will find that your Service class has at least two getPortName() methods (more if you use a WS-Addressing aware generator). One of these methods gets a URL instance as a parameter. This URL must contain the endpoint URL, that is, the same URL you would use in the example above. Therefore, you can again build this URL using your configured host name. You may allow configuring only a part of your endpoints, like in: String hostName = myProps.getProperty(hostName); URL url = new URL(http://; + hostName + /axis/services/echo); or you may get the full endpoint URL from your configuration file, like: String echoEndpoint = myProps.getProperty(Endpoint.Echo); URL url = new URL(echoEndpoint); I personally think the second option gives you more freedom to change your server deployment at will. HTH, Rodrigo Carsten Schmidt wrote: Hi Rodrigo, these ideas are very interesting. First of all, thanks a lot for that. But for the first way of making the host address configurable, I still have to ask you, how to do that in detail? I don't mean how to read the address from a properties file, but how can I set the value? Carsten Am Montag, den 15.05.2006, 17:28 +0200 schrieb Rodrigo Ruiz: Carsten, In fact, there are several ways to handle your situation, but I guess almost none of them is as simple as adding some lines to your client code. The ones I know are: - Make the host address configurable. That is, read the host address from a configuration file. I know this is not what you are asking for, but it is probably the only easy workaround to your problem. In fact, I think it will be the only one that will work if you want to test your client application from the same host, and manually select the adapter to use. - You may use DNS to provide a common name to your server, and access it through host name, instead of host address. This probably means some work to get your client domain name, in order to build the complete host name in each subnetwork, or be sure that using the host name without a domain name will return you the correct host address in all cases. - In a more complicated fashion, you could decide to convert your service in a standard service, and register it into your DNS servers. DNS protocol allows to register the addresses for standard services, providing a simplistic discovery service, and allowing you to ask for a service name, instead of a host name. AFAIK, this option is not usual, but it should work. I am not sure, but you may probably need to use Jakarta commons-net library to perform such kind of queries to your DNS server. - You can delegate the problem to a well-known UDDI server. Anyway, if you use TCP/IP, this will just move your problem from one host to another, as this UDDI server/s will probably also have different addresses in each sub-network. - You might use some UDP based discovery service. The idea in this case would
Re: Select the output-network-interface to call an axis-webservice
Ok, it is about the communication between two Webservers (with Tomcat as Servlet Engine). My local Server provides a Servlet. Well, it provides lots of Servlets on different tomcats. Each of these tomcats has its own virtual IP apache listens on. The server itself has another IP (Which is not used by an application but to administrate the server). The servlet calls an axis-service which runs on a completely different server in another company. The IP from my server (let's take 10.33.5.1. for example) is not allowed to access the non-local webservice. This is not changeable, the reason that for is uninteresting at the moment. The only IP, which can access is the one of my servlet (in this case 10.33.5.67). If I am starting this servlet from my pc (10.33.5.100) it should run like this: 10.33.5.100 (Browser) - 10.33.5.67 (Tomcat) 10.33.5.67 (Servlet running in Tomcat) - WebService anywhere in the internet (including the answer, because axis handels this) 10.33.5.67 (Tomcat returns the generated website) - 10.33.5.100 (Browser) but this way is broken because: 10.33.5.100 (Browser) - 10.33.5.67 (Tomcat) 10.33.5.1 tries to connect the webservice, what is denied by firewall. With NetworkInterface.getNetworkInterfaces() it shows my all IPs existing on the server. But it seems as if there was no way of manuelly choosing which IP to use for an axis-connection. This topic is awful, I know;-)) Am Dienstag, den 16.05.2006, 13:03 +0200 schrieb Rodrigo Ruiz: Wow! Ok, I guess the solution to your problem will depend on where do you want to set the address. Could you elaborate a bit more? Are you talking about the client-side or the server-side? I guess you are talking about the server response, but I am not sure. Could you describe a bit your server deployment configuration? Do you have a single Axis webapp and you want to customize its behavior depending on the incoming network adapter, or you have separate webapps for each virtual-IP? Regards, Rodrigo Carsten Schmidt wrote: Hi, oh, maybe we missunderstood each other. There is no problem with the IP the service is running on. On another machine a servlet is calling this service. For this call I have to determine a special outgoing-IP, because it is a webserver on which each webapp has it's own virtual-IP. Only the IP from the app has the necessary permissions to pass the firewall correctly. By default the axis-call doesn't use the virtual-IP from the webapp-context, but the IP from the server itself. In detail: Webserver with the IP 10.33.5.1 Virtual IP for the webapp 10.33.5.67 Carsten Am Dienstag, den 16.05.2006, 09:47 +0200 schrieb Rodrigo Ruiz: Ok, If you look at the very first example in the users guide: 1 import org.apache.axis.client.Call; 2 import org.apache.axis.client.Service; 3 import javax.xml.namespace.QName; 4 5 public class TestClient { 6 public static void main(String [] args) { 7 try { 8 String endpoint = 9 http://ws.apache.org:5049/axis/services/echo;; 10 11Service service = new Service(); 12Call call= (Call) service.createCall(); 13 14call.setTargetEndpointAddress( new java.net.URL(endpoint) ); 15call.setOperationName(new QName(http://soapinterop.org/;, echoString)); 16 17String ret = (String) call.invoke( new Object[] { Hello! } ); 18 19System.out.println(Sent 'Hello!', got ' + ret + '); 20 } catch (Exception e) { 21System.err.println(e.toString()); 22 } 23} 24 } You can see that the service endpoint is a URL declared at lines 8-9. You simply have to build this URL using the host you have read from your configuration file. If you are working with generated stubs, you will find that your Service class has at least two getPortName() methods (more if you use a WS-Addressing aware generator). One of these methods gets a URL instance as a parameter. This URL must contain the endpoint URL, that is, the same URL you would use in the example above. Therefore, you can again build this URL using your configured host name. You may allow configuring only a part of your endpoints, like in: String hostName = myProps.getProperty(hostName); URL url = new URL(http://; + hostName + /axis/services/echo); or you may get the full endpoint URL from your configuration file, like: String echoEndpoint = myProps.getProperty(Endpoint.Echo); URL url = new URL(echoEndpoint); I personally think the second option gives you more freedom to change your server deployment at will. HTH, Rodrigo Carsten Schmidt wrote: Hi Rodrigo, these ideas are very interesting
RE: Select the output-network-interface to call an axis-webservice
Hi Alain, thanks for your answer, but it seems as if the NetworkInterface-class would just be able to give you information about the interfaces. For me, it is important to tell the program which Interface to use, because the webserver I'm working on got different IP's in different sub-networks. So, I am looking for a method like setHostAdress(foo). Maybe this is more a part of java than axis, but the Axis-Call-class seems to handle the whole hardware/network-stuff on it's own. I can't believe that there is no smart way to handle this. Carsten Am Montag, den 15.05.2006, 16:28 +0200 schrieb Pannetier Alain: Hi Carsten, Here is an example I use to know whether I'm in the office or at home : try { Enumeration myInterfaces = NetworkInterface.getNetworkInterfaces(); interfaceEnum: while ( myInterfaces.hasMoreElements()) { NetworkInterface netInterf = (NetworkInterface) myInterfaces.nextElement(); Enumeration addresses = netInterf.getInetAddresses() ; while (addresses.hasMoreElements()) { InetAddress address = (InetAddress) addresses.nextElement(); if ( address.getHostAddress().startsWith( OFFICE_PREFIX ) ) { isAtTheOffice = true ; break interfaceEnum ; } } } } catch (SocketException e) { e.printStackTrace(); } ... It shows how to loop on all your interfaces and select one (according to its address prefix...). That's probably close to what your're after. Alain -Original Message- From: Schmidt, Carsten -81.01- [mailto:[EMAIL PROTECTED] Sent: 15 May 2006 16:17 To: axis-user@ws.apache.org Subject: RE: Select the output-network-interface to call an axis-webservice Hi, did really no one every had a problem like that? This problem can not be so special, can it? But maybe you know another mailinglist or a book, which might be able to help me? It is really important for me to find a solution for that, and meanwhile I ain't got no more idea where to look at. Regards, Carsten Hi everybody, maybe this question has already been answered a thousend times, but I haven't found anything about it. I got a server with a few different network adapters. Each of them with a different IP. Now I'm searching for a way to call a webservice by choosing exacly one of those adapters (which is not the default one). How can I do than? java.net.NetworkInterface shows me what is available, but where can it set what to use? org.apache.axis.client.Call? org.apache.axis.client.Service? Can anybody help me? Carsten