Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Monday, August 22, 2016

OpenXava

OpenXava is a nice Java based model driven development model such that you only have to create the domain classes you want to model. You then decorate the properties to add additional details such as relationships, if it is required, specify views, etc. The UI and database is generated automatically for you. This could be a very nice tool to do a quick POC or demo. It is open source that uses Eclipse as the IDE. It could be a good replacement for projects that used IronSpeed Designer and don't mind switching from C# to Java.

Monday, February 23, 2009

Make Tiny Time Tracker launch faster!

I like the Tiny Time Tracker application available from Source Forge that allows you to easily track how much time you spend on different tasks or projects. I highly recommend it. Its interface is very simple, but powerful. It basically has a drop down list that floats above all other windows. You can position it anywhere. You can shift time from one project to another if you forget to change it when you actually switched projects. It even stores the data to Excel. So, you get a very good reporting tool without any exporting. So, what is the problem you ask. Well, quite simply it takes way too long to open up. It takes like 30 seconds to open sometimes. If it is when I boot, it is even worse, but that is probably because of all the start up apps I have. In my mind, this is a very simple application that should open in like 1-3 seconds, not 15 to 30 seconds. I think the problem is Java WebStart. It looks for updates before it loads the local copy. Plus, just opening WebStart takes many seconds. I decided to see how fast the application launches if I run the jar directly. I was very happy with the results. It launched in 1 to 2 seconds!!! The problem with the default installation of Tiny Time Tracker is that what you actually download is a .jnlp file. All this file does is tell the WebStart application where to download the latest copy from. What we need is the .jar file, not the .jnlp file. If you want your Tiny Time Tracker application to launch extremely fast, I recommend doing the following:
  1. Go to the CVS repository and select tinytimetracker.jar and download the latest tinytimetracker.jar. You will probably need to download poi-3.5-beta3-20080926.jar if you don't have it.
  2. You can put the tinytimetracker.jar file anywhere on your system. For simplicity, I assume you are putting it at c:\TinyTimeTracker\tinytimetracker.jar.
  3. Using Windows Explorer, navigate to the C:\TinyTimeTracker directory.
  4. Right-click and choose New | Shortcut.
  5. For the location of the item field that comes up, just enter the following: javaw -cp "C:\TinyTimeTracker\tinytimetracker.jar" tracker.Tracker
  6. Name the shortcut whatever you want to.
  7. Now you can double-click the shortcut and Tiny Time Tracker will launch much faster than it ever did using Java WebStart.
If you have any problems, you can also run the same command from the command line. This will give you more information.

Friday, June 27, 2008

A safe way to save entities in HP OpenView Service Desk (OVSD) web-api

If you have have worked with HP OpenView Service Desk (OVSD) web-api, you may have noticed sometimes it throws an exception that says "There are no changes to save." when you call the save() method on entities such as Servicecall, Workorder, Change, etc. This is annoying and fairly useless thing to know if you ask me. This should not be an exception in my opinion if you call save too often, especially since the api doesn't support transactions. Instead of repeating the same try catch blocks everywhere in my code, it became obvious to me that the safest thing to do is to just write a very simple method to call instead of the standard save() method on an entity. What the method below does is allows you to pass virtually any type of entity from HPOV web-api objects that have a save() method or more specifically inherit from IApiEntity object (this is at least all the major ones). Now instead of ... myServiceCallObject.save(); just call the method and pass it the object you want to save. SaveEntity(myServiceCallObject); This is clean and reduces unexpected bugs caused by this "exception" :) private void SaveEntity(IApiEntity entity) throws Exception { try{ entity.save(); } catch (Exception ex) { if (!ex.getMessage().equalsIgnoreCase("There are no changes to save.")) { throw ex; } } }

HP OpenView Service Desk Web-api saves when you don't expect it to.

To be fair, I have not looked in the documentation of the HP OpenView web-api docs, but I can't believe that records can be saved without called .save() method on an object. How you ask, here is an example in pseudo-code.
IWorkorder myNewWorkOrder = WorkOrderHome().openNewWorkorder(); IServicecall myExistingServiceCall = ServiceCallHome().openServicecall(1234l); // no work order will exist and will not be related to the service call before the call to the next line myExistingServiceCall.addWorkorder(myNewWorkOrder); // after the above call, the work order exists, and IS related to the service call. I could not believe it, but this is true. A word of caution if you mean to not save in all cases.

Thursday, June 26, 2008

HP OpenView template field returns null from Web-api

I tried to come up with a title for this that made sense, but it is just a weird problem really. I thought there was a bug in HP OpenView, but I am now confident it is a configuration issue. Here is the behavior I saw that will help explain what the issue is. I have a work order (though this issue is not specific to work orders I suspect) template. I have set the assigned to workgroup to a workgroup that happens to be inactive. Obviously I would not do this on purpose. Actually someone made the workgroup inactive and didn't know that the template was using it and should be updated. The issue is that when you create a work order using this template it shows the value of the assigned to workgroup field as blank (in the HP OpenView Service Desk Client) or null (in the case of the Java web-api. If you know that inactive workgroups show as blank or null then there is no problem. However, it is VERY frustrating when in the template you see a workgroup set, and in the UI and web-api call you see blank or null respectively. It just doesn't make sense without knowing this quirk. So, I hope this helps others. One other caveat to this is that IF the assigned to person is specified in the template then (at least with our business rules, I don't know if this is default behavior) the assigned to workgroup is changed to the workgroup of the assigned to person assuming that the workgroup is inactive. This was the main confusing part. We removed the assigned to person, and started getting validation errors that said the assigned to workgroup was null. So, while they seem unrelated, they are related in particular circumstances.
Good luck to all.

Thursday, March 20, 2008

Lessons learned with Web Services in Eclipse 6

I am using MyEclipse 6. It is quite nice. I learned the hard way were to find some resources and how to do things like Exception handling. I found the process to be much more difficult and the learning curve much steeper than I thought it would be. Here are some things I learned. MyEclipse has a project type called Web Service Project. Use this to start a new project that will be your web service. It also allows you to use XFire web services (not CXF until version ?? of MyEclipse). You can use Java 1.5 or Java 5. Getting Started:
Start with the tutorial I mention in my blog to get started: http://www.myeclipseide.com/documentation/quickstarts/webservices/
Examples: Get the XFire distribution (http://xfire.codehaus.org/Download and pick the Binary Distribution in zip package for the newest release) because it has some good examples in it. I didn't find this until way too late. You can also download the source code for XFire on this page if you want to also. Once you download the zip I highly recommend the Book example. It shows how to return complex types, and how to create your own custom exceptions. How to store application settings
I am sure there are many ways to do this... check out my blog on: http://justgeeks.blogspot.com/2008/03/storing-application-settings-in.html Make Complex types that use java.util.Date as a data type be nillable when generated in the WSDL.
The basic solution is create a file called YourClassNameHere.aegis.xml and put it in the same location as the class that defines the complex type that contains the java.util.Date property. In the file, do something like this:
<mappings>
<mapping>
<property name="datePropertyName" nillable="true"/>
<property name="anotherDatePropertyName" nillable="true"/>
</mapping>
</mappings>
Now your automatically generated WSDL will have nillable="true" for the properties that you specified in the mapping file. This is particular important when using ASP.Net 2.0 and Nullable Types to consume your web service. It means the difference between DataTime and DateTime?. For more details check out: http://www.nileshk.com/node/69#comment-12609 Exception Handling You can follow the example in the Book example noted above, or you can do it another way also. You can do much like they did in the Book example, except just have your custom exception class extend java.lang.Exception instead of the XFire specific type. This will cause your custom exception class to be serialized and set as the Detail property in the SoapException. You can then parse it using a standard XML parser on the client side. You will be catching an Exception of type SoapException on ASP.Net. If you want your properties of your custom exception class to show up in the serialized text, you will need to make sure that you have setters and getters for each member variable in your class. One key is that your web methods must explicitly throw your custom exception, not just java.lang.Exception. If you don't, the Detail property of the SoapException won't be filled in when it is serialized and sent to your client (web service consumer). This basically tells Aegis to use our custom exception type instead of just java.lang.Exception. Changing parameters (in0, in1, in2, etc) to the real names when the WSDL is generated. I searched long and hard to find a simple solution for this one. Much to my amazement there did not seem to be too many intuitive solutions. I picked the easiest one. My solution is very simple and requires no maintenance. It seems to be a bug to me, so.... Do just like the tutorial referenced in the Getting Starting section of this blog and add the new web service just as says EXCEPT when you get to the page that asks you for the Service Interface and Service impl. class, set the Service interface to the same thing as Service impl class. This will affect your server.xml file. Finish the wizard as noted in the tutorial. Next, open the xxxImpl.java file and remove the implements xxxx from the class declaration such that it does not implement the interface file. If there is an interface file you can safely remove it from your project now. You will never need it now. Now, when the WSDL is generated it will use the proper parameter names as you would expect. Go figure! Word of caution, I did not have as much luck doing effectively manually doing the same thing AFTER I did the wizard as the tutorial suggests. So, I suggest doing it from the start when you do it in the wizard. I also found that I couldn't query the for the WSDL without my CPU going to nearly 100% when I did it manually. I don't really know why, but it did. I suspected that maybe I just had to many methods in my class and was slowing the parsing of the class to generate the WSDL or something, so I put all my real code in another class and just have stub like web methods that simply call the other object and a method on it. This seemed to help, but all these issues could have been do to needing a reboot and trying too many different things and messing up some files. Hard to tell, so let me know if anyone else has a similar experience. Other Tips Make your life easier, just forget about getting access to the Request and other servlet type things. It is just too much of a pain. Stay away from web.xml when it comes to storing application settings. Accessing it programmatically seems to be container (application server) specific, so use a properties file or xml file.

Storing application settings in a property file

This is not a totally necessary class, but it doesn't abstract loading text from a properties file. For example if you need to store application specific settings or even localizations you can use this class to access it using flexible paths (dot notation or directory path style). Here is how to use it: Properties props = PropertyLoader.loadProperties("/some/package/Config.properties"); String val = props.getProperty(key); package mypackage;
import java.util.ResourceBundle; import java.util.Properties; import java.io.InputStream; import java.util.Locale; import java.util.Enumeration;
public class PropertyLoader { /** Creates a new instance of PropertyLoader */ public PropertyLoader() { } /** * Looks up a resource named 'name' in the classpath. The resource must map * to a file with .properties extention. The name is assumed to be absolute * and can use either "/" or "." for package segment separation with an * optional leading "/" and optional ".properties" suffix. Thus, the * following names refer to the same resource: * <pre> * some.pkg.Resource * some.pkg.Resource.properties * some/pkg/Resource * some/pkg/Resource.properties * /some/pkg/Resource * /some/pkg/Resource.properties * </pre> * * @param name classpath resource name [may not be null] * @param loader classloader through which to load the resource [null * is equivalent to the application loader] * * @return resource converted to java.util.Properties [may be null if the * resource was not found and THROW_ON_LOAD_FAILURE is false] * @throws IllegalArgumentException if the resource was not found and * THROW_ON_LOAD_FAILURE is true */ public static Properties loadProperties (String name, ClassLoader loader) { if (name == null) throw new IllegalArgumentException ("null input: name"); if (name.startsWith ("/")) name = name.substring (1); if (name.endsWith (SUFFIX)) name = name.substring (0, name.length () - SUFFIX.length ()); Properties result = null; InputStream in = null; try { if (loader == null) loader = ClassLoader.getSystemClassLoader (); if (LOAD_AS_RESOURCE_BUNDLE) { name = name.replace ('/', '.'); // Throws MissingResourceException on lookup failures: final ResourceBundle rb = ResourceBundle.getBundle (name, Locale.getDefault (), loader); result = new Properties (); for (Enumeration keys = rb.getKeys (); keys.hasMoreElements ();) { final String key = (String) keys.nextElement (); final String value = rb.getString (key); result.put (key, value); } } else { name = name.replace ('.', '/'); if (! name.endsWith (SUFFIX)) name = name.concat (SUFFIX); // Returns null on lookup failures: in = loader.getResourceAsStream (name); if (in != null) { result = new Properties (); result.load (in); // Can throw IOException } } } catch (Exception e) { result = null; } finally { if (in != null) try { in.close (); } catch (Throwable ignore) {} } if (THROW_ON_LOAD_FAILURE && (result == null)) { throw new IllegalArgumentException ("could not load [" + name + "]"+ " as " + (LOAD_AS_RESOURCE_BUNDLE ? "a resource bundle" : "a classloader resource")); } return result; } public static Properties loadProperties (final String name) { return loadProperties (name, Thread.currentThread ().getContextClassLoader ()); } private static final boolean THROW_ON_LOAD_FAILURE = true; private static final boolean LOAD_AS_RESOURCE_BUNDLE = true; // if true localization and caching is used. private static final String SUFFIX = ".properties"; }

Monday, March 17, 2008

Creating a web service in MyEclipse 5 or 6 and deploying to Tomcat application server.

Creating a web service in MyEclipse 5 or 6 and deploying to Tomcat application server.
Well, I can't say it is difficult, but I think the link below that points to a MyEclipse tutorial is great. It gave me everything I needed to get started.
The tutorial is also in the documentation included in MyEclipse 6 (maybe 5 also, I don't know). The tutorial is called "MyEclipse Code-First Web Services Tutorial" if you want to search the included doc for it. It is the same either way. Your choice. ;)
Enjoy!

Thursday, March 6, 2008

Setting Default page in JSF

I am assuming you have a JSF application that runs in Tomcat, and that you are using MyEclipse as your IDE (though it isn't really that important. What I wanted to do was instead of a url that included the specific default page, I wanted the ability for users to assume a default page in the url. For example: Users could put in the browser: http://myhost:8080/MyJSFApp/MyJSFPage.faces What I want them to also be able to do that will get them to the same page as if they had typed the above url. http://myhost:8080/MyJSFApp or
http://myhost:8080/MyJSFApp/
To make this work, there is a little trickery that we need to do. Step 1: Create a new JSP page called index.jsp (it could be called anything) Step 2: The only thing you need in the index.jsp file is: <jsp:forward page="/MyJSFPage.faces"/> At this point you should be able to type the following into the browser and have it redirect (without the url changing) to the MyJSFPage.faces page. http://myhost:8080/MyJSFApp/index.jsp Step 3: Now all we have to do is edit the web.xml file. You will most likely have a welcome-file-list tag already in the file. Change it (or add it if it doesn't exist) to the following (or similar for your application).

<welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> That's it. Side Notes This all assumes that JSF is using the .faces pattern to designate what a JSF page is. The whole reason we need the first two steps to create the index.jsp file is because the welcome-file tag must point to a file that actually exists in the file system. It can't be a .faces file, because it doesn't actually exist. Has anyone tried it such that JSF is setup to use a pattern like /faces/* instead of *.faces?. I have not tried it, but I think the same problem would exist because the faces directory directory doesn't exist either. Feedback is welcome on this issue. Instead of the JSP forward tag, you could use pageContext.forward("/MyJSFPage.faces") or requestDispatcher.forward("/MyJSFPage.faces") and the behavior would be the same. On the other hand if you want the url to change to the url of the new page in the browser, you could use response.sendRedirect("...") which can redirect to any page on any server (any url really). The difference is that this sends a response to the browser that sends back an immediate request to the url that you wanted to redirect to. This is slower, but may be the behavior that you need in some cases.

Monday, February 25, 2008

The cost effective way to develop web applications using Java.

Java Web Development
Objectives:
  • User friendly environment that is similar to ASP.Net
  • Low or no cost to develop and deploy
  • Flexible deployment options
  • Use standard and frameworks where possible
  • MVC or other separation of presentation code from business logic. In short Multi-tier architecture
NetBeans 6.0 for IDE
  • It supports deployment multiple Java Application servers
  • Sun as all but decided that there will not be a next version of Java Studio Creator (pending out cry from community), and has pushed technology out to NetBeans 6.0
  • Supports J2EE and Java 5 EE platform.
  • JavaServer Faces built in gives an IDE and framework much like ASP.Net.
  • Keeps pace with Java releases and technology changes
  • Drag and Drop or code by hand developement
  • FREE and OpenSource and Open Standards
  • IDE and our applications are platform independent.
  • Extensible IDE.
JavaServer Faces (JSF) for MVC and UI
  • Is to be included in future J2EE standard.
  • Can be used in same project as Struts (MVC defacto standard, but not an official standard)
  • Component based framework that encourages reuse between applications
Hibernate for Persistence
jUnit or HttpUnit for testing
log4j or Java Logging API for Logging
Tiles for templating

ASP.Net and NetBeans JavaServer Faces (JSF) comparison from a .Net Developers perspective

Both have server controls (tags in JSF) that encapsulate and enhance standard html elements and form elements.
Code-behind == Backing bean (aka Managed Bean)
They both have code-behind. JSF calls it backing beans. The difference is that backing beans are just plain old java objects (POJO). This means that they are just regular classes. They don't have to inherit from any class or interface.
Another difference is that Code-behind and the .aspx files are linked together by a page directive in the .aspx. Visual Studio does this automatically for you unless you change it manually or rename a file. In JSF, this linking is done in the faces-config.xml.
Event Handler (in Code-behind) == Event Handler (in Backing bean)
Both provide event handler for user actions such as button clicks, selections, etc. Event handlers in ASP.Net always return void, but in JSF they return a string or null. Null means just navigate to the current page (a postback essentially). Any other value is is basically the name of an action that determines what navigation is taken. This is the same model as the new MVC that is being worked on in .Net currently. With JSF the class that handles the event needs to implement the ActionListener, ValueChangedListener, etc.
Postback vs. MVC
While Postback is a special case of MVC navigation as described above, JSF also allows for true MVC processing. This means that all page navigation is also done in one place. This is nice when you need to make navigation type changes. This means all requests come through a controller, and then the Model (data store) pulls the data, and the View (user interface) is rendered for that data. JSF has a powerful feature called RenderKit that allows the rendering to differ based on what medium is accessing the app. For example, if I access a page with my cell phone or computer I can get a different interface. The only change is the View, the Model and Controller stay the same. How cool is that!
ASP.Net Life Cycle vs. JSF Life Cycle
JSF has 6 lifecycle phases for a request. Restore View, Apply request values, Process validations, Update model values, Invoke the application, Render the response.
.ASPX vs. .JSF
In ASP.Net pages have the file extension and the url is also .aspx. In JSF the url is different from the file name. The filename ends in .jsp and the url has .jsf instead. By default, a knowledgeable user could access your pages with .jsp extension, but we really want all requests to go through the .jsf extension so we configure our application this way typically. However, there are exceptions to this. You can also configure your application to process .jsp pages that have a /faces/ before them in the url. The key here is that JSF allow you to define the convention for specifying which JSP pages are handled by the JSF servlet and which are not. BTW, not all .jsp pages are JSF pages, that is the reason for needing the difference.
Validation Summary == Message Group
In ASP.Net in general validation can handled by validators, and errors reported back to the user using Validation Summary. JSF, has similar items. However, in JSF, the messages are added to the FacesContext. This makes it easy to add custom validation logic back to the user also. The FacesContext shows up in the Message Group. This allows for validation to occur at the Business Logic Layer more easily.
ASP.Net Validator controls vs. JSF Standard Validators
JSF has similar validators like ASP.Net, but not as many, though you can create custom ones or just add validation code to backing bean. JSF includes DoubleRangeValidator, LengthValidator, and LongRangeValidator. ASP.Net in contrast has RequiredFieldValidator, RangeValidator, RegularExpressionValidator, CompareValidator, CutomValidator. The number of validators don't match, but much of the same validation checks can be performed on both platforms.
ASP.Net Form Data Conversion vs. JSF Converters
ASP.Net requires that you convert string form values to data types that the database (model) uses. For example, if you have a textfield that only accepts integers on a ASP.Net web form you need to get the text from the control, do data conversion to an appropriate type such as an int and then store it to the database, etc. In JSF, the same thing is needed, but it can be done using the UI using things called Converters. These converters can use number and date formats much like Excel to convert and format data. While, the effect is the same, the way that the conversion is done is different. There are converters for just about every datatype.

Wednesday, December 19, 2007

Fixing Derby Driver error in NetBeans 6.0

I just installed NetBeans IDE 6.0. I also have SUN Java Studio, and NetBeans 5.5.1 already installed. They also seem to have a Derby database for them. When in NetBeans 6.0 I try to connect to any of the sample databases or even one that I create, I get message similar to "....unable to connect. cannot establish connection to using org.apache.derby.jdbc.ClientDriver (Unable to find a suitable driver).
To fix the issue I simply expand the NetBeans IDE | Services tab | Databases | Drivers | Java DB (4 of them) and add the path to the correct Derby database driver location. I just right clicked each of the drivers and chose Customize menu item. Then added the following path (customize it to your system) C:\Documents and Settings\MyProfileHere\.netbeans\6.0\jdbc-drivers\derbyclient.jar.

Wednesday, September 12, 2007

How to optimize HP OpenView Service Desk web-api calls

Open HP OpenvView Service Desk (OVSD). Go to the System administration module. In the tree select Data and then Web Api Application. Add a new item and give it a name. This is the name you will reference in your code. Add the attributes you will be using in your code. It is important to include as many of the columns as possible. Otherwise, they will be loaded on demand when you access them and this takes more time. Now that you have a Web Api Application defined in OVSD use the following code to use it in your code. public void SetWebApiApplication(ApiSDSession session, String appName) { IWebApiApplicationWhere where; IWebApiApplication[] applications; IWebApiApplication appl1; // Find the application mentioned in the argument. IWebApiApplicationHome applicationHome = session.getWebApiApplicationHome(); where= applicationHome.createWebApiApplicationWhere(); where.addCriteriumOnText(appName); applications = applicationHome.findWebApiApplication(where); if (applications == null) { System.out.println("There is no Web Api application called " + appName); return; } appl1= applications[0]; session.setApplicationSettings(appl1); } Essentially, when you use Web Api Application it is like doing the following in SQL. select col1, col5, col34 from MyLargeTable instead of select * from MyLargeTable You may not realize it, but I think OVSD also uses a "select" to do an update of data as well. The reason for this conclusion is that you must still search for the record you want to update, load the data into memory, make the modification, and then write change back to database. With that said, the biggest performance gain is going to be when you bring back many records instead of just one. There is still a performance gain for one or two records, but it is negligible in most cases because you have to specify the Web Api Application before you do the actual query.

Monday, August 6, 2007

Converting String to / from Date using Custom Formatting

In Java it is easy to convert a date as text / string to a Date object. String to Date object Date dateObj = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse("05/18/05 18:15:10"); Date object to String String dateStr = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(dateObj);

Thursday, July 12, 2007

HP Open View Service Desk web-api maybe long, but isn't Long

If the title of this blog is confusing, you may also find this blog confusing not because the content is confusing, but because you won't be able to understand what the developers that designed web-api were thinking. HP Open View Service Desk (OVSD) web-api is a set of java api's that have little to do with the web as far as I can tell. It is an api for OVSD that is implemented in Java and jarred. No big deal there, just a strange name. OVSD has a concept of OID and ID for some records like Service Calls. ID is what the unique id that is shown in the UI that end users use. OID is the unique ID that is used in Oracle for relationships. My big conundrum is what were the developers thinking when they created two methods to open (find and load) and service call. The two methods are called openServicecall(). It is overloaded to accept a Long or a long. Long is an object in Java, and long is a primitive in Java. Very different things. One might think that the developers were nice and just provided the ability to pass either an object or primitive. This would make sense, but is not what they did. They made long mean ID and Long mean OID. Only place to get that is in the documentation. Below is the correct snippet for opening a service call by ID (the end user value). ApiSDSession session = null; try { session = ApiSDSession.openSession(server, username, password); IServicecallHome scHome = session.getServicecallHome(); long id = 123456; // NOTE: long MUST be used, NOT Long IServicecall serviceCall = scHome.openServicecall(id); } catch (Exception ex) { // handle exception here } finally { session.closeConnection(); } I hope this saves someone hours of frustration.

Tuesday, February 27, 2007

Java Application Server start and stop manually

Starting the Java Application Server that comes with Java Studio Enterprise 8 by running the start-domain is not recommended due to parameters that are expected by the batch file. Consequently the batch file hangs. To properly start the Java Application Server, open a command prompt and type: Asadmin start-domain

To properly stop the Java Application Server, open a command prompt and type: Asadmin stop-domain

Tuesday, January 16, 2007

Java Web Service Exception Handling

This assumes that you are using JAX-RPC which uses SOAP 1.1 to implement a web service, and that the web service is being consumed by .Net (1.1 or 2.0). If you are using WS 2.0 there are some different options.

 

While it is possible to just throw an plain old Exception in your java web service, it will show up your .Net client as a exception. The problem is determining what exception you have catch once you get it. In this situation we need a code that can be used in the client to identify the exception without try to rely on the message of the exception since this is typically semi user-friendly text. Exception class doesn’t have the concept of a code to identify the exception. The good news is SOAPFaultException has the concept of a code and it also allows you to attach any other data that may be useful.

 

Creating a SOAPFaultException can be a little messy, so I recommend created a convenience method to encapsulate this. In case this isn’t clear, this goes in your java web service.

 

// Creates and returns a SOAPFaultException. Throws one if there is an error creating

// Should be Client or Server

// If it is Client then message should NOT be resent without change

// i.e. Server.Fault or Client.Fault

public SOAPFaultException NewException(String faultType, String errorCode, String errorMessage, String webServiceOperationName) throws SOAPException

{

 

       // The faultcode element provides an algorithmic mechanism for identifying the fault.

//SOAP defines a small set of SOAP fault codes covering basic SOAP faults.

       QName faultCode = new QName("http://FrontLineWebService/" + webServiceOperationName, faultType + "." + errorCode);

 

       // The faultstring provides a human-readable description of the SOAP fault and is not intended for algorithmic processing.

       String faultString = errorMessage;

 

       // The faultactor element provides information about which SOAP node on the SOAP message path caused the fault to happen.

//It indicates the source of the fault.

       String faultActor = "http://FrontLineWebService/" + webServiceOperationName;

 

       // The detail element is intended for carrying application specific error information related to the SOAP Body.

       Detail faultDetail = SOAPFactory.newInstance().createDetail();

 

       // Define what the body of the email should be in terms of XML. You can put whatever data you want here

       faultDetail.addChildElement("ErrorMessage").addTextNode(errorMessage);

       faultDetail.addChildElement("ErrorCode").addTextNode(errorCode);

 

       // for more info on params: see http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383507

       throw new SOAPFaultException(faultCode, faultString, faultActor, faultDetail);

 

}

 

Here is an example of how you would throw the SOAPFaultException in your web service.

 

 

public void testMethod() throws Exception, SOAPFaultException, java.rmi.RemoteException

{

 

       throw NewException("Server.Fault", "TEST_CODE", "This is only a test description in English", "testMethod");

}

 

 

Now that you can easily throw a SOAPFaultException (SoapException in .Net), you are all set. Here is an example of catching it in your .Net client.

 

using System.Web.Services.Protocols;

...

 

try

{

    MyWS ws = new MyWS();

 

    ws.testMethod(new testMethod());

   

}

catch (SoapException ex)

{

    if (ex.Code.Name == "Server.Fault.TEST_CODE")

    {

        // do stuff here

    }  

}

Tuesday, December 12, 2006

Web.xml to configure your Java Web Service

This blog describes how to configure your Java Web Service. Specifically, how to initialize your Java Web Service. In this article I assume you have used Sun Java Studio Enterprise 8 to create your RPC based web service.

Add the following lines to the top of you web service class. Typically this class ends in Impl. Your web service class needs to implement ServiceLifecycle. The example below shows how to read the init param called MyParam that is in web.xml.


import javax.xml.rpc.server.*;
import javax.xml.rpc.*;

public class MyDemoWSImpl implements MyDemoWSSEI, ServiceLifecycle {

     // store the servletContext here since we can only get it when the applet starts up.
     private ServletContext servletContext;


     // Required by ServiceLifecycle interface
     // This is only called once when the web service is started.
     // This is NOT called everytime a web method is called
     public void init(Object context) throws ServiceException
     {
          // get the servlet context
          // This is where the General context parameters (aka init parameters) of the web.xml are stored.
          ServletEndpointContext soapContext = (ServletEndpointContext) context;
          servletContext = soapContext.getServletContext();
     }


     // Required by ServiceLifecycle interface
     public void destroy()
     {
    
     }

     public String MyParam() throws Exception
     {
          return GetInitParam("MyParam");
     }


}

 

To add and specify the value for MyParam in web.xml you need to find you web.wml file. It is typically in the Web Pages\Web-INF\web.xml path if you are using BluePrints type project in Sun Java Studio Enterprise 8. You can type the entry in web.xml as shown below or you can just double click the web.xml file and use the Sun Java Studio Enterprise 8 editor. The editor has tabs. Click on the General tab if it is not already selected. Expand the Context Parameters section, then click the Add button. Type in MyParam as the Param Name, some value as Param Value, and Description is a description of what the param is or what it is for (whatever you want to put there, it is just for documentation purposes).

Here is web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <context-param>
    <description>MyParam description for documentation</description>
    <param-name>MyParam</param-name>
    <param-value>the value of MyParam</param-value>
  </context-param>
  <servlet>
    <servlet-name>WSServlet_MyDemoWS</servlet-name>
    <servlet-class>philips.MyDemoWSImpl</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>WSServlet_MyDemoWS</servlet-name>
    <url-pattern>/MyDemoWS</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>
            30
        </session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>
            index.jsp
        </welcome-file>
  </welcome-file-list>
</web-app>

Wednesday, September 6, 2006

Making the relationship between OSVD objects

I wasted way too much time trying to figure this out, so I thought I would try to save others from doing the same. OVSD has a webapi available for Java. The api is quite nice. One thing that was not obvious to me at first, but kind of makes sense in the end is how to make relationships between objects. Let's assume you are creating a service call. The service call has a relationship to an assignment which as a relationship to a workgroup. Long templateID = 12345l; // note the lowercase L at the end to designate a LONG. IServicecall sc = ServiceCallHome().openNewServicecall(templateID); The first lesson is that you cannot create the assignment directly. You must call the getAssignment() method on the service call; it creates it for you. IAssignment ia = sc.getAssignment(); The next thing we do is make the relationship to the to-workgroup by calling the the setAssWorkgroup() on the assignment object. ia.setAssWorkgroup(GetServiceDesk1stLineWorkgroup()); The second lesson comes when trying to save changes. In OVSD webapi related objects don't use a save method. Instead they have a transfer() method that does some magic, but is basically the same as a save on a child/related object. ia.transfer(); Finally, call save() on the service call to save all changes to database. sc.save();