Creating a Serviced Component


In short, a serviced component is a component that inherits the class System.EnterpriseServices.ServicedComponent . Could it be that simple? That's almost the case. Let's dive quickly into demonstration mode to see just how you create a serviced component.

The sample applications you will create for this purpose involve selecting the Class Library project template. As shown in Figure 19-7, you will name the first sample application MyFirstClassLibraryCobol. You will create a Visual Basic .NET (VB .NET) versioned sample application as well. After you code and build these applications, you will end up with your very own .dll files [5] (class libraries).

click to expand
Figure 19-7: The VS .NET New Project window with the Class Library project template selected

The next thing you need to do is set a reference to the System.EnterpriseSer-vices assembly. As you know, you do this by right-clicking the References node in the VS .NET IDE Solution Explorer window. Figure 19-8 shows the appropriate component selection that you are targeting.

click to expand
Figure 19-8: Adding a reference for System.EnterpriseServices with the VS .NET IDE Component Selector window

Following this reference-adding task, you have a few remaining steps to go: adding actual code, decorating your code with attributes, and creating a strong name key. You will notice that I have included the COBOL .NET code for the MyFirstClassLibraryCobol project and the VB .NET code for a VB .NET “versioned class library project named MyFirstClassLibraryVB.

Note  

You must set a reference for System.EnterpriseServices in the VB .NET “versioned sample application.

Sample Class Library Code Using COBOL .NET

The code you use for the sample application MyFirstClassLibraryCobol appears in Listing 19-1. You will notice the System.EnterpriseServices.ServicedComponent class is inherited. Additionally, you will notice the use of a System.EnterpriseServices attribute class.

Listing 19-1: The MyFirstClassLibraryCobol Sample Code
start example
 000010 IDENTIFICATION DIVISION. 000020 CLASS-ID. MyFirstClass AS "MyFirstClassLibraryCobol.MyFirstClass"  000021           INHERITS CLASS-ServicedComponent. 000030 ENVIRONMENT DIVISION. 000040 CONFIGURATION SECTION. 000051 SPECIAL-NAMES. 000052    CUSTOM-ATTRIBUTE AutoCompleteAttribute  000053                     CLASS CLASS-AutoCompleteAttribute 000054    . 000060 REPOSITORY. 000070    CLASS CLASS-AutoCompleteAttribute  000071          AS "System.EnterpriseServices.AutoCompleteAttribute" 000073    CLASS CLASS-STRING AS "System.String" 000075    CLASS CLASS-ARGUMENTEXCEPTION AS "System.ArgumentException" 000076    CLASS CLASS-ServicedComponent  000077          AS "System.EnterpriseServices.ServicedComponent" 000078    CLASS CLASS-OBJECT AS "System.Object" 000079 . 000080 STATIC. 000090 DATA DIVISION. 000100 WORKING-STORAGE SECTION. 000110 PROCEDURE DIVISION. 000120 000130 END STATIC. 000140 000150 OBJECT. 000160 DATA DIVISION. 000170 WORKING-STORAGE SECTION. 000180 PROCEDURE DIVISION. 000190 000200 METHOD-ID. DOTRANSACTION AS "DoTransaction"  000201            CUSTOM-ATTRIBUTE IS AutoCompleteAttribute. 000202  000210 DATA DIVISION. 000220 WORKING-STORAGE SECTION. 000221   01 MyException OBJECT REFERENCE CLASS-ARGUMENTEXCEPTION. 000222   01 MyString PIC X(10). 000223 LINKAGE SECTION. 000224   01 InputString OBJECT REFERENCE CLASS-STRING. 000225   01 ReturnString OBJECT REFERENCE CLASS-STRING. 000230 PROCEDURE DIVISION USING BY VALUE InputString RETURNING ReturnString  000231    RAISING CLASS-ARGUMENTEXCEPTION. 000240*    The Input Parm is tested to be non-blank for DEMO purposes 000241    SET MyString TO InputString 000242    IF MyString NOT > SPACE 000243       INVOKE CLASS-ARGUMENTEXCEPTION "NEW"  000244       USING BY VALUE "Invalid Input Parameter"  000245       RETURNING MyException 000246       EXIT METHOD RAISING MyException 000247    END-IF 000248    SET ReturnString TO "Hello World with Enterprise Services". 000249 000250 END METHOD DOTRANSACTION. 000260 000270 END OBJECT. 000280 END CLASS MyFirstClass. 
end example
 

Please take a moment to review Listing 19-1. You will notice that one method has been included. This method, DoTransaction , makes use of the AutoComplete- Attribute class from the System.EnterpriseServices namespace. Notice that I did not use an additional attribute at the class level. I will explain this later. As you can gather, this is a very basic example of how to create a code-driven transaction.

Tip  

The System.ArgumentException class is included in Listing 19-1 to provide an example of .NET-style exception handling. Many other types (other than this one, which handles argument exceptions) of specific exceptions are available. The Microsoft documentation provides further details on this topic.

Now you'll quickly review the VB .NET sample code that basically accomplishes the same task.

Sample Class Library Code Using VB .NET

The sample code in Listing 19-2 was taken from the MyFirstClassLibraryVB sample application. Naturally, this class library code will inherit from the System.EnterpriseServices.ServicedComponent class. Please recall that this is one of the few definite requirements needed to convert a normal class library into a serviced component. Again, you will create a rather basic transaction using the specific function. Please take a moment to review the code in Listing 19-2.

Listing 19-2: Code from the MyFirstClassLibraryVB Sample Project
start example
 Imports System.EnterpriseServices <TransactionAttribute(TransactionOption.Required)> _  Public Class MyFirstClassLibraryVB       Inherits System.EnterpriseServices.ServicedComponent       Public Sub New()             MyBase.New()       End Sub       <AutoComplete()> Public Function DoTransaction() _       As String             Return "Hello World with Enterprise Services :-)"       End Function End Class 
end example
 

The main difference between the code in Listing 19-2 and the COBOL .NET sample application is the use of a System.EnterpriseServices attribute at the class level. The class-level attribute is TransactionAttribute . In the COBOL .NET code, this attribute was omitted intentionally (but it could have been included). This attribute is used to set the TransactionOption.Required property. In this case, you are setting it in code. In the case of the COBOL .NET sample, you set this same property manually.

Whether you set your component transaction support using the Transaction- Attribute attribute or using the manual approach (via the Component Services MMC snap-in), you actually have five choices. For the purposes of this discussion, assume that you are using the TransactionAttribute approach. Your particular application needs will dictate which TransactionOption enumeration you use for the TransactionAttribute setting. I chose TransactionOption.Required simply for demonstration purposes.

The complete list of TransactionOption choices are as follows :

  • TransactionOption.Disabled

  • TransactionOption.NotSupported

  • TransactionOption.Supported

  • TransactionOption.RequiresNew

  • TransactionOption.Required

Let's briefly take a look at the impact of choosing one enumeration over another. To begin with, you might wonder what the difference is between setting your TransactionAttribute with TransactionOption.Disabled and setting it with TransactionOption.NotSupported. After all, the names do imply a similar result ” the potential to render your component as nontransactional. Actually, choosing NotSupported does result in having a nontransactional component. On the other hand, the choice of Disabled basically implies that you do not want your com ponent to receive the automatic transaction management services offered by COM+.

Note  

You might use the Disabled option if for some strange reason you want to manually control the transaction management of your component. You should be aware that if you happen to use the Regsvcs.exe tool to introduce your serviced component into COM+, the TransactionOption will default to TransactionOption.Disabled.

The remaining three TransactionOption enumeration choices will likely be of more use to you. Figuring out which one to choose is rather straightforward. Say that your component participates in a multicomponent application design. In this multicomponent design, say that you have component X that is called by a client application and initiates the logical unit of work. Then, after component X, the parent, has done some work, you may have a child component Y that gets called to do work. Perhaps a third component Z, another child, gets called to complete the logical unit of work and complete the transaction.

It's easy to imagine that you might want component X to always be created in a new transaction. This would be a chance to set your TransactionAttribute to use TransactionOption.RequiresNew. Now, let's change the scenario to have the parent component needing to participate in a transaction and needing to have the capability to create its own transaction. Assume that in this case it is not important that component X participate in a "new" transaction. This scenario is perfect for the choice TransactionOption.Required . Component X causes the creation of a new transaction if one does not exist.

The child components described in this scenario are good candidates for the TransactionOption.Supported option. This option communicates that component Y and component Z share the transaction created by component X (i.e., the parent). If component X has not created a transaction, component Y and component Z do not care. In effect, they run as nontransactional. This is what the Supported option gives you. However, if you want component Y and component Z to really care about the existence of a transaction, use the TransactionOption.Required setting. This allows the child components (component Y and component Z) to share an existing transaction or create their own if needed.

Note  

Further research into the topic of COM+ transactions and object creation will have you learning about the "context." In this context, a context represents an organizing or grouping mechanism that COM+ uses. Each component, as it's used in COM+, gets assigned to a particular context . The transactional support implemented by your component can affect whether your component gets its own context or inherits the context of its client.

As your application designs will vary, so will your use of the TransactionOption enumeration. Having a basic understanding of these TransactionOption choices will prove to be useful. Keep in mind that you can also apply your understanding of these options to the situations where you might choose to manually set the trans action support COM+ component properties (using the Component Services MMC snap-in).

Tip  

You will notice that both the VB .NET and COBOL .NET samples use the AutoComplete attribute (at the method/function level). Using this attribute saves you the trouble of having to explicitly call the SetAbort or SetComplete function.

The remaining task for both sample applications is to create a strong name key. Once you create the strong name key (.snk) file, you will need to add a few assembly-level attributes.

Creating a Strong Name Key (.snk)

In Chapter 17 I briefly discussed the concept of a strong name. During that discussion, I mentioned the command-line utility Sn.exe. I will now demonstrate how to use this tool to create a strong name key file for your two class libraries. The creation of a strong name key is a requirement for your serviced component.

Note  

Use of the Global Assembly Cache (GAC) is not a requirement for your serviced component. However, it is recommended that you consider putting your managed serviced component into the GAC. If your serviced component is installed as a COM+ server application, this becomes more critical. The reasoning for this speaks to the potential need for Dllhost.exe to communicate with your managed serviced component. A separate concern surrounds the use of ASP.NET and a dynamic registration installation for your serviced component. If you are not using the GAC, your assembly will be shadow- copied into the download cache. Keep these points in mind. You use the Gacutil.exe to place your managed serviced component into the GAC.

To create a strong name you will need to navigate to the Visual Studio .NET Command Prompt window (click the Start button and select Programs Microsoft Visual Studio .NET Visual Studio .NET Tools Visual Studio .NET Command Prompt) and enter sn followed by -k and < assemblyName >.snk . As shown in Figure 19-9, this is fairly straightforward.

click to expand
Figure 19-9: Using the Visual Studio .NET Command Prompt window to create a strong name key (.snk) file

After you create the .snk file, physically move each .snk file to the \bin folder of each respective sample application folder. Later, in the section "Using Regsvcs.exe," you will find that placing the .snk file in your \bin folder ( alongside your assembly/.dll) is a requirement for using the Regsvcs.exe command-line tool.

Adding Assembly-Level Attributes

You have seen attributes used at the assembly level before in Chapter 18. Now you will need to add an attribute setting for the strong name key file. As shown in Figure 19-10, you can update the Property Pages window to add assembly attributes for your COBOL .NET project.

click to expand
Figure 19-10: Adding the .snk file assembly-level attribute setting

For the VB .NET sample application, you add the assembly-level attributes into the AssemblyInfo.vb file. As you may recall, you access this file from the VS .NET IDE Solution Explorer window for the opened MyFirstClassLibraryVB sample project. The code snippet in Listing 19-3 shows the attributes used in the VB .NET sample application.

Listing 19-3: Assembly Attribute Code Used in the AssemblyInfo.vb File for MyFirstClassLibraryVB
start example
 Imports System.Reflection Imports System.Runtime.InteropServices Imports System.EnterpriseServices . . . <Assembly: ApplicationNameAttribute("MyFirstCOMPlusAppVB")>  <Assembly: AssemblyKeyFileAttribute("bin/MyFirstClassLibraryVB.snk")>  <Assembly: ApplicationActivationAttribute(ActivationOption.Library)>  <Assembly: ClassInterface(ClassInterfaceType.AutoDual)> . . . 
end example
 

As you can observe, I used a few additional attributes for demonstration purposes. The main requirement is that I have added the attribute setting to support the inclusion of the strong name key file.

Note  

Observe the use of the assembly-level ApplicationActivation- Attribute attribute. The choice of "Library" as an activation type has important implications. I discuss this topic further in the section "Using the /regfile:<filename.reg> Option."

Finally, you can build each sample project. Congratulations! You have created a serviced component. Shortly, you will explore the steps you need to take to use this class library (.dll) file that you have turned into a serviced component.

While I am on the topic of the System.EnterpriseServices namespace, I will drill down just a bit. For example, there are other attributes that you could have used from the System.EnterpriseServices namespace. In the next section you will take a quick look at those.

Other System.EnterpriseServices Attributes

This is a good breaking point to mention the other attributes that your serviced component can make use of from the System.EnterpriseServices namespace. In most cases, the attributes represent "property settings" that you can set either in code using an attribute or manually using the appropriate MMC snap-in (I discuss the MMC snap-in used for this purpose in the section "Introducing Your Serviced Component to COM+").

I have provided Listing 19-4 for your convenience. Please refer to the available Microsoft .NET documentation for details regarding the use of each attribute.

Listing 19-4: The Available Attributes from the System.EnterpriseServices Namespace
start example
 System.EnterpriseServices.ApplicationAccessControlAttribute  System.EnterpriseServices.ApplicationActivationAttribute  System.EnterpriseServices.ApplicationIDAttribute  System.EnterpriseServices.ApplicationNameAttribute  System.EnterpriseServices.ApplicationQueuingAttribute  System.EnterpriseServices.AutoCompleteAttribute  . . .CompensatingResourceManager.ApplicationCrmEnabledAttribute  System.EnterpriseServices.ComponentAccessControlAttribute  System.EnterpriseServices.COMTIIntrinsicsAttribute  System.EnterpriseServices.ConstructionEnabledAttribute  System.EnterpriseServices.DescriptionAttribute  System.EnterpriseServices.EventClassAttribute  System.EnterpriseServices.EventTrackingEnabledAttribute  System.EnterpriseServices.ExceptionClassAttribute  System.EnterpriseServices.IISIntrinsicsAttribute  System.EnterpriseServices.InterfaceQueuingAttribute  System.EnterpriseServices.JustInTimeActivationAttribute  System.EnterpriseServices.LoadBalancingSupportedAttribute  System.EnterpriseServices.MustRunInClientContextAttribute  System.EnterpriseServices.ObjectPoolingAttribute  System.EnterpriseServices.PrivateComponentAttribute  System.EnterpriseServices.SecureMethodAttribute  System.EnterpriseServices.SecurityRoleAttribute  System.EnterpriseServices.SynchronizationAttribute  System.EnterpriseServices.TransactionAttribute 

Also, please keep in mind that there are other delegates, interfaces, classes, enumerations, and structures (remember the DICES acronym?) available for your use in the System.EnterpriseServices namespace.

You are ready now to introduce your serviced component to COM+.

end example
 

[5] The .dll file was originally referred to as a dynamic link library.




COBOL and Visual Basic on .NET
COBOL and Visual Basic on .NET: A Guide for the Reformed Mainframe Programmer
ISBN: 1590590481
EAN: 2147483647
Year: 2003
Pages: 204

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net