(For more on C# and database access, see Accessing Data with ADO.NET or http://www.c-sharpcorner.com/Database.asp)
[WebMethod]
public string generate(string account) {
/**
conStr is the static connection string
/
SqlConnection conn = new SqlConnection(conStr); SqlConnection conn2 = new SqlConnection(conStr);
SqlDataReader accountReader = null;
SqlCommand sql;
/** returns the exact path to the command shell executable. **/
string command = Environment.ExpandEnvironmentVariables("%comspec%");
string returnInfo = "";
string fpID = "0";
/ I've simplified this example so you don't have to look at all the code
/
try
{
sql = new SqlCommand("SELECT FrontPageID, Command "+
" FROM WebFrontPageRequest " +
"WHERE Account = '"+account+
"' AND Completed = 0",
conn);
conn.Open();
accountReader = sql.ExecuteReader();
do
{
while(accountReader.Read())
{
fpID = accountReader["FrontPageID"].ToString();
conn2.Open();
/** Update the command **/ sql = new SqlCommand("UPDATE "+
"WebFrontPageRequest SET "+
"Completed = 1 WHERE FrontPageID = "+
fpID, conn2);
sql.ExecuteNonQuery();
conn2.Close();
string readerCmd = accountReader["Command"].ToString();
ProcessStartInfo startInfo = new ProcessStartInfo(command,args);
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.WindowStyle = ProcessWindowStyle.Normal;
startInfo.CreateNoWindow = false;
Process proc = Process.Start(startInfo);
proc.WaitForExit();
if (proc.ExitCode != 0)
{
// TODO: clean up your mess
returnInfo = returnInfo+
"unsuccessful "+
command+args+ proc.StandardOutput.ReadToEnd()
+"\n" +
proc.StandardError.ReadToEnd()
+"\n";
}
else
{
returnInfo = returnInfo+
"successful "+
proc.StandardOutput.ReadToEnd();
}
}
} while(accountReader.NextResult());
}
catch(Exception e)
{
conn2.Open();
sql = new SqlCommand("UPDATE WebFrontPageRequest "+
"SET Completed = 0 "+
"WHERE FrontPageID = "+
fpID, conn2);
sql.ExecuteNonQuery();
conn2.Close();
return e.Message;
}
finally
{
if(accountReader != null)
accountReader.Close();
conn.Close();
conn2.Close();
}
return returnInfo;
}
Now that there is a method to do some work, the web service can be built and published to a production server. There is an option to publish the service under the build menu.
Once the service is on production server is when the real fun begins which brings us to the Application Pool but before I get to the Application pool here's a little brief on the new issue. Up to this point, there is a web service that is attempting to create webs on an IIS server. Well when the service is called I can see the service start and then die. IIS runs under the ASPNET account which doesn't have administrative rights to execute commands like owadmin.exe, or cacls.exe, etc. Since the server is providing services for multiple users I didn't want to grant ASPNET the rights to satisfy the requests of the service because others could then write code that utilizes these rights. Thus, I had to create a new local account and grant it administrative rights. If you use my approach, you will also have to grant the account rights to log on as a service. For more information on "IIS 6 & Service Unavailable Errors" see Brian Desmond's Blog. You'll have to modify the security settings for your new account before the Web Service will execute without error. You need to make sure that the new account has setting to log on as a service. You can get a good idea of what is needed by looking at the ASPNET account security settings.Application Pool
Application Pools allow .NET applications to run in isolation of each other. Each pool has it's own worker process, thus, if one pool chokes, it won't affect the other applications running on the system. For my purposes, I have multiple application running on the server, most of which are out of my control and don't need special priviledges to do their work. However, the web service that was created does need rights. So, I configured a new application pool to run as another user for the web service and only the web service.
From the next dialog, name your Application Pool. I also selected to use the default app pool as a template. This allowed me to take advantage of configurations that already exist in the default pool.
Once the new app pool is created, you need to modify the pool's identity. Initially the pool uses the Network Service account. I changed this to use the new user administrative account created above. This will allow the worker process to execute the commands needed to generate a web.
For more on application pools, see the article on http://www.developer.com/net/asp/article.php/2245511. Now that the application pool is configured, the web site that hosts the application must be configured to use the new pool. To configure the pool, go to "Web Sites" in IIS and right click on the web that is hosting the web service. Select "Properties". From the properties dialog you can set the application pool that this web will use from the lower drop-down list.
Once the pool is set, restart the web. Now the web service is running under an account that has proper rights to execute the tools needed to create webs on the server.On a side note, I've seen posts where users are trying to impersonate an administrative account to execute tools like owsadm.exe. This will not work because the web application is running under the ASPNET account and doesn't have proper rights to execute those tools. Often I see users using the ProcessStartInfo object to impersonate the administrator like:
ProcessStartInfo.Username
ProcessStartInfo.Password
ProcessStartInfoDomain
This doesn't work and the process will hang or if you set a timeout, it will be killed without ever doing the work because the CreateProcess API is called, and the Platform SDK states: "If the calling process is impersonating another user, the new process uses the token for the calling process, not the impersonation token". Since the underlining process is ASPNET, the process doesn't work. My work around, was to create a new pool running under a less restrictive process solely to execute tools and whalla!
Apache Axis
Back to Java! The Apache Group has come out with some really helpful tools to get me through my day; Ant, Commons, Maven2, Tomcat, to name a few. For consuming web services, I don't think they could make it much easier with Axis. The when you download Axis it comes with a tool to convert a WSDL to client bindings, WSDL2Java, which allows you to consume a web service in a few lines of code, but before we look at the client code, here's how I generated the bindings:
java org.apache.axis.wsdl.WSDL2Java http://mywebservice.url/Service.asmx?WSDL
Executing the WSDL2Java tool created, five Java classes:
Service.java
ServiceLocator.java
ServiceSoap.java
ServiceSoap12.java
ServiceSoapStub.java
The generated classes are described in the table below (from the Axis site)
| WSDL clause | Java class(es) generated |
|---|---|
| For each entry in the type section | A java class |
| A holder if this type is used as an inout/out parameter | |
| For each portType | A java interface |
| For each binding | A stub class |
| For each service | A service interface |
| A service implementation (the locator) |
Once the Axis classes have been compiled I can use them to invoke the web service as follows:
import edu.fullcoll.axis.stubs.*;
public class TestClient {
public static void main(String [] args) {
try {
ServiceLocator loc = new ServiceLocator();
ServiceSoap port = loc.getServiceSoap();
System.out.println(port.generate("webaccount");
} catch (Exception e) {
System.err.println(e.toString());
}
}
}
This main should output something like "successful", if all goes well. At which point I am satisfied that I can incorporate this snippet of code into a portlet or any other Java application to access a .NET service.
The coding of the application wasn't difficult, just getting all the pieces to function properly since I wasn't that familiar with .NET and impersonation or .NET application pools. Additions to the code, I added some security to the web service to ensure that only authorized users have access to the service. You can get information on securing your ASP application at MSDN. Hopefully this helps if you're trying to get these two worlds to function in harmony. With the help of Apache and Microsoft, this whole process was a lot easier than I had planned. Enjoy!
Grabbed a tuna melt at
cable cars going by, people on the move, that's really enjoyable. Every time I come here, there is some real character to this place that is like no other place I've been. Quite nice to walk the streets, to see the hustle and bussel moving through the streets being apart of it for a week is a nice change. The weather is cool jacket weather that feels great from the heat of the south lately.
Got up at the break of dawn, 6:10 am (that's early for me), headed over to Moscone North, grabbed my registration and went to the lower level to pick up my materials for the conference. It's been since 2004 since I've visited Moscone and JavaOne, it looks similar to previous years, it always looked good and ready to deliver. This year is no exception. I guess I was so anxious to get over to the center and get my learn on that I had about two hours before my first Session, Developing Enterprise Applications with the Spring Framework, with two backpacks in tow I headed back to the hotel to drop some of this mess off.
Without actually thinking anyone would read this, I've been trying to spend a little more time writing in my blog. But work and life in general seem to get in the way.
Ok after years of procrastination, I've finally broken down and gotten a new phone, but not just any phone, I got an iPhone. After hearing all the hype and the expense I've fought the urge the purchase a new phone for some time. My previous phone was the Treo 650. Now I guess this phone serviced its purpose, but the interface had issues and I could never really tell how many voice messages were in my inbox without calling. The internet of the phone, was pretty much unusable.
Now I have a good portion of the
Now that I have the application (Sakai Gradebook) working as a portlet, I had to modify a few more things that the portlet framework didn't like. 
some work on behalf of the user that signed into 






