LavaBlast Software Blog

Help your franchise business get to the next level.
AddThis Feed Button

jUCMNav Tutorial 5: Dynamic Stubs

clock February 21, 2010 19:38 by author jkealey

 

This is the last jUCMNav tutorial in a series of five. Below are links to other articles in this series.

 

The above video models a simple process for a paintball location. Customers sign a waiver (limitation of liability), pay, and have fun. 

  • Creating dynamic stubs
  • Dynamically selecting which plug-in map will be selected by a scenario

Links



jUCMNav Tutorial 4: Waiting places and timers

clock February 19, 2010 08:24 by author jkealey

 

This is the fourth jUCMNav tutorial in a series of five. Below are links to other articles in this series.

 

The above video models a simple process for a paintball location. Customers sign a waiver (limitation of liability), pay, and have fun. 

  • Introduce waiting places, timers, timeout paths
  • Introduce start point pre-conditions
  • Create a scenario with multiple start points
  • Create a path that triggers a blocked path

Links



jUCMNav Tutorial 3: Loop and scenario enhancements

clock February 18, 2010 08:27 by author jkealey

 

This is the third jUCMNav tutorial in a series of five. Below are links to other articles in this series.

 

The above video models a simple process for a paintball location. Customers sign a waiver (limitation of liability), pay, and have fun. 

  • Including a scenario definition inside another
  • Creating an Integer variable 
  • Writing pseudo-code inside responsibilities
  • Creating a loop

Links



jUCMNav Tutorial 2: Adding forks & joins

clock February 17, 2010 07:50 by author jkealey

 

This is the second jUCMNav tutorial in a series of five. Below are links to other articles in this series.

 

The above video models a simple process for a paintball location. Customers sign a waiver (limitation of liability), pay, and have fun. 

  • Creating an or-fork and or-join to model an exclusive choice
  • Creating an and-fork and and-join to model concurrency
  • Merging a start point and an end point
  • Creating a Boolean variable
  • Initializing variables inside a scenario

Links



jUCMNav Tutorial 1: Creating a simple path

clock February 16, 2010 07:46 by author jkealey

 

This is the first jUCMNav tutorial in a series of five. Below are links to other articles in this series.

 

The above video models a simple process for a paintball location. Customers sign a waiver (limitation of liability), pay, and have fun. 

  • How to create a blank Use Case Map
  • Using the Path Tool to create a path
  • Presents the following path nodes: Start Point, End Point, Empty Point, Responsibility, and Static Stub.
  • Presents the “Refactor into Stub” menu option
  • Presents Components and how to change their fill color.
  • Explains how to bind path nodes to components.
  • Create a simple scenario

Links



Software engineers as salespeople

clock February 15, 2010 10:12 by author jkealey

LavaBlast is a small startup; we don’t currently have dedicated salespeople. I still do most of the selling at this point – I’ve got a background in software engineering, not sales. That may seem crazy until you realize that we don’t sell commercial-off-the-shelf software. If a prospect needs us to build custom software on top of our existing platform, the engineering team is involved in determining the scope (and therefore the cost presented in the quote). Because of the scope of the systems that we’re building, we have the “luxury” to spend more time on each individual quote and learning more about the prospect’s business. Adding a personalized touch in every quote gives us a competitive advantage compared to firms that pump out boilerplate text without analyzing the context.  I strongly feel that, for this type of sale, understanding the customer’s problems is much more important than having them understand your product. Furthermore, understanding/solving problems is definitely something software developers know how to do!

LavaBlast Software builds integrated software solutions for the franchise industry. Although the systems we build are similar because we reuse the building blocks which we’ve developed over the years, we understand that each franchise has different business rules. Understanding these rules before building custom software is of capital importance. This assertion holds regardless of what kind of software you’re building: everyone on the team should have a clear understanding of what needs to be built. Otherwise, you build software that only partially matches your user’s expectations and you need to go back to the drawing board to correct it.

Don’t get us wrong; we’re not fans of the Big Design Up Front (BDUF) approaches such as the waterfall software development model. We follow a more agile development methodology but there is one thing we do with each and every new franchisor client that approaches us: we model their business processes using a visual notation called the Use Case Map notation, a subset of the User Requirements Notation. This helps us understand their business and what they need built. We’ll come back to this notation in a minute.

Communicating business processes

Most business processes are simple (and should be), but a few are not as straightforward. Imagine an online store that sells quilts: the customer goes to the online store, chooses a quilt or two, provides payment, and the warehouse ships them. Simple enough? Add a few requirements to make it complex:

  • a customer can put a particular quilt (a unique hand-made design) on hold and provide payment for it within a week
  • customers can visit the warehouse and make purchases directly – it takes 24 hours for the website to be notified of stock changes
  • the store also receives telephone/fax orders
  • a customer can return a quilt for a full refund with 15 days, in person or by mail.
    These few extra requirements make the whole process a bit more complex.  In real life, there are always dozens of these added constraints. Some are very infrequent whereas others cause problems on a daily basis. Some can be solved by a better process while others can only be mitigated (especially things like delayed notifications) – you need to understand the context to be able to represent the current process and differentiate it from what you see as the ideal process to be implemented. However, as you are the developer and not the domain expert, you need to effectively communicate with the other stakeholders in order to create the best system. In most cases, your best guess is not sufficient.
    We’ve found that the best way to communicate these processes with our customers, who are not in the software world, is by using the User Requirements Notation. The notation provides a way to visually represent processes very quickly. Spending a few minutes designing a Use Case Map is akin to drawing on a whiteboard, with the added benefit of being a persisted artefact that can be “executed” to visualize certain scenarios. Additionally, the Goal-Oriented Requirements Language (the other half of the User Requirements Notation) allows the designer to compare different processes in terms of non-functional requirements such as performance, maintainability, security, etc.

Better than drawing on a whiteboard

Back in 2007, we’ve talked about the Use Case Map notation and jUCMNav in our initial blog post. To celebrate the release of jUCMNav version 4.2.0, we thought it would be nice to produce a series of tutorials that show you how to create your own model using jUCMNav. In case you didn’t know, LavaBlast’s co-founders have contributed massively to jUCMNav in the past five years. We’re responsible for 60% of the code in this open source project which we started during our time as undergraduate software engineering students at the University of Ottawa.

The following is a short 90 second video that gives you an example model and a very quick overview of what can be done with the notation and the tool. Stay tuned to our next blog posts to see us build this example from the ground up. The overview and the tutorial are intended for people with a background in software development. If you wish to introduce the notation to someone outside the development community, I would recommend starting with simple screenshots instead of showing the tool (which, in the end, should only be used by developers).

Conclusion

We hope you found this introduction interesting and that you’ll not only watch our upcoming tutorials but also download jUCMNav (an Eclipse plug-in) and play with it!



BlogEngine.NET 1.6 Breaking Old Links

clock February 12, 2010 10:17 by author EtienneT

UPDATE: BlogEngine 1.6.0.1 will fix this problem

Download BlogEngine 1.6 Binary Patch (drop in your bin folder)

We recently installed an open source error logging project called Elmah on our BlogEngine.NET because we noticed that comments were broken on our blog and some people informed us of other errors.

After installing Elmah, we found out that we had a lot of exceptions like this:

The file '/post/2008/01/Attach-to-Process-with-one-shortcut.aspx' does not exist.

After some investigation, we found out that a lot of the links leading to our blog were broken!  This is bad news because we care about our Google rankings!

I investigated the BlogEngine.NET code a little bit because we considered this a major problem and found out that BlogEngine.NET changed the link pattern from:

http://blog.lavablast.com/post/2008/02/I2c-for-one2c-welcome-our-new-revision-control-overlords!.aspx  (the old pattern)

to

http://blog.lavablast.com/post/2008/02/11/I2c-for-one2c-welcome-our-new-revision-control-overlords!.aspx  (the new pattern)

The day is now required in the link. Otherwise, external links are redirected to an error page.

After investigating the code, I found out that the method RewritePost in the class BlogEngine.Core.Web.HttpModules.UrlRewrite was changed in svn revision 29143 from:

Post post = Post.Posts.Find(delegate(Post p)
{
    if (date != DateTime.MinValue && (p.DateCreated.Year != date.Year || p.DateCreated.Month != date.Month))
    {
        if (p.DateCreated.Day != 1 && p.DateCreated.Day != date.Day)
            return false;
    }
 
    return slug.Equals(Utils.RemoveIllegalCharacters(p.Slug), StringComparison.OrdinalIgnoreCase);
});
 

to

Post post = Post.Posts.Find(delegate(Post p)
{
    if (date != DateTime.MinValue &&
        (p.DateCreated.Year != date.Year || p.DateCreated.Month != date.Month || p.DateCreated.Day != date.Day))
    {
        return false;
    }
    return slug.Equals(Utils.RemoveIllegalCharacters(p.Slug), StringComparison.OrdinalIgnoreCase);
});

 

Days are now mandatory in the URL rewrite to lead to a valid post.  Our old links that were using the yyyy/mm pattern are now returning and error page, and without installing Elmah or double-checking links, I would probably not have noticed. .

The RelativeLink property of the class Post was changed at svn revision 8906 to change the pattern from yyyy/mm to yyyy/mm/dd.  This in itself was not a problem if the old links continued to work.  But with this new change to the UrlRewrite class, the legacy format no longer works.

I changed the code manually to fix our problem, but this might affect other BlogEngine.NET users as well.  If you have a pretty old blog where people link to your old blog posts, then you probably are affected.

After some investigation, this bug was introduced while fixing Bug 9212.

I made a temporary patch for those of you who run BlogEngine.NET 1.6 and are experiencing the same issue.

I changed the code in UrlRewrite to search posts a second time but ignoring days in the date if it didn’t find the post in the first search.  Here is my code:

var predicate = new Func<bool, Predicate<Post>>(includeDays =>
{
    return new Predicate<Post>(
        p =>
        {
            if (date != DateTime.MinValue &&
                (p.DateCreated.Year != date.Year || p.DateCreated.Month != date.Month || (p.DateCreated.Day != date.Day && includeDays)))
                    {
                        return false;
                    }
                    return slug.Equals(Utils.RemoveIllegalCharacters(p.Slug), StringComparison.OrdinalIgnoreCase);
                }
        );
});
 
// Search all post and include days in the search
// A valid link would look like this
// http://blog.com/post/2010/02/10/slug.aspx
Post post = Post.Posts.Find(predicate(true));
 
// We can't find this post, try to find it but ignore days in the path
// http://blog.com/post/2010/02/slug.aspx
// Some older blogengine.net site used this link pattern
// We want to preserve links to those sites.
if (post == null)
    post = Post.Posts.Find(predicate(false));

 

BlogEngine.NET developers are aware of this bug, but in the meantime, you can just drop this new version of BlogEngine.Core.dll in your bin folder to temporary fix the problem if you are using version 1.6 of BlogEngine.NET.

I highly recommend installing Elmah on your BlogEngine.NET to discover errors like these!

Download BlogEngine.NET 1.6 Binary Patch (drop in your bin folder)

kick it on DotNetKicks.com

Shout it



ASP.NET Regenerate .designer.cs

clock February 8, 2010 11:58 by author EtienneT

In this simple post, I want to share a quick tip with Visual Studio.  You probably encountered this problem before: you are designing an ASPX or ASCX form in Visual Studio and then for some reason an element you just added in the ASPX/ASCX is not available in the code behind.

If you are lucky you know exactly what you changed in the page to cause this problem and you fix it.  However, if you’re opening a file that hasn’t been worked on in a long time (maybe someone else did the most recent modification), it becomes difficult to know what exactly cause the .designer.cs automatic generation fail. There are a few common scenarios for this such as invalid HTML, missing or duplicate declarations, or unresolved references. Finding the core issue by hand is difficult because the designer does not let you know what the specific issue is.

Small Tip

To regenerate the .designer.cs file for a ASPX/ASCX, first delete the .designer.cs file, then right click on the ASPX/ASCX and click “Convert to Web Application”.  This will probably give you an error message that will help you find the root of the problem.  I noticed that there’s a difference in the error message you might get here versus when the file is opened in Design mode in Visual Studio.

For example, we had a .ASCX file where the .designer.cs file was not being generated when we modified it.  We could not figure out what the error was until we discovered this tip because Visual Studio did not give us any feedback.  Once I deleted the .designer.cs and ran “Convert to Web Application” on the file, I was prompted with an error message that informed me that we had a <%@ Register /> declaration in our ASCX that was also declared in our web.config file (and this was creating a conflict even if they both pointed to the same location).  Visual Studio could benefit from better error reporting for this particular scenario.

kick it on DotNetKicks.com

Shout it



Simplified Chinese on Epson TM-T88IV Receipt Printer

clock January 15, 2010 14:27 by author jkealey

 

As you might know, our favourite teddy bear franchise is now opening stores in China. Since we’ve developed a fully integrated point of sale for the teddy bear industry, we’re helping them setup the first store over there. One of our challenges has been getting the receipt printer to recognize Simplified Chinese characters. We posted this issue on StackOverflow and contacted Epson support for the first time to try and resolve this issue but we ended up finding the solution ourselves. I’d like to share this solution with you (and some of the hoops we had to go through) as it might prove helpful to other point of sale developers out there.

 Chinese Teddy Bear Birth Certificate

For neophytes, using point of sale hardware is usually straightforward. We use the Microsoft Point of Sale SDK for .NET which is a .NET class library that interfaces with OPOS (OLE for POS). OPOS is the first widely-adopted POS device standard, allowing developers like us to write code that will work with hardware using a unified interface. I will spare you the details of how to get a handle on the printer (open it, claim it, enable it) and will focus on the actual printing portion.

string str = "this is a test";
PosPrinter printer = GetPrinter(); // open it, claim it, enable it. 
printer.PrintNormal(PrinterStation.Receipt, str);
ReleasePrinter(); // unclaim it. 
 

 

Easy enough?  This code worked for us for our stores in Québec (French), Spain (Spanish), and Denmark (Danish) and still worked for us in China when printing Latin characters, but all the Simplified Chinese characters appeared as question marks. 

Question Marks

The first thing to note is that you cannot use any plain old Epson TM-T88IV to print Chinese characters. You need the special multilingual version (which we have: TM-T88IVM). Second, you need to ensure that Epson OPOS sees it configured as the multilingual version, otherwise it won’t know it can print in simplified Chinese. In our tests, we were able to print to the printer via the sample application that comes with the Microsoft POS SDK.

Epson OPOS Configuration ms

Doing a bit of research, we found that we simply had to change the printer’s codepage (from 1252 to 936) for it to recognize the simplified Chinese characters. (Our CharacterSetList=255,437,850,852,858,860,863,865,866,936,998,999,1252 which implied that we could actually use this character set value. If we had not configured Epson OPOS to use the multilingual version, we would get an exception because 936 is not in the list.)

   1:  string str = "重新开始";
   2:  string str = "this is a test";
   3:  PosPrinter printer = GetPrinter(); // open it, claim it, enable it. 
   4:  printer.CharacterSet = 936;
   5:  printer.PrintNormal(PrinterStation.Receipt, str);
   6:  ReleasePrinter(); // unclaim it. 

 

However, this changed absolutely nothing. At this point, we contacted Epson support who could not help us. Our printer self tests showed the printer was capable of printing the characters, but we were still unable to print Chinese characters. Furthermore, the build-publish-test cycle was very slow because we did not have this printer on site (70 days to have it delivered from our regular supplier!) – we had to rely on our partner who was in China to help with the store setup. We tried dozens of things, but could not find the answer. We needed to have the printer on site – we had our partner ship one to us – it arrived three days later. We then decided to run another test:  printing the following website.

Some characters printed image

Interesting… some Chinese characters printed. But not where we were expecting them! I immediately realized it was encoding other (simpler) characters as Chinese characters. In this case, I took the first one above that was generated when the source string was ài. I did a few tests to confirm that àj, àk, àl were all printing different Chinese characters.

Having no knowledge of Chinese, finding the character’s unicode/decimal value in some character map was impossible for me. I had to reverse engineer the problem. 

  • à = 0xE0 in hex = 224 in decimal
  • i = 0x69 in hex = 105 in decimal
  • ài is therefore {224, 105} as confirmed by
byte[] source = Encoding.Unicode.GetBytes(text);

 

I looked up 0xE069 but found it was nothing. I then reloaded one of my old tests to convert this byte array to Code Page 936.

   1:  // simplified chinese
   2:  var encoding = Encoding.GetEncoding(936);
   3:   
   4:  // convert the text into a byte array
   5:  byte[] source = Encoding.Unicode.GetBytes(text);
   6:   
   7:  // convert that byte array to the new codepage. 
   8:  byte[] converted = Encoding.Convert(Encoding.Unicode, encoding, source);

 

Looking in the resulting byte array, I saw {145, 6}. However, converting this byte array back to a string and sending it to the printer did not work. It did not work because I was simply reconverting it back into a Unicode string (C#). I also did not have a PrintNormal method I could call that would accept a byte array. I therefore computed the decimal value of {145, 6} (256 * 145 + 6 = 37126) and looked it up to see it was indeed the character I was looking for ()!  I therefore implemented an ugly byte-by-byte conversion and sent it off to the printer. It worked!

   1:  StringBuilder builder = new StringBuilder();
   2:   
   3:  // simplified chinese
   4:  var encoding = Encoding.GetEncoding(936);
   5:   
   6:  // convert the text into a byte array
   7:  byte[] source = Encoding.Unicode.GetBytes(text);
   8:   
   9:  // convert that byte array to the new codepage. 
  10:  byte[] converted = Encoding.Convert(Encoding.Unicode, encoding, source);
  11:   
  12:  // take multi-byte characters and encode them as separate ascii characters 
  13:  foreach (byte b in converted)
  14:      builder.Append((char)b);
  15:   
  16:  // return the result
  17:  string result = builder.ToString();

Thanks to other Stack Overflow users, I found the following concise implementation.

string result =  Encoding.GetEncoding("ISO-8859-1").GetString(Encoding.GetEncoding(936).GetBytes(text));

Thus, it appears that although the printer supports multilingual characters, one needs to re-encode them in the target codepage and then back into Latin-1 encoding for the Epson TM-T88IV Multilingual to detect it properly. The only things left for us to fix was the string padding (because these characters are twice as wide as latin characters on our printer) and finish off the receipt translation before the grand opening.

Success!

As a side note, if any of our readers have experience with controls (ActiveX or other Windows-specific applications) that allow to print to receipt printer, control the cash drawer, and receive barcodes from a barcode scanner from within a web browser, Flash, or Silverlight, please let us know.



ASP.NET callback not being fired in Internet Explorer

clock January 13, 2010 10:03 by author JKealey

Happy New Year!

Very brief news: We’ve been working hard on our software products for the last few months. We’re building a large line of business application for a service franchise and a few stores opened with our software in Ireland, Scotland, Mexico, and, more recently, China. We’ve also contributed some work to the jUCMNav open source project, which focuses on visually representing software requirements.

Today, we encountered a weird little bug in Internet Explorer and we thought it might be good to describe the workaround which we found thanks to StackOverflow.

We're using a control that uses ASP.NET callbacks (not postbacks) in our page. However, in certain circumstances, the control stops working.

Problem: ASP.NET callbacks are not fired in Internet Explorer

  • The control works fine in FireFox, Google Chrome, etc.
  • The control works fine if we do not use ASP.NET AJAX History. As soon as we call the following code, the callbacks stop working in IE (6, 7, and 8)
ScriptManager.GetCurrent(Page).AddHistoryPoint("h", "12");

 

  • I did some server side debugging to figure out that RaiseCallbackEvent was not fired in IE, but was fired for others.
  • I have debugged using Fiddler and observed that it was not querying the appropriate URL. The server returns an invalid request error.

    Root Cause : IE thinks the anchor (hash tag) is part of the filename.

    Other browsers send the HTTP POST to: test.aspx but Internet Explorer is sending it to: test.aspx%23&&h=12

This is because the URL in the browser's bar is test.aspx#&&h=12, because of our AJAX History Control. For some reason, it URL Encodes the hash tag, but not the rest, and appends it to the aspx filename. Other browsers don’t exhibit this behaviour.

 

Goal: Force IE to drop the AJAX history anchor when calling WebForm_DoCallback via JavaScript?

Technique 1: Add a query string parameter

I found that if the browser was at a certain URL such as test.aspx?test=ing that the control worked fine. This is because appending the AJAX history to this URL makes test.aspx?test=ing%23&&h=12. This implies that we’re sending an invalid test query string of (ing%23&&h=12), but since we’re not using this query string parameter, it does not really matter. However, this does give you an ugly address.

Technique 2: Change the form’s action parameter

Gabriel McAdams lead me in this direction on StackOverflow.

Reading the contents on WebForm_DoCallback, I didn't see anything that set the URL of the server call. This means that it is either getting it from the form action or sending it to the current page. Try setting the form's action attribute.

Indeed, this is the solution we were looking for. ASP.NET has a single server-side FORM element named aspnetForm (auto-generated). If you remove the hash-tag from the form’s action parameter, the control works in all browsers. I assumed that the following code in the right spot would fix the issue, but it did not since ASP.NET’s action element is auto-generated. Any changes made to action don’t seem to do anything. (By default, Action is empty, forcing the browser to decide what URL to use for the current page, which must be the root problem here.)

this.Page.Form.Action = HttpContext.Current.Request.Url.PathAndQuery; 

 

However, if you change it using JavaScript (here I am using jQuery to make my life easier), then your problem is solved.

<div onmousedown="$('#aspnetForm').attr('action', '<%= HttpContext.Current.Request.Url.PathAndQuery %>')">
<!-- my control is in here - I could have executed the above code after every postback, but was sufficient for my needs -->
</div>

 

I’m executing the code when the mouse button is pushed here (sufficient for my needs, and executed before the click event which caused my problems). A cleaner solution would have you output this automatically when necessary. Note that I had tried changing window.location.hash to an empty string before the callback, but this caused the page to scroll, left the hash character in the URL, and broke my AJAX history.

kick it on DotNetKicks.com



Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

Sign in