Important practices -at least to me!

Data types: this is key, because javascript is not type safe and sometimes the type is not evident

Always specify the type for parameters, return values and properties.
This is usually done writing {xxx} somewhere, where xxx is the type (String, Array, Sm.log.Logger,etc.).

If something can have several types, use this notation: {String/Sm.log.Logger}, with ‘/’ separating several alternative types.

If you want to refer to the special arguments variable, you can define its type as {Arguments}.

Always add @returns {void} to functions that returns nothing. Else, you never know whether there is no type because the function returns nothing, or you forgot to specify it.

Statics:

You must always add the @static tag by hand, even though you are commenting something in statics: else, the static member will appear as an instance member.

You must specify @property explicitly for statics, or they will appear as a global, instead of appearing as part of a class. Bug?

If you are using the config thing in ExtJs based code:

You must explicitly add the @cfg tag, or else the item will be signaled as a property, not a config.

To get getter/setter doc you must add the @accessor explicitly.
Unfortunately, if a config entry is not marked with @cfg, there is no documentation generated for getters/setters.

If you have an item for which you don’t want a setter, create documentation for the setter and make it private.
As explained below, you can create documentation for an item even if you don’t declare it explicitly.

Mark the config as required if needed: you do this by writing something like @cfg (required)

Always add the @readonly tag where appropriate. It is very important because this tells you not to juggle with something.

Always specify the @protected and @private tags. Because in javascript everything is public, your only way to know about this is the documentation.

Always specify the @abstract tag where appropriate. This will help implementors of derived clases quite a lot.

In a @returns tag, do not start comment in one line and continue in another, or it will not be considered part of the return comment. You can start the comment in the second line, placing the type in the first one.

To hide a class to documenation, make it @private.

In javascript you can always add a new property or function as you see fit, but, how do you document something you add in the middle of some function?You can document things that are not declared explicitly like this:

/**
* @cfg {String} name (required)
* A very importand config option that must be specified.
*/

I have to confess that it feels a bit strange to have comments for a property that is not there, and that I feel better if I provide the property itself, if at all possible. But I have to consider what’s worse, a ‘lonely’ comment or a comment with a property initialized to a fake and posibly wrong value.

Doubts

There are some things I’m not sure how to handle:

I’m not sure about how to specify an enumerated type (WARNING, INFO, …).
Maybe the best way is to create a class just for that enumeration, and refer to that class as the type.
I think this is good style, too, so everything should be ok with this approach.

I’m not sure about how to specify optional arguments: for example, in log4js-ext a logger’s logging methods can receive from 1 to n arguments, with very different purpose. I have not decided on a way to document that, beyond providing a link to examples.

I miss an additional visibility qualifier, to designate those methods visible only inside a subsystem (package, library, a group of classes…).
Right now I just mark these as private, and add an extra ‘Package’ comment there (which is not visible in the API documentation, unfortunately).

I’m torn about when to make something private, and when not to document it.
This being javascript, I feel that documenting a private method to the public is almost like telling them that they might use it if they are careful enough, and that to make it really private I should just avoid documenting it.

Huh?

And there are some things that make me wonder if I’m missing something…

The @template tag, does it really make sense to use it? Its meaning, to me, is equivalent to implying that a certain function is overridable, but, is not that the case for functions,
by default?

Checking everything is ok

Once you’ve generated API doc, you’ll want to:

Take a look at warnings -though JSDuck generates a lot.

Look for the ‘unknown type’ string in JSDuck output!

Take a look at the API doc page with all your classes, and look for spurious globals.

In some cases, I’ve got warnings about missing images…that were there.
When checking warnings, make sure that they are for real.

One of these days I will create doc that includes the ExtJs doc itself, so that the user can check whatever he wants *and* I do not get a thousand ‘class not found’ messages when generating the doc.

Juicer is a nice tool to merge and minify several CSS files into just one file. Kudos to the guy that created it!

That said, I’ve been bitten several times by it. Here are some of the troubles I experienced and what I did to get things to work for me.

Juicer: embedding images in CSS

Juicer wants to know the –-document-root when embedding images with --force-image-embed or --embed-images data_uri.

Note that I’m talking about image inclusion in a css using relative URLs, I have not checked this for absolute urls because I don’t care: I never use then.

For things to work, the --document-root must be the directory of the css file you are processing.

Again, a clarification is in order: I always process just one css file each time with Juicer, because I make a point of creating a single css file that @imports all css files I want to consolidate. The net effect is that I’m processing several files, but specifying just one in the command line.

I’m making this clear so that you know I just haven’t tested Juicer behavior with --document-root and multiple css files in the command line. Better safe than sorry!

If you notice I’m being defensive, it is because I am. Juicer is great, but I’ve found its ways are not obvious to me and made many assumptions that did not hold.

Fixing relative CSS urls with ant

I run juicer from my project ant tasks, and that can be problematic because there are ant ways and there are Juicer ways, and they collide from time to time.

As point in case, I have to perform text substitution on the generated css file so that relative urls are right: this is due to the fact that Juicer seems to be intended to be run from the webapp root directory if you want correct relative urls in your css.

*But* I have not managed to run the ant task in the webapp root directory. I tried the dir attribute in the exec task, that seemed to be the cure, but that didn’t do what I needed.

Yes, I can bypass ant and run things from the command line. But then I will have ant’s way, the command line way, and will need to duplicate configuration information for ant and batch files (quick, where is the YUI compressor jar in your system/project?). And I hate breaking the DRY (Don’t Repeat Yourself) rule.

Workaround: replace ../WebContent/ with ../, WebContent being the subdirectory relative to my ant build.xml file. This is way simple in ant:

Juicer does not generate a non-minified css: but you can trick it into it

Juicer provides two nices features for CSS: consolidates several css files into one, and minifies the resulting file.

I would love to have a single production time css that is minified, and another one that is not, to help users of my js libraries with customizing the css. But Juicer does not provide a way to generate a non-minified version.

Workaround: specify a fake inexistent .jar file with the --path INEXISTENT_MINIFIER_JAR_TO_GET_NON_MINIFIED_CSS argument. Juicer will generate the consolidated css and will fail with a Unable to access jarfile error…but the consolidated css file with be there.

Yes, ugly, but very useful. I hope they had added a none option to the --minifyer argument that would have the same effect without the rror message, but they did not

It adds some extra functionality over 0.9 (which was almost a 1.0 candidate), but the main attraction is that it’s been polished to the point of being a product. You know: documentation, multiple file consolidation into a single file, minification, etc.

Here is the new features and improvements list:

Detail view for individual log entries:
The built-in log viewer can show log details in an expanded view.
That’s great for complex logged objects that will be happier formatted as multiple line JSON.

Documentation:
The wiki provides information for users to be proficient with log4js-ext in no time.

Javascript and CSS consolidation and minification:
This makes using log4js-ext easier as now all that’s needed is to add a single .js and a single .css to use all of log4js-ext.
Besides, minification has reduced size to less than a third of the original size.

Refactored formatters to layouts:
This is to follow log4j naming, a good thing because there is a thousand pages about log4j out there that might be useful in one way or other to log4js-ext users.
Should have zero impact, as I doubt there is anybody out there creating custom formatters/layouts as of version 0.9

Besides, the library passes almost thirty unit tests in the latest Firefox, Chrome, Internet Explorer, Safari and even Opera versions.

Finally I decided that extra exception information would made it in the final version, despite being experimental in the beta: the only change with respect to beta 1 is that we have decided to add a where property to all exceptions, making it possible to get the whole stack trace, but *only* in debug mode.

DJN 2.2 provides the following new features:

Automatic conversion to a single element array when calling Java functions that expect an array but receive a single value.

This one helps get around the annoying behaviour ExtJs exhibits in some cases, as it can call a Java function with a single value or an array of values. Java, being type safe, can’t handle that.

The default way dates are serialized by Gson is not very useful or easy to handle, and I decided to provide a custom default implementation that is easier to work with.

Just remember to check this link to make sure you understand how to handle it, and don’t forget to add the required code in the ExtJs side

Enhancements to unexpected server exception handling

Right now, when there is an unexpected exception at the server, DJN provides a message, as per the Ext Direct specification.

While this message provides both the exception type (without the package) and the exception message, I would like to have them apart. This way, it would be possible to handle exceptions without having to dissect the message, making things easier.

Now we are returning the additional serverException with the error information, that provides the following entries:

exception.type: the full exception name of the topmost exception.

exception.message: the message of the topmost exception.

exception.where: the stack trace, only in debug mode.

rootException.type: the full exception name of the root exception.

rootException.message: the message of the root exception.

rootException.where: the stack trace, only in debug mode.

exceptions: an array of elements containing the type , message and where with the stack trace for all exceptions in the exception chain.

As always, more tests have been added to help make DJN code more robust.

I released log4js-ext several days ago, and I’m planning to add remote logging support. I would love to consolidate client and server side logging at the server to help me debug complex browser/server app interactions.

The first logging system I would like to support is Log4j, with slf4j a close second.

Log4js-ext remote logger sends information that I will gather in my RemoteLoggingEvent Java class, as follows:

This works, but there is a *BIG* but. The logged timestamp will correspond to the moment when we called the log method at the server, not the client side timestamp.

Due to the asynchronous nature of web requests, it might well happen that two logs A and B that were created in that order at the client could be received in the server in B, A order. Then the call to logger.log will generate slightly different timestamps, telling lies about the ordering of client-side actions. Really bad for debugging purposes.

It is important to note that I’m implementing remote logging with an eye to help debug during development. During development we tend to run the client an the remote app in the same computer, and then we have the guarantee that the client and server side timestamps are coherent. In that scenario, using the client generated log timestamps will be a real boon, providing correct sequencing information.

That can be so useful for debugging that I decided to byspass the Log4j loggers and log directly against their appenders, which have a nice doAppend method that receives a LoggingEvent accepting not only messages, but a timestamp, an NDC, etc.

The following code will create a LoggingEvent based on the remote information provided to the server in my own RemoteLoggingEvent object:

Now, the problem is Log4j loggers do log following certain rules, and calling its appenders doAppend method would bypass them all.

To follow the rules we have to take into account several things:

We have to log to appenders *only* when the log level/priority (error, warn, info, etc.) is greater than the logger priority.

We need to write to the logger appenders, and then to all parent appenders, and to the parent parent’s appenders, and so on. But *only* if the current logger additivity is set to true, else the only appenders I have to write to are those directly attached to the logger (maybe none).

I wanted to get the same level of support for slf4j, but I just found that there is not an easy way to log timestamps and other additional information. In the end I just wrote the slf4j adapter by calling Logger.info, error, etc., with the corresponding timestamps being server generated.

This will make into log4js-ext in the following weeks, probably using my own DirectJNgine to perform remote communication, so that I can benefit from the built-in support for batching, etc.