Tuesday, November 19, 2013

How to host a WCF in IIS and enable Windows Authentication

I came across a scenario where I wanted to deploy a web service in windows server. Since I am mainly familiar with Linux environment and Java technology it took a while for me to get it done. So here I am sharing the knowledge gathered by me for those who wants to achieve the same task with less time.

WCF is a runtime set of APIs in .NET framework to create Web services.
IIS is a Microsoft Web server.


Environment:

JDK 1.6
.NET 4.0
IIS 7.5
Windows 7 professional

When you type IIS on the search in Start menu and did not retrieve any related results you can follow below steps:

Go to Control Panel -> Programs -> Programs and Features and click on "Turn Windows Features on or off". Refer the attached diagram.



Make sure you have ticked what is shown in here to avoid getting exceptions when you deploy WCF in IIS and try to access it from the browser.


I mainly referred this link to create WCF application but did some slight changes on Web.config. (Important: Please create your application directory in C:\inetpub\wwwroot\ directory)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   <system.serviceModel>
      <bindings>
         <basicHttpBinding>
            <binding name="BasicHttpEndpointBinding">
               <security mode="TransportCredentialOnly">
                  <transport clientCredentialType="Windows" />
               </security>
            </binding>
         </basicHttpBinding>
      </bindings>
      <services>
         <service name="Microsoft.ServiceModel.Samples.CalculatorService">
            <endpoint address="" binding="basicHttpBinding" contract="Microsoft.ServiceModel.Samples.ICalculator" />
            <endpoint address="mex" binding="basicHttpBinding" contract="IMetadataExchange" />
         </service>
      </services>
      <behaviors>
         <serviceBehaviors>
            <behavior>
               <serviceMetadata httpGetEnabled="true" />
            </behavior>
         </serviceBehaviors>
      </behaviors>
   </system.serviceModel>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true" >
        <listeners>
             <add name="xml"/>
        </listeners>
      </source>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
            <add name="xml"/>
        </listeners>
      </source>
      <source name="myUserTraceSource"
              switchValue="Information, ActivityTracing">
        <listeners>
            <add name="xml"/>
        </listeners>
      </source>
    </sources>
    <sharedListeners>
        <add name="xml"
             type="System.Diagnostics.XmlWriterTraceListener"
             initializeData="Error.svclog" />
    </sharedListeners>
  </system.diagnostics>
</configuration>

In order to create the application you need to first go to "IIS Manager" and expand the node and go to "Default Web Site" and right click on it as follows.


Now go to the application you have created and select it. In the feature view, under IIS click on "Authentication" and disable "Anonymous Authentication" and enable "Windows Authentication".

Now you need to add users in order to use windows authentication.
For that go to Computer Management -> Local Users and Groups -> Users and create new user. Uncheck "User must change password at next logon" and click "User cannot change password" and "Password never expires".

Then go to Computer Management -> Local Users and Groups ->Groups and select "IIS_IUSERS". Write click on it and click on All Tasks->Add to Group and add the user created in the previous step.

Now when you type the app url in browser you should be prompted to enter credentials.


Saturday, November 16, 2013

Access SOAP fault data in fault sequence when Store and Forward Messaging Patterns is used in WSO2 ESB with WSO2 MB or ActiveMQ

Use case 1: WSO2 ESB with ActiveMQ

Steps:

1. Follow this to configure ESB 4.7.0 with ActiveMQ. First start ActiveMQ
and then start ESB.
2. Sample synpase configuration is provided below. Copy it to Home/Manage/Service Bus/Source view and save it.

<definitions xmlns="http://ws.apache.org/ns/synapse">
   <registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
      <parameter name="cachableDuration">15000</parameter>
   </registry>
   <proxy name="JMSProxy" startonload="true" trace="disable" transports="https http">
      <description>
      <target>
         <insequence>
            <log level="full">
            <property name="target.endpoint" value="AxisEp">
            <property name="FORCE_ERROR_ON_SOAP_FAULT" value="true">
            <store messagestore="JMSMS">

         </store></property></property></log></insequence>
      </target>
   </description></proxy>
  <endpoint name="AxisEp">
      <address uri="http://localhost:9000/services/echo">
         <suspendonfailure>
            <errorcodes>-1</errorcodes>
            <progressionfactor>1.0</progressionfactor>
         </suspendonfailure>
      </address>
</endpoint>
   <sequence name="Axis_Ok"></sequence>
   <sequence name="Axis_Fault">
      <log category="ERROR" level="custom">
         <property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE" xmlns:ns="http://org.apache.synapse/xsd"></property>
         <property expression="get-property('ERROR_CODE')" name="ERROR_CODE" xmlns:ns="http://org.apache.synapse/xsd"></property>
         <property expression="get-property('ERROR_DETAIL')" name="ERROR_DETAIL" xmlns:ns="http://org.apache.synapse/xsd"></property>
      </log>

   </sequence>
   <sequence name="fault">
      <log level="full">
         <property name="MESSAGE" value="Executing default 'fault' sequence"></property>
         <property expression="get-property('ERROR_CODE')" name="ERROR_CODE"></property>
         <property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE"></property>
      </log>
      <drop>
   </drop></sequence>
   <sequence name="main">
      <in>
         <log level="full"></log>
         <filter regex="http://localhost:9000.*" source="get-property('To')">
            <send>
         </send></filter>
      </in>
      <out>
         <send>
      </send></out>
      <description>The main sequence for the message mediation</description>
   </sequence>
   <messagestore class="org.wso2.carbon.message.store.persistence.jms.JMSMessageStore" name="JMSMS">
      <parameter name="java.naming.factory.initial">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
      <parameter name="store.jms.cache.connection">false</parameter>
      <parameter name="java.naming.provider.url">tcp://localhost:61616</parameter>
      <parameter name="store.jms.JMSSpecVersion">1.1</parameter>
    <parameter name="store.jms.destination">JMSMS</parameter>
   </messagestore>
   <messageprocessor class="org.apache.synapse.message.processors.forward.ScheduledMessageForwardingProcessor" messagestore="JMSMS" name="SampleMessageForwardingProcessor">
      <parameter name="message.processor.reply.sequence">Axis_Ok</parameter>
      <parameter name="max.delivery.attempts">4</parameter>
      <parameter name="interval">1000</parameter>
  <parameter name="message.processor.fault.sequence">Axis_Fault</parameter>
   </messageprocessor>
</definitions>


 3. Download the Echo.aar and copy it to /samples/axis2Server/repository/services/ folder. The go to /samples/axis2Server location from terminal and run "sh axis2server.sh".
4. Now you can use soapUI to send the fault request. Create a new project with provided wsdl below:

http://localhost:8280/services/JMSProxy?wsdl

and open echoInt request and set a string as follows in order to get a soap fault from Echo service:

<soapenv:envelope xmlns:echo="http://echo.services.core.carbon.wso2.org" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:header>
   <soapenv:body>
      <echo:echoint>
         <!--Optional:-->
         <in>hi</in>
      </echo:echoint>
   </soapenv:body>
</soapenv:header></soapenv:envelope>

Use case 2: WSO2 ESB with WSO2 MB

1. Follow this to configure ESB 4.7.0 with WSO2 MB. First start MB
and then start ESB.
2. Sample synpase configuration is provided below. Copy it to Home/Manage/Service Bus/Source view and save it.

><definitions xmlns="http://ws.apache.org/ns/synapse">
   <registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
      <parameter name="cachableDuration">15000</parameter>
   </registry>
   <proxy name="JMSProxy" startonload="true" trace="disable" transports="https http">
      <description>
      <target>
         <insequence>
            <log level="full">
            <property name="target.endpoint" value="AxisEp">
            <property name="FORCE_ERROR_ON_SOAP_FAULT" value="true">
            <store messagestore="JMSMS">

         </store></property></property></log></insequence>
      </target>
   </description></proxy>
  <endpoint name="AxisEp">
      <address uri="http://localhost:9000/services/echo">
         <suspendonfailure>
            <errorcodes>-1</errorcodes>
            <progressionfactor>1.0</progressionfactor>
         </suspendonfailure>
      </address>
</endpoint>
   <sequence name="Axis_Ok"></sequence>
   <sequence name="Axis_Fault">
      <log category="ERROR" level="custom">
         <property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE" xmlns:ns="http://org.apache.synapse/xsd"></property>
         <property expression="get-property('ERROR_CODE')" name="ERROR_CODE" xmlns:ns="http://org.apache.synapse/xsd"></property>
         <property expression="get-property('ERROR_DETAIL')" name="ERROR_DETAIL" xmlns:ns="http://org.apache.synapse/xsd"></property>
      </log>

   </sequence>
   <sequence name="fault">
      <log level="full">
         <property name="MESSAGE" value="Executing default 'fault' sequence"></property>
         <property expression="get-property('ERROR_CODE')" name="ERROR_CODE"></property>
         <property expression="get-property('ERROR_MESSAGE')" name="ERROR_MESSAGE"></property>
      </log>
      <drop>
   </drop></sequence>
   <sequence name="main">
      <in>
         <log level="full"></log>
         <filter regex="http://localhost:9000.*" source="get-property('To')">
            <send>
         </send></filter>
      </in>
      <out>
         <send>
      </send></out>
      <description>The main sequence for the message mediation</description>
   </sequence>
      <messagestore class="org.wso2.carbon.message.store.persistence.jms.JMSMessageStore" name="JMSMS">
      <parameter name="java.naming.factory.initial">org.wso2.andes.jndi.PropertiesFileInitialContextFactory</parameter>
      <parameter name="store.jms.cache.connection">false</parameter>
      <parameter name="java.naming.provider.url">repository/conf/jndi.properties</parameter>
      <parameter name="store.jms.JMSSpecVersion">1.1</parameter>
      <parameter name="store.jms.destination">JMSMS</parameter>
   </messagestore>
   <messageprocessor class="org.apache.synapse.message.processors.forward.ScheduledMessageForwardingProcessor" messagestore="JMSMS" name="MyMsgProc">
      <parameter name="message.processor.reply.sequence">Axis_Ok</parameter>
      <parameter name="max.delivery.attempts">4</parameter>
      <parameter name="interval">5000</parameter>
      <parameter name="message.processor.fault.sequence">Axis_Fault</parameter>
   </messageprocessor>
</definitions>
3. Follow the 3rd and 4th steps in use case 1.

Note:

For both the cases you need to get a console output simillar to follows:
ERROR - ERROR_MESSAGE = Invalid value "hi" for element in, ERROR_CODE = Client, ERROR_DETAIL =
[2013-11-16 15:41:15,013] ERROR - LogMediator To: /services/FaultTestProxy.FaultTestProxyHttpsSoap11Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:268e04bb-9020-4640-b543-d8720e9b2142, Direction: request, Envelope: axis2ns2:ClientInvalid value "punnadi" for element in