Analytics


Google

Friday, October 31, 2008

Consuming Webservice using MSSoap

Even though majority of the programmers have started using vb.net, there may be cases where you have a legacy system that still needs to consume webservice. This is how to do it with MSSoap.

First thing to be aware of is you may encounter issue if the webservice returns XML, so have it return a string instead. This is easily done by using a wrapper function. For example, if you have a webmethod say getLotData, just create a getLotDataStr as follows:

<WebMethod()> _
Public Function getLotData(ByVal pLotID As String) As XmlDocument
....
End Function

...

<WebMethod()>
Public Function getLotDataStr(ByVal pLotID As String) As String
Dim tmpStr As String = ""
Dim xDoc As XmlDocument

xDoc = getLotData(pLotID)
tmpStr = xDoc.OuterXml

Return tmpStr
End Function


To consume the webservice, in vbscript or VB, you then use the MSSoap client as follows:

Dim wsClient As New MSSOAPLib30.SoapClient30
Dim urlStr as String = "http://www.blogger.com/wservice.asmx?WSDL"
Dim sReply, lotID As String
Dim xDoc As DOMDocument30

lotID = ...
wsClient.MSSoapInit urlStr
sReply = wsClient.getLotDataStr(lotID)

xDoc.loadXML sReply

...


Once the information is loaded to the XmlDocument, you can then access the information by using the getElementsByTagName. You can also access the inner text by access the Text Property.

E.g.

Dim lotNode As IXMLDOMNode
Dim processStep As String

Set lotNode = xDoc.getElementByTagName("processID")
ProcessStep = lotNode.Text


'If it is an attribute then access it by the Attributes as in
ProcessStep = lotNode.Attributes.getNameItem("Name").Text


You can also use the DomDocument30 data type to create the parameters if the Webservice requires a XML as a parameter.

Wednesday, October 29, 2008

Creating properly aligned content in Blogger

The easiest way to create a properly aligned information in Blogger is:
  1. Open excel and place the data in table as shown below.
  2. Copy and then paste into the compose screen (this only works if you are using FireFox) and there you have it, your data is aligned correct (as shown below).

This is how the excel looks like:


Using Firefox:

Date Mileage time
1-Jan-08 10 1 hr
2-Jan-08 5 0.5 hr

Saturday, October 25, 2008

Dynamically loading UserControl in ASP.Net

I gathered information from the following sources to come up with the following:

4 Guys from Rolla
ASP.Net
CodeProject

First the UserControl:

This is how it looks like in VS Designer:


The code is as follows:

<%@ Control Language="vb" AutoEventWireup="false" Codebehind="ucAckFrm.ascx.vb" Inherits="testWeb.ucAckFrm" TargetSchema="http://schemas.microsoft.com/intellisense/ie5" %>
<asp:panel id="PaneCtrl" runat="server">
<asp:Label id="lblCtrlName" runat="server"></asp:Label>
<BR>
<asp:Panel id="paneDisp" runat="server">
<asp:Label id="lblMsg" runat="server"></asp:Label><BR><BR>
<asp:Button id="btnAck" runat="server" Text="Acknowledge"></asp:Button>
<asp:Button id="btnReject" runat="server" Text="Reject"></asp:Button>
<asp:TextBox id="txtReason" runat="server"></asp:TextBox><BR>
<asp:Label id="lblErrMsg" runat="server" ForeColor="Red"></asp:Label>
<HR>
</asp:Panel>
</asp:panel>


The code behind is as follows:

Public Class ucAckFrm
Inherits System.Web.UI.UserControl

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
Private Sub InitializeComponent()

End Sub
Protected WithEvents lblMsg As System.Web.UI.WebControls.Label
Protected WithEvents btnAck As System.Web.UI.WebControls.Button
Protected WithEvents btnReject As System.Web.UI.WebControls.Button
Protected WithEvents txtReason As System.Web.UI.WebControls.TextBox
Protected WithEvents lblCtrlName As System.Web.UI.WebControls.Label
Protected WithEvents lblErrMsg As System.Web.UI.WebControls.Label
Protected WithEvents PaneCtrl As System.Web.UI.WebControls.Panel
Protected WithEvents paneDisp As System.Web.UI.WebControls.Panel

'NOTE: The following placeholder declaration is required by the Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Public Event AckClick As EventHandler
Public Event RjctClick As EventHandler

Public Property RjctReason() As String
Get
Return txtReason.Text
End Get
Set(ByVal Value As String)
txtReason.Text = Value
End Set
End Property

Public Sub setMainPane(ByVal pVisible As Boolean)
PaneCtrl.Visible = pVisible
End Sub

Public Sub setDispPane(ByVal pVisible As Boolean)
paneDisp.Visible = pVisible
End Sub

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblCtrlName.Text = Me.ID
End Sub

Private Sub btnAck_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAck.Click
RaiseEvent AckClick(Me, e)
End Sub


Private Sub btnReject_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnReject.Click
Dim tmpStr As String

tmpStr = Trim(txtReason.Text)

If tmpStr.Length > 0 Then
RaiseEvent RjctClick(Me, e)
Else
lblErrMsg.Text = "Reject Reason cannot be blank"
End If
End Sub
End Class


The main aspx page:


The code:

<%@ Register TagPrefix="uc1" TagName="ucAckFrm" Src="ucAckFrm.ascx" %>
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="TestPage.aspx.vb" Inherits="testWeb.WebForm1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<title>WebForm1</title>
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
<meta content="Visual Basic .NET 7.1" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
</HEAD>
<body>
<form id="Form1" method="post" runat="server">
<asp:label id="lblMsg" runat="server"></asp:label><br>
<asp:textbox id="txtMsg" runat="server"></asp:textbox><br>
<br>
<asp:button id="btnSubmit" runat="server" Text="Submit"></asp:button><br>
<asp:Label id="lblErrMsg" runat="server" ForeColor="Red"></asp:Label><br>
<hr>
<br>
<uc1:ucAckFrm id="DefAck" runat="server"></uc1:ucAckFrm><br>
<asp:PlaceHolder id="pHolder" runat="server"></asp:PlaceHolder></form>
</body>
</HTML>


The code behind:

Public Class WebForm1
Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

'This call is required by the Web Form Designer.
Private Sub InitializeComponent()

End Sub
Protected WithEvents lblMsg As System.Web.UI.WebControls.Label
Protected WithEvents txtMsg As System.Web.UI.WebControls.TextBox
Protected WithEvents btnSubmit As System.Web.UI.WebControls.Button
Protected WithEvents defAck As ucAckFrm
Protected WithEvents pHolder As System.Web.UI.WebControls.PlaceHolder
Protected WithEvents lblErrMsg As System.Web.UI.WebControls.Label

'NOTE: The following placeholder declaration is required by the Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object

Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub

#End Region

Dim vStr As String
Dim ackArray As New ArrayList

Private Sub PageInit2(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
Dim ctrlCnt, tmpStr As String
Dim loopCnt, ackCnt As Integer
Dim vAckCtrl As ucAckFrm
Dim ctrl As Control

ctrlCnt = Request.Item("opt")
vStr = ctrlCnt

If IsNumeric(vStr) Then
ackCnt = CInt(vStr)
If ackCnt > 0 Then
For loopCnt = 0 To (ackCnt - 1)
ctrl = LoadControl("ucAckFrm.ascx")
tmpStr = "Ack_" & loopCnt
ctrl.ID = tmpStr
vAckCtrl = CType(ctrl, ucAckFrm)
AddHandler vAckCtrl.AckClick, AddressOf AckHandlerAck
AddHandler vAckCtrl.RjctClick, AddressOf AckHandlerRjct

ackArray.Add(vAckCtrl)
pHolder.Controls.Add(ctrl)
Next
End If
End If

AddHandler defAck.AckClick, AddressOf AckHandlerAck
AddHandler defAck.RjctClick, AddressOf AckHandlerRjct

End Sub


Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If IsPostBack = False Then
Try
lblMsg.Text += "ctrlCnt value is " & vStr
Catch ex As Exception
lblErrMsg.Text += "<br>" & ex.Message
End Try

End If

End Sub


Private Sub AckHandlerAck(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim idName As String

idName = UCase(CType(sender, Control).ID)

lblMsg.Text += "<br>Acknowledge by " & idName
End Sub

Private Sub AckHandlerRjct(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim idName, reason As String
Dim handledCtrl As ucAckFrm

idName = UCase(CType(sender, Control).ID)
handledCtrl = CType(sender, ucAckFrm)
reason = handledCtrl.RjctReason

lblMsg.Text += "<br>Rejected by " & idName & " due to " & reason
End Sub
End Class


In this example, to simplify testing, I use the url parameter opt to determine how many times I want to load the usercontrol. In the following example, I loaded it twice - i.e. ?opt=2


Key points I learn from the articles are:
  • Init will be called each time the page is refreshed.
  • View State is loaded after the init phase before the page load phase.
  • To load the control, we actually use the .ascx file using Page.LoadControl
  • After loading the control, we need to use CType to change back to the class defined in the codebehind for the usercontrol so we can access the properties, events etc for the user control.
Other Notes on this example:
  • In the example above, I assigned the ID for each of the controls that are dynamically loaded, this is actually for a project I am working on where the requestor will specify how many persons will be informed of a request made. Each person receiving the request will then have an option to either acknowledge the request or reject it. In that situation, I will then name each of the controls with the role for each receipient.
  • I added the mainPane and dispPane to provide an option if to either hide the whole control or to display on the header (but not used in the example above).
  • I use a try catch and throw to practice Error handling I wrote in my previous article.

Wednesday, October 22, 2008

Consuming WebService in Lotus NOTES

I found it difficult to find reference on how to consume webservice in Lotus NOTES. That is why I have this as a bookmark to help me get back to those locations:

Consuming webservice in LN 6


Another good one that shows a simple client side method is found here (snippet as follows):
Dim Client As Variant
Set Client = CreateObject("MSSOAP.SoapClient")
'Initialize connection to the Web Service
Call Client.mssoapinit
("http://localhost/testWS.nsf/Simple?wsdl")
'Call our simple GetEmailAddress
function provided by Web service
Dim result As String
result = Client.getJoke()
'output result to message box
Messagebox result, 48, "Get Joke"


There is also an open source project which produces a java stub to consume the webservice called stubby, however, still not sure whether is meets my counterparts requirements.

In LN 8, it is much simpler to consume the webservice, just have to create a new script - either JavaScript, LotusScript or Java Library and there is a button at the bottom labeled WSDL, just click it and import WSDL to create the required reference to consume the webservice.

There is also another reference on how to write do some of the coding in java - found here. Another reference talking about webservice in LN 8.5 is found here.

Monday, October 20, 2008

Lotus NOTES programming

If you are curious about programming in Lotus NOTES, IBM provides an excellent resource here. The item I found most useful is the reference entitle Lotus Script Language Guide. Unfortunately, there is only one version of the reference book available (i.e. version 7.x).

When I first started on Lotus NOTES (4.x), they only provided formula for programming. Since version 5.x, the introduced JavaScript and LotusScript. If you are from MS environment, you will probably be more comfortable with LotusScript, since the syntax is identical to VBScript used for macros of all the MSOffice products.

If you prefer, you can either program in Java or JavaScript which is also available within Lotus NOTES. So just as you can program in Oracle using PL/SQL or using Java. The preference is yours.

Wednesday, October 15, 2008

Oracle 10G migration Issues - not group by

When we migrated from Oracle 9i to 10G, we encountered a few issues. One of the strangest one is as follows.

The following query works fine in 9i but when we execute in 10G, we encounter the following error:

ORA-00979: not a GROUP BY expression

The SQL statement (changes have been made on the column names and table names to protect the innocent code) is as follows:

SELECT TO_CHAR(Time_Date, 'yyyymmdd') Time_Date ,
Def_Code ,
StepName ,
ScrapReason ,
StartQty ,
ScrapQty ,
BonusQty ,
ROUND(DECODE(StartQty,0,0,(ScrapQty-BonusQty)/StartQty*100), 2) DefectPercentage,
0 Normalised
FROM
(SELECT Time_Date,
Def_Code ,
StepName ,
ScrapReason ,
ScrapQty ,
BonusQty ,
(SELECT SUM(YLDPACKAGE.GET_OPSTEPSTARTQTY(StepName,StartQty,ScrapQty,BonusQty))
FROM yld_summary
WHERE Time_Date = d.Time_Date
AND RType = 'ASSEMBLY'
AND (Owner LIKE 'SPECIALBUILD%'
AND (Category = 'PRODUCTION'
OR Category = 'BETA' ) )
AND (PRODUCTNAME(WafID,Owner) = 'VISTA')
AND YLDPACKAGE.GET_STEPGRP(StepName) = d.StepName
) StartQty
FROM
(SELECT Time_Date ,
Def_Code ,
YLDPACKAGE.GET_STEPGRP(StepName) StepName ,
REPLACE(ScrapReason, '_RI','') ScrapReason,
SUM(ScrapQty) ScrapQty ,
SUM(BonusQty) BonusQty
FROM yld_dtl
WHERE Time_Date BETWEEN to_date('20081007', 'yyyymmdd') AND to_date('20081014', 'yyyymmdd')
AND RType = 'ASSEMBLY'
AND (Owner LIKE 'SPECIALBUILD%'
AND (Category = 'PRODUCTION'
OR Category = 'BETA' ) )
AND (PRODUCTNAME(WafID,Owner) = 'VISTA')
AND YLDPACKAGE.GET_STEPGRP(StepName) = 'LAPPING'
AND ScrapReason = 'Scratches'
GROUP BY Time_Date ,
Def_Code ,
YLDPACKAGE.GET_STEPGRP(StepName),
REPLACE(ScrapReason, '_RI','')
) d
) order by time_date


The work around is to just add another column in the group by (highlighted below in red):

SELECT TO_CHAR(Time_Date, 'yyyymmdd') Time_Date ,
Def_Code ,
StepName ,
ScrapReason ,
StartQty ,
ScrapQty ,
BonusQty ,
ROUND(DECODE(StartQty,0,0,(ScrapQty-BonusQty)/StartQty*100), 2) DefectPercentage,
0 Normalised
FROM
(SELECT Time_Date,
Def_Code ,
StepName ,
ScrapReason ,
ScrapQty ,
BonusQty ,
(SELECT SUM(YLDPACKAGE.GET_OPSTEPSTARTQTY(StepName,StartQty,ScrapQty,BonusQty))
FROM yld_summary
WHERE Time_Date = d.Time_Date
AND RType = 'ASSEMBLY'
AND (Owner LIKE 'SPECIALBUILD%'
AND (Category = 'PRODUCTION'
OR Category = 'BETA' ) )
AND (PRODUCTNAME(WafID,Owner) = 'VISTA')
AND YLDPACKAGE.GET_STEPGRP(StepName) = d.StepName
) StartQty
FROM
(SELECT Time_Date ,
Def_Code ,
YLDPACKAGE.GET_STEPGRP(StepName) StepName ,
REPLACE(ScrapReason, '_RI','') ScrapReason,
SUM(ScrapQty) ScrapQty ,
SUM(BonusQty) BonusQty
FROM yld_dtl
WHERE Time_Date BETWEEN to_date('20081007', 'yyyymmdd') AND to_date('20081014', 'yyyymmdd')
AND RType = 'ASSEMBLY'
AND (Owner LIKE 'SPECIALBUILD%'
AND (Category = 'PRODUCTION'
OR Category = 'BETA' ) )
AND (PRODUCTNAME(WafID,Owner) = 'VISTA')
AND YLDPACKAGE.GET_STEPGRP(StepName) = 'LAPPING'
AND ScrapReason = 'Scratches'
GROUP BY Time_Date ,
Def_Code ,
YLDPACKAGE.GET_STEPGRP(StepName),
StepName ,
REPLACE(ScrapReason, '_RI','')
) d
) order by time_date



Nov 23, 2008

Found the above code did not product correct output, had to rewrite it as follows:

 SELECT TO_CHAR(Time_Date, 'yyyymmdd') Time_Date                                   ,
Def_Code ,
StepName ,
ScrapReason ,
StartQty ,
ScrapQty ,
BonusQty ,
ROUND(DECODE(StartQty,0,0,(ScrapQty-BonusQty)/StartQty*100), 2) DefectPercentage,
0 Normalised
FROM
(SELECT Time_Date,
Def_Code ,
StepName ,
ScrapReason ,
ScrapQty ,
BonusQty ,
(SELECT SUM(YLDPACKAGE.GET_OPSTEPSTARTQTY(StepName,StartQty,ScrapQty,BonusQty)),
YLDPACKAGE.GET_STEPGRP(StepName) step
FROM yld_summary
WHERE Time_Date = d.Time_Date
AND RType = 'ASSEMBLY'
AND (Owner LIKE 'SPECIALBUILD%'
AND (Category = 'PRODUCTION'
OR Category = 'BETA' ) )
AND (PRODUCTNAME(WafID,Owner) = 'VISTA')
group by YLDPACKAGE.GET_STEPGRP(StepName)) l,
(SELECT Time_Date ,
Def_Code ,
YLDPACKAGE.GET_STEPGRP(StepName) StepName ,
REPLACE(ScrapReason, '_RI','') ScrapReason,
SUM(ScrapQty) ScrapQty ,
SUM(BonusQty) BonusQty
FROM yld_dtl
WHERE Time_Date BETWEEN to_date('20081007', 'yyyymmdd') AND to_date('20081014', 'yyyymmdd')
AND RType = 'ASSEMBLY'
AND (Owner LIKE 'SPECIALBUILD%'
AND (Category = 'PRODUCTION'
OR Category = 'BETA' ) )
AND (PRODUCTNAME(WafID,Owner) = 'VISTA')
AND YLDPACKAGE.GET_STEPGRP(StepName) = 'LAPPING'
AND ScrapReason = 'Scratches'
GROUP BY Time_Date ,
Def_Code ,
YLDPACKAGE.GET_STEPGRP(StepName),
StepName ,
REPLACE(ScrapReason, '_RI','')
) d where l.step = d.stepname
) order by time_date

Sunday, October 12, 2008

Installing Framework 1.1 in Vista (if error)

Found the article from here.
Install Microsoft .NET Framework 1.1 on Windows Vista - Fix RegSvcs.exe Fails Error

Windows Vista comes packaged with Microsoft .NET Framework 2.0 and 3.0, but not version 1.1, which may still required by some applications such as QuickBooks 7, GFI Report Packs, VS.NET 2003, InstallShield 11.5, and many other developed software. However, when trying to install Microsoft .NET Framework 1.1 (dotnetfx.exe) on Windows Vista, one or more error messages similar to one of the following text will appear, and stop or prevent setup installation of .NET Framework 1.1 from continuing successfully.

RegSvcs.exe - Common Language Runtime Debugging Services

Application has generated an exception that could not be handled.
Process id=0xe50 (3664), Thread id=0xd44 (3396).

Click OK to terminate the application.
Click CANCEL to debug the application.

In Event Viewer of Vista, the following log or similar can be seen:

Source: MsiInstaller
Event ID: 1030
Description:
Product: Microsoft .NET Framework 1.1. The application tried to install a more recent version of the protected Windows file C:\Windows\Microsoft.NET\Framework\sbs_wminet_utils.dll. You may need to update your operating system for this application to work correctly. (Package Version: 1.0.0.0, Operating System Protected Version: 1.0.0.0).

Source: MsiInstaller
Event ID: 1030
Description:
Product: Microsoft .NET Framework 1.1. The application tried to install a more recent version of the protected Windows file C:\Windows\Microsoft.NET\Framework\sbs_system.enterpriseservices.dll. You may need to update your operating system for this application to work correctly. (Package Version: 1.0.0.0, Operating System Protected Version: 1.0.0.0).

The error pops up in the end of .NET Framework 1.1 setup when it’s almost finished, and is registering “System.EnterpriseServices.dll” when the error occurs, time remaining for the installatin process shows 0 seconds.

Why exactly the error occurs when installing Microsoft .NET Framework 1.1 in Windows Vista is not known, as the issue happens randomly. It may affect both 32-bit and 64-bit Vista system, but not all system will have the issue. But one thing is for sure. Microsoft .NET Framework 1.1 SP1 (Service Pack 1) has resolved the issue. However, Microsoft does not provide download to standalone .NET Framework 1.1 installer that integrated with SP1.

Thus, the workaround to fix the Microsoft.NET Framework 1.1. installation error on Vista is to slipstream .NET Framework 1.1 SP1 into .NET Framework 1.1 installer, so that both the .NET Framework and the Service Pack can be installed at the same time.

To slipstream .NET 1.1 SP1 into .NET Framework setup package to have a integrated .NET Framework 1.1 SP1 installer, follow steps in this trick:


1. Create a new folder named DotNet in C:\ drive (C:\DotNet is used in this guide, you can change to any folder you prefer, but ensure that you use correct path in the following steps).
2. Download Microsoft .NET Framework 1.1 Redistributable Package (dotnetfx.exe). Make sure the setup file is saved as dotnetfx.exe.
3. Download Microsoft .NET Framework 1.1 Service Pack 1 (NDP1.1sp1-KB867460-X86.exe). Make sure that the file is renamed and saved as dotnetfxsp1.exe, so that the rest of the steps can be followed easily.
4. Move both installation files into the same directory (i.e. C:\DotNet), if you’re not saving them together.
5. Open command prompt as Administrator.
6. Change to the directory where the two installation setup files for .NET 1.1 are saved (i.e. C:\DotNet).
7. Run the following commands one by one, press Enter after each one.
* dotnetfx.exe /c:"msiexec.exe /a netfx.msi TARGETDIR=C:\DotNet"

If you’re not using C:\DotNet directory, change the target to your path accordingly.

Install Microsoft .NET Framework 1.1 on Windows Vista
Then click on “Yes” when prompted to answer “would you like to install Microsoft .NET Framework 1.1. Package?”

Wait for the uncompression, extraction and setup to complete with the display of the following dialog which says installation complete.
Install Microsoft .NET Framework 1.1 on Windows Vista
* dotnetfxsp1.exe /Xp:C:\DotNet\netfxsp.msp

No status message for this step.
* msiexec.exe /a c:\DotNet\netfx.msi /p c:\DotNet\netfxsp.msp

Install Microsoft .NET Framework 1.1 on Windows Vista
Wait for Windows Installer for Microsoft .NET Framework 1.1 to finish and disappear automatically.
8. Install Microsoft .Net Framework 1.1 with slipstreamed/integrated Service Pack 1 by running netfx.msi created in the working folder.

Wednesday, October 8, 2008

Microsoft is offering three VS 2008 PDF for free download but...

Just found the following in my email today from Microsoft - just click the following link:


After signing up, it allows you to download the three books (from Microsoft Press) in PDF format:

Programming Microsoft LINQ
Introducing Microsoft Silverlight 2
Programming ASP.NET 3.5

I was expecting the whole book but only selected chapters of each book is provided : (

However, Microsoft does provide some other pdf books for free such as:

Composite Application Guidance for WPF (but requires simple registration - just log into hotmail)

Tuesday, October 7, 2008

Decompiler

Recently one of my team member was in the midst of migrating to a new database and was performing some testing and encountered some problem. I told him to go back to the code and make the changes and testing. However, when he did that, he found that the person who previously wrote the code (and left the company) failed to checkin the source code into our SourceSafe repository.

As such, I went to search for decompilers. I came across many articles but the following are the more helpful ones:

Decompiling .Net Assemblies
Decompilers

For .Net, it appears that Reflector is the free solution recommended.

There were a couple of sharewares that did the samething - Spice, Dis# and Salamander.

For Java, you have Jode and Jad. Hmm, where do this people come up with these names :)

Wednesday, October 1, 2008

Connecting to RAC using SQLDeveloper

The following are two definition in tnsnames.ora pointing to the same RAC database. The first one uses name (racdb1), the second (racdb2) uses actual IP address:

racdb1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = db1.blogspot.COM)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = db2.blogspot.COM)(PORT = 1521))
(LOAD_BALANCE = yes)
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ORCL.BLOGSPOT.COM)
(FAILOVER_MODE =
(TYPE = SELECT)
(METHOD = BASIC)
(RETRIES = 180)
(DELAY = 5)
)
)
)


racdb2 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.155.1.1)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.155.1.2)(PORT = 1521))
(LOAD_BALANCE = yes)
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ORCL.BLOGSPOT.COM)
(FAILOVER_MODE =
(TYPE = SELECT)
(METHOD = BASIC)
(RETRIES = 180)
(DELAY = 5)
)
)
)

If you use SQL Developer to connect to racdb1 using the TNS, you will encounter the following error:

Status: Failure - Test failed: (null).

It works fine if you connect to racdb2. Apparently, it is not able to perform a nslookup to obtain the IP address when using TNS. It works fine if you use advance and use thin client to connect as in:

Strangely, if you use Advanced and put the following string, it works:

jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS = (PROTOCOL = TCP)(HOST = db1.blogspot.COM)(PORT = 1521))(ADDRESS = (PROTOCOL = TCP)(HOST = db2.blogspot.COM)(PORT = 1521))(LOAD_BALANCE = yes))(CONNECT_DATA=(SERVER = DEDICATED)(SERVICE_NAME = ORCL.BLOGSPOT.COM)(FAILOVER_MODE=(TYPE = SELECT)(METHOD = BASIC)(RETRIES = 180)(DELAY = 5))))