• How to add a web service interface to Wowza Media Server and integrate with .NET (dotNet)

    The following is a server listener class that is invoked when a Wowza media server starts. You can download a pre-built version of this web service.

    ServerListenerWowzaServerWS.java
    package com.wowza.wms.plugin.test.ws;
    
    import com.wowza.wms.logging.*; 
    import com.wowza.wms.server.*;
    import com.wowza.wms.application.*;
    
    public class ServerListenerWowzaServerWS implements IServerNotify
    {
    	private String hostname = "localhost";
    	private int port = 9091;
    	private String serviceName = "wowzaserverws";
    
    	private WowzaServerWebService ws = null;
    	
    	public void onServerCreate(IServer server)
    	{
    	}
    
    	public void onServerInit(IServer server)
    	{
    		WMSProperties props = server.getProperties();
    		
    		this.hostname = props.getPropertyStr("wsIpAddress", this.hostname);
    		this.serviceName = props.getPropertyStr("wsServiceName", this.serviceName);
    		this.port = props.getPropertyInt("wsPort", this.port);
    		
    		WMSLoggerFactory.getLogger(null).info("ServerListenerWowzaServerWS.onServerInit: http://"+hostname+":"+port+"/"+serviceName);
    		this.ws = new WowzaServerWebService();
    		this.ws.bind(hostname, port, serviceName);
    	}
    
    	public void onServerShutdownStart(IServer server)
    	{
    		WMSLoggerFactory.getLogger(null).info("ServerListenerWowzaServerWS.onServerShutdownStart: http://"+hostname+":"+port+"/"+serviceName);
    		if (this.ws != null)
    			this.ws.shutdown();
    		this.ws = null;
    	}
    
    	public void onServerShutdownComplete(IServer server)
    	{
    	}
    }
    This is the actual Web Services class:

    WowzaServerWebService.java
    package com.wowza.wms.plugin.test.ws;
    
    import javax.jws.*;
    import javax.xml.ws.*;
    
    import com.wowza.wms.application.*;
    import com.wowza.wms.logging.*;
    import com.wowza.wms.server.*;
    import com.wowza.wms.vhost.*;
    
    import edu.emory.mathcs.backport.java.util.concurrent.locks.*;
    
    @WebService
    
    public class WowzaServerWebService
    {
    	private Endpoint endpoint = null;
    	
    	public static final String DEFAULT_VHOST = "_defaultVHost_";
    	public static final String DEFAULT_APPLICATION = "_defapp_";
    	public static final String DEFAULT_APPINSTANCE = "_definst_";
    
    	public static class AppConextName
    	{
    		String vhostName = null;
    		String appName = null;
    		String appInstName = null;
    		
    		public AppConextName()
    		{
    		}
    		
    		public AppConextName(String fullname, boolean startWithDefaults)
    		{
    			if (startWithDefaults)
    			{
    				vhostName = DEFAULT_VHOST;
    				appName = DEFAULT_APPLICATION;
    				appInstName = DEFAULT_APPINSTANCE;
    			}
    
    			int qloc = fullname.indexOf(":");
    			if (qloc >= 0)
    			{
    				vhostName = fullname.substring(0, qloc);
    				fullname = fullname.substring(qloc+1);
    			}
    			else
    				vhostName = DEFAULT_VHOST;
    			
    			if (fullname.length() > 0)
    			{
    				appName = fullname;
    				int sloc = fullname.indexOf("/");
    				if (sloc >= 0)
    				{
    					appName = fullname.substring(0, sloc);
    					appInstName = fullname.substring(sloc+1);
    				}
    			}
    		}
    		
    		String getObjName()
    		{
    			String ret = "";
    			
    			while(true)
    			{
    				if (vhostName == null)
    					break;
    				
    				ret += "vHosts=VHosts,vHostName="+vhostName;
    				
    				if (appName == null)
    					break;
    				
    				ret += ",applications=Applications,applicationName="+appName;
    				
    				if (appInstName == null)
    					break;
    				
    				ret += ",applicationInstances=ApplicationInstances,applicationInstanceName="+appInstName;
    				break;
    			}
    									
    			return ret;
    		}
    	}
    
    	public WowzaServerWebService()
    	{
    		
    	}
    		
    	public void bind(String host, int port, String path)
    	{
    		String endpointURL = "http://"+host+":"+port+"/"+path;
    		try
    		{
    			endpoint = Endpoint.publish(endpointURL, this);
    			WMSLoggerFactory.getLogger(null).info("WowzaServerWebService.bind: "+endpointURL);
    		}
    		catch (Exception e)
    		{
    			WMSLoggerFactory.getLogger(null).error("WowzaServerWebService.host: "+e.toString());
    		}
    	}
    	
    	public void shutdown()
    	{
    		WMSLoggerFactory.getLogger(null).info("WowzaServerWebService.shutdown");
    		if (endpoint != null)
    			endpoint.stop();
    		endpoint = null;
    	}
    
    	@WebMethod
    	public String getServerVersion()
    	{
    		IServer server = Server.getInstance();
    		WMSLoggerFactory.getLogger(null).info("WowzaServerWebService.getServerVersion: "+server.getVersion());
    		return server.getVersion();
    	}
    	
    	@WebMethod
    	public void startAppInstance(String appInstanceStr)
    	{
    		WMSLoggerFactory.getLogger(null).info("WowzaServerWebService.startAppInstance: appInstance:"+appInstanceStr);
    
    		AppConextName context = new AppConextName(appInstanceStr, true);
    		
    		try
    		{
    			while(true)
    			{
    				IVHost vhost = VHostSingleton.getInstance(context.vhostName);
    				if (vhost == null)
    				{
    					WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.stopAppInstance: vhost missing: "+context.vhostName);
    					break;
    				}
    				
    				vhost.startApplicationInstance(context.appName, context.appInstName);
    				break;
    			}
    		}
    		catch(Exception e)
    		{
    			WMSLoggerFactory.getLogger(null).error("WowzaServerWebService.startAppInstance: "+e.toString());
    		}		
    	}
    
    	@WebMethod
    	public void stopAppInstance(String appInstanceStr)
    	{
    		WMSLoggerFactory.getLogger(null).info("WowzaServerWebService.stopAppInstance: appInstance:"+appInstanceStr);
    
    		AppConextName context = new AppConextName(appInstanceStr, true);
    		
    		try
    		{
    			while(true)
    			{
    				IVHost vhost = VHostSingleton.getInstance(context.vhostName);
    				if (vhost == null)
    				{
    					WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.stopAppInstance: vhost missing: "+context.vhostName);
    					break;
    				}
    				
    				IApplication application = vhost.getApplication(context.appName);
    				if (application == null)
    				{
    					WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.stopAppInstance: application missing: "+context.appName);
    					break;
    				}
    				
    				application.shutdownAppInstance(context.appInstName);
    				break;
    			}
    		}
    		catch(Exception e)
    		{
    			WMSLoggerFactory.getLogger(null).error("WowzaServerWebService.stopAppInstance: "+e.toString());
    		}		
    	}
    
    	@WebMethod
    	public void startMediaCasterStream(String appInstanceStr, String streamName, String mediaCasterType)
    	{
    		WMSLoggerFactory.getLogger(null).info("WowzaServerWebService.startMediaCasterStream: appInstance:"+appInstanceStr+" streamName:"+streamName+" mediaCasterType:"+mediaCasterType);
    
    		AppConextName context = new AppConextName(appInstanceStr, true);
    		
    		try
    		{
    			while(true)
    			{
    				IVHost vhost = VHostSingleton.getInstance(context.vhostName);
    				if (vhost == null)
    				{
    					WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.startMediaCasterStream: vhost missing: "+context.vhostName);
    					break;
    				}
    				
    				vhost.startApplicationInstance(context.appName, context.appInstName);
    				
    				WMSReadWriteLock lock = vhost.getApplicationLock();
    				
    				IApplication application = null;
    				IApplicationInstance appInstance = null;
    				try
    				{
    					lock.writeLock().lock();
    					application = vhost.getApplication(context.appName);
    					if (application == null)
    						WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.startMediaCasterStream: application missing: "+context.appName);
    					else
    						appInstance = application.getAppInstance(context.appInstName);
    					
    					if (appInstance == null)
    						WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.startMediaCasterStream: appInstance missing: "+context.appInstName);
    				}
    				catch(Exception e)
    				{	
    				}
    				finally
    				{
    					lock.writeLock().unlock();
    				}
    				
    				if (appInstance == null)
    					break;
    				
    				appInstance.startMediaCasterStream(streamName, mediaCasterType);
    				break;
    			}
    		}
    		catch(Exception e)
    		{
    			WMSLoggerFactory.getLogger(null).error("WowzaServerWebService.startMediaCasterStream: "+e.toString());
    		}		
    	}
    
    	@WebMethod
    	public void stopMediaCasterStream(String appInstanceStr, String streamName)
    	{
    		WMSLoggerFactory.getLogger(null).info("WowzaServerWebService.stopMediaCasterStream: appInstance:"+appInstanceStr+" streamName:"+streamName);
    
    		AppConextName context = new AppConextName(appInstanceStr, true);
    		
    		try
    		{
    			while(true)
    			{
    				IVHost vhost = VHostSingleton.getInstance(context.vhostName);
    				if (vhost == null)
    				{
    					WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.stopMediaCasterStream: vhost missing: "+context.vhostName);
    					break;
    				}
    				
    				vhost.startApplicationInstance(context.appName, context.appInstName);
    				
    				WMSReadWriteLock lock = vhost.getApplicationLock();
    				
    				IApplication application = null;
    				IApplicationInstance appInstance = null;
    				try
    				{
    					lock.writeLock().lock();
    					application = vhost.getApplication(context.appName);
    					if (application == null)
    						WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.startMediaCasterStream: application missing: "+context.appName);
    					else
    						appInstance = application.getAppInstance(context.appInstName);
    					
    					if (appInstance == null)
    						WMSLoggerFactory.getLogger(null).warn("WowzaServerWebService.startMediaCasterStream: appInstance missing: "+context.appInstName);
    				}
    				catch(Exception e)
    				{	
    				}
    				finally
    				{
    					lock.writeLock().unlock();
    				}
    				
    				if (appInstance == null)
    					break;
    				
    				appInstance.stopMediaCasterStream(streamName);
    				break;
    			}
    		}
    		catch(Exception e)
    		{
    			WMSLoggerFactory.getLogger(null).error("WowzaServerWebService.stopMediaCasterStream: "+e.toString());
    		}		
    	}
    }
    This is an ant build script that compiles and builds the solution. To use this with the Wowza IDE, the ant script components must be integrated into the build.xml file that's created during the new project creation process. Directory paths must be updated accordingly.

    Ant build script
    <?xml version="1.0"?>
    <project name="wstest" default="jar" basedir="..">
    	
    	<property name="wowza.home" value="c:/projects/wms200"/>
    	<property name="project.home" value="c:/projects/workspace/jaxws"/>
    	<property name="java6.home" value="C:/jdk1.6.0_18"/>
    
    	<property name="wowza.lib.dir" value="${wowza.home}/lib"/>
    	<property name="project.bin.dir" value="${project.home}/bin"/>
    	<property name="project.src.dir" value="${project.home}/src"/>
    	<property name="project.wsdl.dir" value="${project.home}/wsdl"/>
    
    	<property name="jar.filename" value="wms-plugin-wowzaserverws.jar"/>
    
    	<path id="project.class.path">
    		<fileset dir="${wowza.lib.dir}">
    			<include name="**/*.jar"/>
    			<exclude name="${jar.filename}"/>
    		</fileset>
    		<pathelement location="${java6.home}/jre/lib/rt.jar"/>
    		<pathelement location="${java6.home}/jre/lib/jsse.jar"/>
        		<pathelement location="${java6.home}/lib/tools.jar"/>
    	</path>
    
    	<target name="prepare">
    		<delete dir="${project.bin.dir}/com"/>
    	</target>
    
    	<target name="compile" depends="prepare">
    		<javac srcdir="${project.src.dir}" destdir="${project.bin.dir}" debug="on" optimize="on" deprecation="on" verbose="off">
    			<classpath refid="project.class.path"/>
    		</javac>
    	</target>
    
    	<target name="wsgen" depends="compile">
    		<exec executable="${java6.home}/bin/wsgen">
    			<arg value="-verbose"/>
    			<arg value="-cp"/>
    			<arg value="${project.bin.dir};${wowza.lib.dir}/wms-server.jar;${wowza.lib.dir}/wms-core.jar;${wowza.lib.dir}/log4j-1.2.15.jar"/>
    			<arg value="-d"/>
    			<arg value="${project.bin.dir}"/>
    			<arg value="-wsdl"/>
    			<arg value="-r"/>
    			<arg value="${project.wsdl.dir}"/>
    			<arg value="com.wowza.wms.plugin.test.ws.WowzaServerWebService"/>
    		</exec>
    	</target>
    
    	<target name="jar" depends="wsgen">
    		<jar jarfile="${wowza.lib.dir}/${jar.filename}">
    			<fileset dir="${project.bin.dir}"/>
    		</jar>
    	</target>
    	
    </project>
    Open [install-dir]/conf/Server.xml in a text editor and add the server listener to the <ServerListener> section:
    <ServerListeners>
    	<ServerListener>
    		<BaseClass>com.wowza.wms.plugin.test.ws.ServerListenerWowzaServerWS</BaseClass>
    	</ServerListener>
    </ServerListeners>
    Start the Wowza media server. You should be able to get the web service wsdl by entering the following URL in a browser:
    http://localhost:9091/wowzaserverws?wsdl
    To consume from .NET, first install the .NET 3.5 SDK. Then navigate to the VC command prompt shortcut and open. Mine was at:

    C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\Visual Studio 2008 Command Prompt
    Create a C# application file that looks like this:

    WinApp.cs
    using System;
    using System.IO;
    
    namespace SvcConsumer
    {
    	class Consumer
    	{
    		public static void Main(String[] args)
    		{
    			WowzaServerWebService WowzaWS = new WowzaServerWebService();
    
    			string serverVersion = WowzaWS.getServerVersion();
    			Console.WriteLine("getServerVersion: "+serverVersion);
    			
    			Console.ReadLine();
    		}
    	}
    }
    Generate a web service consumer class from the WSDL, compile it, and then compile and link WinApp.cs into an executable with these commands run from the VC command prompt (assume WinApp.cs is in the current directory):
    wsdl http://localhost:9091/wowzaprows?wsdl
    csc /t:library WowzaServerWebService.cs
    csc /r:WowzaServerWebService.dll WinApp.cs
    References:

    .NET Web Services Tutorial
    Simple Web Service with JAX-WS
    Developing Web Services Using JAX-WS

    Notes:
    • Must use Java 6 JDK Update 4 or greater (I used Java 6 JDK Update 18).

    • Assume you have Ant 1.6.x or greater installed and configured properly.

    Originally Published: 10-03-2010.

    If you're having problems or want to discuss this article, post in our forum.