Thursday, May 28, 2009

JSP include tag versus include directive

The first thing to note is that if either of these directives fails, then the page stops loading.

The directive will accept a relative path from the current location; the tag must have a path that starts with /, which is the root of the web application, not the root of the server.

The difference between the two is how they handle dynamic content. The tag includes the output of the dynamic reference in the page at runtime; the directive includes the contents of the dynamic reference when the including JSP is compiled into a servlet.

I am hard pressed to devise an example using JSPS that has different output for the tag and the directive. The directive can only include actual files, so the directive is useless if CGI or PHP files are to be included.

If the tag includes a reference to a servlet, be sure that the servlet does not close the output stream. This is a problem for a servlet that forwards to a JSP, since the output stream is closed after the forward is complete.

Both by-pass the security constraints in the web.xml file. Both can access WEB-INF, directly.

Both can only include resources that are in the web application.



I just read on another site that the difference is when they are loaded.

The tag loads at runtime.

<jsp:include page="includedPage" /> 

The directive loads at compile time.

<%@ include file="banner.jsp" %> 

From http://stackoverflow.com/questions/9188478/how-to-implement-a-include-jsp-tag

Friday, May 22, 2009

Connecting with JDBC to SQL Server

My tale of woe that has a happy ending.

I wanted to connect to SQL Server 2005 using JDBC. I verified the connection string and used standard code to test the connection.

try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String connectionUrl = "jdbc:sqlserver://localhost:1433;" +
"databaseName=Northwind;user=x;password=x;";
Connection con = DriverManager.getConnection(connectionUrl);
} catch (SQLException e) {
System.out.println("SQL Exception: " + e.toString());
} catch (ClassNotFoundException cE) {
System.out.println("Class Not Found Exception: " + cE.toString());
}
When I ran the code, I received this error
com.microsoft.sqlserver.jdbc.SQLServerConnection Prelogin
WARNING: ConnectionID:1 Prelogin error: host localhost port 1433 Unexpected response status:0
Actually, I received that error multiple times and eventually received a stack trace of

SQL Exception: com.microsoft.sqlserver.jdbc.SQLServerException: The TCP/IP connection to the host localhost, port 1433 has failed. Error: "The driver received an unexpected pre-login response. Verify the connection properties and check that an instance of SQL Server is running on the host and accepting TCP/IP connections at the port. This driver can be used only with SQL Server 2000 or later.

I then checked many sites for this message, but none had the exact message.

I tried logging into SQL Server directly, using the SQL Server Management Express program. I was able to log in with my user account, but could not access the Northwind or pubs databases. I conferred with some colleagues and needed to set the server with mixed access: Windows and SQL. There was an old account that I had created, named sa. I reactivated it and changed its password. I logged on with it and then updated my Windows login account with sysadmin rights. After this, I was able to connect to the Northwind and pubs databases; however, I still received the original error when I tried to connect to the database using JDBC.

After more searching, I found the Code Ranch site which talked about removing dynamic ports and setting a static port in the SQL Server Configuration Manager. I tried to follow the instructions, but my server would not restart with a static port of 1433. I then tried to access the server from JDBC using the dynamic port and was able to connect.

Next, I tried to connect to the database using Hibernate. I used the JDBC driver from microsoft, the package for the driver is com.microsoft.sqlserver.jdbc.SQLServerDriver. The Hibernate dialect for SQL Server is org.hibernate.dialect.SQLServerDialect. I was unable to connect. I used the same URL as I used when connecting with Java, jdbc:sqlserver://localhost:3346/Northwind. The dynamic port is 3346, the name of the database is Northwind.

There was a helpful post about clients and servers that guided me to the SQL Server Configuration Manager again. This time, I started to understand what I was seeing. There is the SQL server and the SQL client. The client was using port 1433, the server was using port 3346. I changed the client to 3346, but I still had an error.

The error was an SSL error. I found a helpful link about certificates, but I was unclear about exporting my certificates and lost them. Since this link referred to installing SQL Server after deleting the certificates, I am downloading Server 2008. I am hoping that a new installation will miraculously have no problems!

The referring page also had some information about not installing the old certificates, but creating a new one. I am investigating. It refers to a program named SelfSSL.exe.

I did not pursue the creation of a certificate, since the reference was for IIS. I did complete the new installation of SQL Server 2008. I am able to access sqlcmd from the command line and am able to connect to the server from Java. I did not have to tweak any parameters, both the client and the server were using 1433 and TCP/IP was enabled.

I did have one confusion, that may have been the basis of a lot of my problems: I didn't know what a schema was in SQL Server. According to MicroSoft, a schema is like a namespace for tables that can be accessed. If you don't have the correct schema, then you can't see all the tables. The default schema is dbo. Once I changed all my tables to that schema, I was able to connect and see them in NetBeans database services.

I still could not connect using Hibernate. I decided to reinstall MySQL, since I was missing the GUI admin app. After installing, I followed an excellent tutorial on using MySQL in NetBeans. I also found an excellent tutorial for using NetBeans to reverse engineer tables to create POJOs. Once I had these tutorials running, I tackled SQL Server 2008.

I modified the process from the tutorial to create the POJO for two tables from the Northwind database. I found an excellent tutorial for installing Northwind and pubs databases, which for some reason are not included in the install of SQL Server. Once I had the table, I changed the database to the SQL Server instead of MySQL. I have included the important properties below.
   <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<property name="hibernate.connection.url">jdbc:sqlserver://localhost:1433;databaseName=mydb</property>
<property name="hibernate.connection.username">name</property>
<property name="hibernate.connection.password">pass</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
The only difference that I could see from what I had used before was the current session context class; however, in my last iteration of testing before the reinstall, I omitted the dialect. That was probably the big error.

It finally works. In review, I had a problem with SQL Server 2005 that I never resolved; the new installation works without a hitch; I probably had a problem with schemas in the 2005 tests.
 

Sunday, May 3, 2009

Enabling SSI in Apache Tomcat 6.0

I used the filter option for SSI in Tomcat 5.5. When I upgraded to Tomcat 6.0, I had to use the servlet option. When I used the filter option I received the error

SEVERE: Error filterStart

The web.xml file that I used had a comment about renaming a Jar file; however, it seems that the comment is left over from 5.5. There is no such Jar file in 6.0. The comment was also missing the instruction to uncomment the servlet mapping for the ssi servlet.

In summary, follow these steps to enable SSI in Tomcat 6.0

  1. Use the servlet, not the filter.
  2. Uncomment the servlet definition and servlet mapping for the ssi servlet in web.xml.
  3. Mark the context as privileged.

Tuesday, March 3, 2009

Serialization

There are several ways to implement serialization in .NET. The simplest way is to mark the class as Serializable and then to create a formatter to do the serialization. Fields that are not serializable can be marked as such and will not be serialized.
[Serializable]
public class SomeClass {
//mark members that are not serializable
[NonSerialized] SomeNoneSerializedType t;
}
The formatter can be created in any class that needs to serialize the above class.
public void SomeSaveHandler(Object sender, EventArgs e) {

using (SaveFileDialog dlg = new SaveFileDialog())
{
if (dlg.ShowDialog() != DialogResult.OK) return;
using (Stream stream =
new FileStream(dlg.FileName, FileMode.Create, FileAccess.Write))
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, instanceSomeClass);
}
}
}
Deserialization is similar.
public void SomeOpenHandler(Object sender, EventArgs e) {

using (OpenFileDialog dlg = new OpenFileDialog())
{
if (dlg.ShowDialog() != DialogResult.OK) return;
using (Stream stream =
new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read))
{
IFormatter formatter = new BinaryFormatter();
SomeClass someClass = (SomeClass) formatter.Deserialize(stream);
}
}
}
More than one object can be serialized by having additional calls to serialize; one for each object. During deserialization, make a corresponding call to deserialize for each object that was serialized; use the same order when deserializing as was used when serializing.

For elements that are calculated fields, they can be recalculated after the object has been deserialized, by implementing the IDeserializationCallback interface. Define the callback method OnDeserialization to instantiate any calculated fields. The parameter to this method is not implemented at this time, so it is always null.
[Serializable]
public class SomeClass: IDerializationCallback {
//mark members that are not serializable
[NonSerialized] SomeNoneSerializedType t;

public void OnDeserialization(object sender) {
t = SomeCalculation();
}
}


The other method to serialize takes a different approach. Instead of assuming that everything is serializable, it assumes that nothing is serializable. Instead of indicating what should not be serialized, the class must specifically serialize each element. This technique is implemented in the interface ISerializable. Define the method GetObjectData and define a constructor that will be used during deserialization.
[Serializable]
public class SomeClass : ISerializable {
SomeType t;
SomeNoneSerializedType non;

public SomeClass(
SerializationInfo info, StreamingContext context)
{
t = (SomeType) info.GetValue("myType", typeof(SomeType));
non = SomeCalculation();
}

public void GetObjectData(
SerializationInfo info, StreamingContext context)
{
info.AddValue("myType", t);
}
}
Call info.AddValue for every member that needs to be serialized. Call info.GetValue for every member that needs to be deserialized.

There is no need for the deserialization callback interface, since calculated fields can be instantiated in the deserialization constructor.

This technique is useful for classes that extend a non-serializable class. The first technique will fail, if the base class cannot be serialized. By using the second technique and specifically serializing each element, the base class does not need to be serializable. The trick in this case is to make sure that any other constructors also get called when the deserialization constructor is called.

For the class that has to serialize this class, there is no difference when creating a formatter for either of these techniques. The calling class just calls serialize and deserialize on the formatter, it is up to the serializable class to determine how it will serialize.



It is possible to add methods to a class that will serialize/deserialize the class by creating a formatter. This encapsulates the entire process of serializing the class so that the class that is doing the serialization will not have to implement the details for creating the formatter.

The second technique is the preferred technique for implementing such methods. While the first technique could be used, its simplicity is lost, since it is not possible to deserialize into this. In order to make the first technique work from a method in the class, it would be necessary to deserialize into another class and then copy member by member into the current class. Another possible implementation would be to serialize/deserialize member by member.

Sunday, March 1, 2009

Handling Arrows

The arrow keys for a container control in .NET are used to switch the focus amongst multiple controls in the container. If a container has several controls, then the arrow keys will move the focus from one control to the next. This is a special behavior for the arrow keys in a container control. In the default case, the arrow keys never reach the controls in the container. There are several ways to get the arrow keys to the controls themselves.

The first way is to allow the arrow keys to maintain the special function that they have. Override the ProcessCmdKey method and add the additional handling for the arrow keys. To allow the keys to have the special function, be sure to call the base class method, in order to have the special function executed.

The second technique is to remove the special function altogether. There is another method called IsInputKey. If it returns true, then the key is passed directly to the control, without the preprocessing of the key. If it returns false, then preprocessing is executed; the key will only make it to the control if the preprocessing routes it there. If the key makes it to the control, then it can be caught in the normal KeyDown handler.

There is a third way, which I will call technique one-and-a-half. If in technique one, the ProcessCmdKey method returns true instead of returning the base class method, then the preprocessing will not be done. This has the same effect as method two. Instead of handling the key in KeyDown, handle the key in ProcessCmdKey.

There is another method for solving this problem: override OnPreviewKeyDown. This method can behave like ProcessCmdKey, but it works for all the keys: extra coding can be done for any key. There is even an event args property for IsInputKey which allows this method to perform like IsInputKey. To remove the command key functionality, set IsInputKey to true.

KeyCode is the code for the key pressed, without any modifiers like Shift or Control.

KeyData is the code for the key OR-ed with any modifier keys, like Shift or Control.

KeyValue is the integer equivalent of KeyData for passing to unmanaged methods.

KeyChar is generated from KeyPress event and has the ASCII code for a key.

Thursday, February 26, 2009

Testing for a Toggled Key

There are several keys on the keyboard that can be in a toggled state: num lock, scroll lock, cap lock and insert. There is a convenient method in the Control class that will get the state of the button: Control.IsKeyLocked(key). The key parameter can be one of Keys.CapLock, Keys.NumLock, Keys.Scroll and Keys.Insert. The method returns true if the key is in the toggled state, otherwise it returns false.

According to the MSDN documentation, the method will throw a NotSupportedException if the key is not CapLock, NumLock or Scroll; however, Insert also works and does not throw an exception.

This method has been available since .NET 2.0. For earlier versions, it was necessary to do some interop with the user32.dll. There is a method that returns a bit field for the state of a key. For keys that can be toggled, the lowest bit in the field will be 1. Use a bitwise & operation to isolate the bit.

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern ushort GetKeyState(int keyCode);

//From winuser.h
private const int VK_INSERT = 0x2D;
private const int VK_NUMLOCK = 0x90;
private const int VK_SCROLL = 0x91;
private const int VK_CAPITAL = 0x14;

public static bool IsKeyToggled(int nKey)
{
return (GetKeyState(nKey) & 0x01) == 1;
}

The hex codes for the keys can be obtained from winuser.h. In VS08, I found this file under the SDK folder for smart phones and pocket PC.

For Vista, there is also a Keyboad class that is part of the System.Windows.Input namespace. References to the presentation core and to the windows base dll's must be made. The presentation core contains the Keyboard and Keystate classes. The windows base contains the Key class. Be careful with the Key class, since there is also a Key class in System.Windows.Forms.

Keyboard.GetKeyStates(Key.CapsLock) == KeyStates.Toggled

 

Thursday, February 19, 2009

Running WPF in a Browser

Aaarrrggghhhh!!!!! Microsoft Security Exceptions!

I have been trying to get my first example of an XBAP file running in a browser. I am using the book Essential Windows Presentation Foundation, by Chris Anderson. I did not have any problems with Chapter 1 and was able to download the source code for the more complicated examples at the end of the chapter.

Chapter 2 does not have any source code available. I was trying to run a very simple "Hello World" application. I was still using the command line to run my examples, just to get a feel for the syntax of the project and application files. I ran the application as an exe without a problem. Next, I added the property in the project file to allow the app to run in the browser.

<PropertyGroup>
<HostInBrowser>true</HostInBrowser>
</PropertyGroup>

When I ran it, I received an error about signing the manifest.

Error 3 The ClickOnce manifest for XAML Browser Applications must always be signed. You must specify properties: SignManifests (value set to True), and either ManifestKeyFile (with the name of your key file) or ManifestCertificateThumbprint (hexadecimal thumbprint value in SHA-1 format, of key file). Alternatively, you may use your IDE's Publish Wizard or Signing options.


I referred back to the book and saw a footnote about singing manifests using Visual Studio. I opened Visual Studio and created a new WPF Project. A lot of files were created for me. I signed the manifest from the Properties -> Signing tab. I created a temporary certificate. I ran the simple application as an exe and it worked. I edited the csproj in a text editor and added the code for running in a browser. I tried to run the app from VS, but could not, since it is meant to be run in the browser. I found the XBAP file in the file system and double-clicked it. The browser opened and I received this error.

System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.

Looking further in the error list, I noticed that the assembly did have UIPermission, but only for save top level windows. I then remembered that the example from the book used Page as the base class, but that the default application in VS used Window. I edited the project so that it used Page instead of Window. I still had the same error.

When I had developed this from a different computer, I received a different error about the assembly not allowing partially trusted callers to use it. I had resolved this on the other computer, so I thought it might be a problem on this one. There is a very detailed explanation of the problem on the web. The trick is to add the AllowPartiallyTrustedCallers attribute to the code-behind file, at the assembly level.

using System.Security;
[assembly: AllowPartiallyTrustedCallers]

I still had the error. I had seen some posts on the web about similar errors that referred to publishing the application, so I published it, using the Build menu. The URL that was generated had an extra " at the end, so it failed. After removing that, I was given a directory listing. I double-clicked the XBAP file and it worked.

Since I had made so many changes before the application worked, I backtracked to see which one(s) had done the trick. The only one that I did not need was for the PartiallyTrustedCallers. Apparently, the computer I am using now has different access rights than the one I was using earlier, so I will keep the assembly attribute in the final solution.

Looking back at the first error I received, I see that it suggests using the IDE's signing or publishing wizards to sign the manifest; apparently, both signing and publishing are needed.

PS. There was another error that I saw referenced on the web about the application cache. At some point I also tried clearing it. The process was to close the browser, open the VS commmand prompt and execute the command mage -cc. The command took a minute to complete. I do not think this had anything to do with getting my example to run.

PPS. I have reconfigured the application for the original computer: I changed the app from a base class of Window to Page and published the application. I did not need to add the partially trusted attribute. To be more specific, I ran it with the attribute, then I removed the attribute, rebuilt, republished and it still ran.
 

More Blogs

Followers