This year I embarked on a journey to migrate a group of
ASP.NET web applications developed to integrate with WebLogic Portal 9.2 via
the
AquaLogic® Interaction .NET Application Accelerator 1.0 to instead use the Oracle WebCenter
WSRP Producer for .NET and integrated with WebLogic Portal 10.3.4. It has
been a very winding path and this blog entry is intended to share both the
lessons learned and relevant approaches that led to those learnings. Like most journeys of discovery, it was not a
direct path, and there are notes to let you know when it is practical to skip a
section if you are in a hurry to get from here to there.
For the Curious
From the perspective of necessity, this section would be
better at the end. If it were there, though, it would probably be read by far
fewer people, including those that are actually interested in these types of
sections. Those in a hurry may skip past and be none the worst for it in
dealing with the hands-on bits of performing a migration from .NET Accelerator
to WSRP Producer. For others who want to talk about why they did what they did
after they did it, or just want to know for themselves, enjoy.
A Brief (and edited) History of the WSRP for
.NET Technologies (as Relevant to the this
Post)
Note: This section is
for those who are curious about why the migration path is not as simple as many
other Oracle technologies. You can skip this section in its entirety and still
be just as competent in performing a migration as if you had read it.
The currently deployed architecture that was to be migrated
and upgraded achieved initial integration between .NET and J2EE over the WSRP
protocol through the use of The
AquaLogic Interaction .NET Application Accelerator. The .NET Accelerator
allowed the applications that were written in ASP.NET and deployed on a
Microsoft Internet Information Server (IIS) to interact with a WebLogic Portal
application deployed on a WebLogic (J2EE application) Server (both version 9.2,
the state of the art at the time of its creation). At the time this
architectural decision for the application was made, both the AquaLogic and
WebLogic brands were owned by BEA Systems. The AquaLogic brand included
products acquired by BEA through the acquisition of Plumtree, whose flagship
product was a portal platform available in both J2EE and .NET versions. As part
of this dual technology support an adaptor was created to facilitate the use of
WSRP as a communication protocol where customers wished to integrate components
from both versions of the Plumtree portal. The adapter evolved over several
product generations to include a broad array of both standard and proprietary
WSRP integration capabilities.
Later, BEA Systems was acquired by Oracle. Over the course
of several years Oracle has acquired a large number of portal applications and
has taken the strategic direction to migrate users of these myriad (and
formerly competitive) products to the Oracle WebCenter technology stack. As
part of Oracle’s strategic technology roadmap, older portal products are being
schedule for end of life, including the portal products that were part of the
BEA acquisition.
The .NET Accelerator has been modified over a very long
period of time with features driven by users of that product and developed
under three different vendors (each a direct competitor in the same solution
space prior to merger).
The Oracle
WebCenter WSRP Producer for .NET was
introduced much more recently with the key objective to specifically address
the needs of the WebCenter customers developing solutions accessible through
both J2EE and .NET platforms utilizing the WSRP
specifications.
The Oracle Product Development Team also provides these
insights on the drivers for developing the WSRP Producer:
*****************************************
Support for ASP.NET AJAX. Controls using the ASP.NET AJAX script
manager do not function properly in the Application Accelerator for .NET.
Support 2 way SSL in WLP. This was not possible with the
proxy/bridge set up in the existing Application Accelerator for .NET.
Allow developers to code
portlets (Web Parts) using the .NET
framework rather than a proprietary framework. Developers had to use the Application
Accelerator for .NET plug-ins to Visual Studio to manage preferences and
profile data. This is now replaced
with the .NET Framework Personalization (for preferences) and Profile
providers.
The WSRP Producer for .NET was created as a new way of
developing .NET portlets. It was never
designed to be an upgrade path for the Application Accelerator for .NET. .NET developers would create new .NET portlets
with the WSRP Producer for .NET and leave any existing .NET portlets running in
the Application Accelerator for .NET.
*****************************************
The advantage to creating a new solution for WSRP is a
product that is far easier for Oracle to maintain and support which in turn improves
quality, reliability and maintainability for their customers. No changes to
J2EE applications consuming the WSRP portlets previously rendered by the.NET
Accelerator is required to migrate from the Aqualogic WSRP solution. For some
customers using the .NET Accelerator the challenge is adapting their current
.NET applications to work with the WSRP Producer (or any other WSRP adapter as
they are proprietary by nature). Part of this adaptation is the need to deploy
the .NET applications as a child to the WSRP producer web application as root.
Differences between .NET Accelerator and WSRP
Producer
Note: This section is
for those who are curious about why the migration is not as pluggable as
something such as changing security providers in WebLogic Server. You can skip
this section in its entirety and still be just as competent in performing a
migration as if you had read it.
The basic terminology used to describe the participating
applications in a WSRP environment are the same when applied to either the .NET
Accelerator or the WSRP Producer: Producer and Consumer. In both cases the .NET application serves as what
is referred to as a WSRP environment as the Producer.
The difference lies in how the two adapters create the WSRP
translation of the .NET application. The .NET Accelerator, as the name implies,
is meant to serve as a quick way of adding WSRP capability to a .NET
application. As such, at a high level, the .NET Accelerator behaves as a proxy
for requests between the .NET application and the WSRP Consumer. A WSRP request
is sent from the consumer to the .NET Accelerator, the.NET Accelerator
transforms this request into an ASP.NET request, receives the response, then
transforms the response into a WSRP response. The .NET Accelerator is deployed
as a stand-alone application on IIS.
The WSRP Producer is deployed as a parent application on IIS
and all ASP.NET modules that will be made available over WSRP are deployed as
children of the WSRP Producer application. In this manner, the WSRP Producer
acts more as a Request Filter than a proxy in the WSRP transactions between
Producer and Consumer.
Highly Recommended
Enabling Logging
Note: You can skip
this section now, but you will most likely want to come back to it later, so
why not just read it now?
Logging is very helpful in tracking down the causes of any
anomalies during testing of migrated portlets. To enable the WSRP Producer
logging, update the Application_Start method in the Global.asax.cs for your .NET application by adding
log4net.Config.XmlConfigurator.Configure();
IIS logs will usually (in a standard configuration) be in a
sub folder under C:\WINDOWS\system32\LogFiles\W3SVC.
WSRP Producer logs will be found at C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdefault\Logs\WSRPProducer.log
InputTrace.webinfo and OutputTrace.webinfo are located under
C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdefault and can be useful in
debugging issues related to markup transformations.
Things You Must Do
Merge Web.Config
Note: If you have been
skipping all the sections that you can, now is the time to stop and pay
attention J
Because the existing .NET application will become a
sub-application to the WSRP Producer, you will want to merge required settings
from the existing Web.Config to the one in the WSRP Producer.
Use the WSRP Producer Master Page
The Master Page installed for the WSRP Producer provides common,
hiddenform fields and JavaScripts to facilitate portlet instance management and
display configuration when the child page is being rendered over WSRP. You add the
Master Page by including it in the <@ Page declaration with MasterPageFile="~/portlets/Resources/MasterPages/WSRP.Master"
. You then replace:
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
With
<asp:Content
ID="ContentHead1" ContentPlaceHolderID="wsrphead"
Runat="Server">
And
</HEAD>
<body>
<form
id="theForm" method="post" runat="server">
With
</asp:Content>
<asp:Content ID="ContentBody1"
ContentPlaceHolderID="Main" Runat="Server">
And finally
</form>
</body>
</HTML>
With
</asp:Content>
In the event you already use Master Pages, adapt your
existing Master Pages to be sub masters. See Nested ASP.NET Master Pages for a
detailed reference of how to do this.
It Happened to Me, It Might Happen to You…Or Not
Watch for Use of Session or Request in OnInit
In the event the .NET application being modified has pages
developed to assume the user has been authenticated in an earlier page request
there may be direct or indirect references in the OnInit method to request or
session objects that may not have been created yet. This will vary from
application to application, so the recommended approach is to test first. If
there is an issue with a page running as a WSRP portlet then check for
potential references in the OnInit method (including references by methods
called within OnInit) to session or request objects. If there are, the simplest
solution is to create a new method and then call that method once the necessary
object(s) is fully available. I find doing this at the start of the Page_Load
method to be the simplest solution.
Case Sensitivity
.NET languages are not case sensitive, but Java is. This
means it is possible to have many variations of SRC= and src= or .JPG and .jpg.
The preferred solution is to make these mark up instances all lower case in
your .NET application. This will allow the default Rewriter rules in
wsrp-producer.xml to work as is. If this is not practical, then make duplicates
of any rules where an issue is occurring due to upper or mixed case usage in
the .NET application markup and match the case in use with the duplicate rule.
For example:
<RewriterRule>
<LookFor>(href=\"([^\"]+)</LookFor>
<ChangeToAbsolute>true</ChangeToAbsolute>
<ApplyTo>.axd,.css</ApplyTo>
<MakeResource>true</MakeResource>
</RewriterRule>
May need to be duplicated as:
<RewriterRule>
<LookFor>(HREF=\"([^\"]+)</LookFor>
<ChangeToAbsolute>true</ChangeToAbsolute>
<ApplyTo>.axd,.css</ApplyTo>
<MakeResource>true</MakeResource>
</RewriterRule>
While it is possible to write
a regular expression that will handle mixed case usage, it would be long and
strenous to test and maintain, so the recommendation is to use duplicate rules.
Is it Still Relative?
Some .NET applications base relative paths with a fixed root
location. With the introduction of the WSRP Producer, the root has moved up one level. References
to ~/ will need to be updated to ~/portlets and many ../ paths will need
another ../ in front.
I Can See You But I Can’t Find You
This issue was first discovered while debugging modules with
code that referenced the form on a page from the code-behind by name and/or id.
The initial error presented itself as run-time error that was difficult to
interpret over WSRP but seemed clear when run as straight ASP.NET as it
indicated that the object with the form name did not exist.
Since the form name was no longer valid after implementing
the WSRP Master Page, the likely fix seemed to simply update the references in
the code. However, as the WSRP Master Page is external to the code, a compile
time error resulted:
Error
155 The name 'form1' does not
exist in the current
context
C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdefault\portlets\legacywebsite\module\Screens
\Reporting.aspx.cs
51
52 legacywebsite.module
Much hair-pulling research later it was discovered that it
was the use of the FindControl method causing the issue. FindControl doesn’t
work quite as expected once a Master Page has been introduced as the controls
become embedded in controls, require a recursion to find them that is not part
of the FindControl method.
In code where the page form is referenced by name, there are
two steps to the solution. First, the form needs to be referenced in code
generically with Page.Form. For example,
this:
ToggleControl ctrl = new ToggleControl(frmManualEntry, FunctionLibrary.ParseArrayLst(userObj.Roles));
Becomes this:
ToggleControl ctrl = new ToggleControl(Page.Form, FunctionLibrary.ParseArrayLst(userObj.Roles));
Generally the form id is referenced in most ASP.NET
applications as a path to a control on the form. To reach the control once a
MasterPage has been added requires an additional method to recurse through the
controls collections within the form and find the control ID. The following
method (found at Rick
Strahl's Web Log) corrects this very nicely:
public static Control FindControlRecursive(Control Root, string
Id)
{
if
(Root.ID == Id)
return
Root;
foreach
(Control Ctl in
Root.Controls)
{
Control
FoundCtl = FindControlRecursive(Ctl, Id);
if
(FoundCtl != null)
return
FoundCtl;
}
return null;
}
Where the form name is not referenced, simply using the
FindControlRecursive method in place of FindControl will be all that is
necessary. Following the second part of the example referenced earlier, the
method called with Page.Form changes its value extraction code block from this:
Label lblErrMsg =
(Label)frmRef.FindControl("lblBRMsg"
To this:
Label lblErrMsg = (Label) FunctionLibrary.FindControlRecursive(frmRef,
"lblBRMsg"
The Master That Won’t Step Aside
In most migrations it is preferable to make as few changes
as possible. In one case I ran across an existing Master Page that would not
function as a sub-Master Page. While it
would probably have been educational to trace down why, the expedient process
of updating it to take the place of the WSRP Master Page is the route I took.
The changes are highlighted below:
…
<asp:ContentPlaceHolder ID="wsrphead"
runat="server"></asp:ContentPlaceHolder>
</head>
<body leftMargin="0" topMargin="0">
<form
id="TheForm" runat="server">
<input type="hidden" name="key"
id="key" value="" />
<input type="hidden"
name="formactionurl" id="formactionurl" value=""
/>
<input type="hidden" name="handle"
id="handle" value="" />
<asp:ScriptManager
ID="ScriptManager1" runat="server"
EnablePartialRendering="true" >
</asp:ScriptManager>
This approach did not work for all existing Master Pages,
but fortunately all of the other existing Master Pages I have run across worked
fine as a sub-Master to the WSRP Master Page.
Moving On
In Enterprise Portals, even after you get everything
working, the work is not finished. Next you need to get it where everyone will
work with it.
Migration Planning
Providing that the server where IIS is running is adequately
sized, it is possible to run both the .NET Accelerator and the WSRP Producer on
the same server during the upgrade process. The upgrade can be performed
incrementally, i.e., one portlet at a time, if server administration processes
support it. Those processes would include the ability to manage a second
producer in the consuming portal and to change over individual portlet
instances from one provider to the other. If processes or requirements demand
that all portlets be cut over at the same time, it needs to be determined if
this cut over should include a new producer, updating all of the portlets in
the consumer, or if the WSRP Producer portlet configuration must maintain the
naming conventions used by the .NET Accelerator and simply change the WSRP end
point configured in the consumer.
In some enterprises
it may even be necessary to maintain the same WSDL end point, at which point
the IIS configuration will be where the updates occur. The downside to such a requirement is that it
makes rolling back very difficult, should the need arise.
Location, Location, Location
Not everyone wants the web application to have the
descriptively obvious wsrpdefault location, or needs to create a second WSRP
site on the same server. The instructions below are from the product team and,
while targeted towards making a second site, will work for creating a site with
a different name and then remove the old site. You can also change just the
name in IIS.
Manually Creating a WSRP Producer Site
Instructions (NOTE: all executables used are the same ones
used by the installer and “wsrpdev” will be the name of the new instance):
1. Copy
C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdefault to C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdev.
2. Bring up a command window as an administrator
3. Run
C:\Oracle\Middleware\WSRPProducerForDotNet\uninstall_resources\IISAppAccelSiteCreator.exe
install WSRPProducers wsrpdev "C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdev"
8678 2.0.50727
4. Run
C:\Oracle\Middleware\WSRPProducerForDotNet\uninstall_resources\PermManage.exe
add FileSystem C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdev "NETWORK
SERVICE" 3 1
5. Run
C:\Oracle\Middleware\WSRPProducerForDotNet\uninstall_resources\PermManage.exe
add FileSystem C:\Oracle\Middleware\WSRPProducerForDotNet\wsrpdev EVERYONE 1 1
6. Open up
C:\Oracle\Middleware\WSRPProducerForDotNet\wsdl\1.0\WSRPService.wsdl and
replace wsrpdefault with wsrpdev
7. Open up C:\Oracle\Middleware\WSRPProducerForDotNet\wsdl\2.0\WSRPService.wsdl
and replace wsrpdefault with wsrpdev
Tests:
1. Bring up a browser on the host itself and go to
http://localhost:8678/wsrpdev/wsdl/1.0/WSRPService.wsdl and make sure that the
URLs in the XML returned include the wsrpdev changes you made in step 6.
2. Bring up a browser on the host itself and see if the
default sample comes up:
http://localhost:8678/wsrpdev/portlets/ASPNET_AJAX_sample/default.aspx
3. Register the producer in WLP and test the portlet.
Changing the Port used by WSRP Producer
The pre-configured port for the WSRP Producer is 8678. You
can change this port by updating both the IIS configuration and C:\Oracle\Middleware\WSRPProducerForDotNet\[WSRP_APP_NAME]\wsdl\1.0\WSRPService.wsdl.
Do You Need to Migrate?
Oracle Premier Support ended in November of 2010 for AquaLogic
Interaction .NET Application Accelerator 1.x and Extended Support ends in
November 2012 (see http://www.oracle.com/us/support/lifetime-support/lifetime-support-software-342730.html
for other related dates). This means
that integration with products released after November of 2010 is not
supported. If having such support is the policy within your enterprise, you do
indeed need to migrate. If changes in your enterprise cause your current
solution with the .NET Accelerator to no longer function properly, you may need
to migrate. Migration is a choice, and if the goals of your enterprise are to
take full advantage of newer technologies then migration is certainly one
activity you should be planning for.