Tim Holloway

Saloon Keeper
+ Follow
since Jun 25, 2001
Tim likes ...
Android Eclipse IDE Linux
Long-time moderator for the Tomcat and JavaServer Faces forums. Designer and manager for the mousetech.com enterprise server farm, which runs VMs, a private cloud and a whole raft of Docker containers.

These days, doing a lot of IoT stuff with Arduinos and Raspberry Pi's.
Jacksonville, Florida USA
Cows and Likes
Total received
In last 30 days
Total given
Total received
Received in last 30 days
Total given
Given in last 30 days
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Tim Holloway

Yeah. You CAN use glob-type wildcards on a from-view ID though. Things like "/admin/*" or the all-inclusive "*". My apps tend to organize along those lines anyway, since that makes it easier to define URL patterns for security rules as well.

But "logic" and other regular-expression view-id patterns are not supported. Your IDE probably won't complain, and the app won't either (JSF tends to ignore a lot of illegal stuff instead of reporting it).

20 hours ago
Haven't checked JBoss/Wildfly recently, but in its early days, JBoss was practically nothing but MBeans.

Also, you may have the option to select which connection pool implementation(s) your JBoss server uses with webapps. It's definitely a plug-in option in Tomcat, anyway. And Tomcat itself used to be part of JBoss.
1 day ago
That's not actually a "logical" (boolean) expression. It's a multiple-option pattern match. And I doubt that would work.

However, if my memory is accurate, you can have multiple <from-view-id> elements for a single navigation rule, which allows you the same result.
1 day ago
Sorry to be a party-pooper, but the database issue I keep referring to was new code. The database was IBM's DB2 and I was using Hibernate JPA2 as the access mechanism. It's entirely possible - since multiple major versions of both have been released since then - that the constraints I was operating under at the time no longer apply, but one has to make due with what's available. It obviously wasn't a choice, since I had to go to the trouble to test for the pre-existence of my internally generated sequence and repeat until I found a viable slot, and normally an auto-generated sequence number would be less coding and much less overhead for both client and server.

A database doesn't "maintain" insertion order (well, outside primitive exceptions like MS-Access and FoxPro), but there's a reason why sequences are so popular that they frequently have built-in DBMS support these days. Accounting systems like them for generating invoice and order numbers, for example. Retrieving a list of unpaid invoices in sequence number order, for example, means that you can have the fastest access to the list in a manner that is most convenient to the accounting process - since First-In/First-Out is one of the most popular ways to manage things. Ordering by date is inferior because multiple invoices or orders are very frequently created on the same date, and timestamps in databases are particularly warty. Plus if you expect people to be able to sort through invoices based on microsecond-level timestamps, you haven't seen how few brain cells most people are willing to devote to such processes. A nice simple number with, say 5 digits, is a lot easier to dig through when you have a stack of papers in hand. Not only accounting systems do this. My nightly backup system numbers each backup job that runs, for example.

Regarding slicing, it's been my experience that database deletions are more the exception than the rule. For various reasons - including audit purposes - most of the production systems I've worked with did not allow deletions. Often the only part of a system that did allow deletions was a staging area used, for example, to assemble transactions before they were either committed or rolled back (either of which caused the staging data to be deleted). So holes in the sequence are not an issue in general. On the other hand, if you have a sequence and use it for slicing, you can potentially free up entire disk drives by archiving to tape periodically. This is something more often seen in major IT shops, but then, they're the ones who employ more skilled DBA's and generally are using more sophisticated techniques for everything.

As I've said, GUIDs have a very definite set of uses. But they're not my identifier of choice because they have no semantic meaning. Their sole property is their uniqueness. If there are other properties in a table (including compound properties), that can be used to enforce uniqueness, then I prefer those, since such properties have additional and practical reasons for existence. As I said, storage space isn't as critical an issue as it used to be, but why waste it gratuitously? GUIDs take up a lot of space, relative to simple numeric and short-sequence character fields. And may Ganesha help you if you have read them out to someone over the phone. I have enough problems with things like MAC addresses. A touch of dyslexia isn't helping any, either.

And finally:

Stephan van Hulst wrote:Can you explain what you mean by that POJOs are not supposed to have infrastructure-related property mandates? Does that mean that I can't simply pass a logger(-factory) in a constructor?

Yes, I can. POJO means "Plain Old Java Object". Once you cannot arbitrarily substitute one bean for another, you've locked yourself in. You now have coupling issues and code reuse limitations. That doesn't mean that you cannot inject complex objects into a POJO, just that it means that you must not require a class of POJO objects to accept a specific property or properties, since then it's by definition no longer a POJO.

Also, it is an essential requirement in both JavaServer Faces (JSF) and in Java Persistence Architecture (JPA) that every bean must have a no-element constructor. For JPA, there is no way to define arguments for the constructor that JPA will use to auto-instantiate the bean. For JPA, JPA needs a no-element constructor for when it internally assembles entity objects. Because in many cases, JPA will not be populating those objects from application logic, it will be populating them from database value retrieval and that means that it simply won't have any knowledge of things like which logger you are using. Or what e-mailer, or any of a number of other such services that can be found via a static service locator without direct propagation from the calling framework.

Finally, I should mention that things like loggers, JDBC Connections, etc. are not serializable. This is critical in JSF and JPA. In fact, Tomcat will flatly refuse to accept a session-scope object that doesn't at least claim to be serializable*. For one thing, when a serializable object is serialized out and back in again, any non-serializable properties do not get initialized, which can break things. A logger retrieved from a static method as part of the internal initializer code doesn't have this problem.

*Yes, I realize that forcing a POJO to to implement java.io.Serializable sounds like a violation of the definition. But it gets a pass since Serializable is a class characteristic, not a promise to implement any sort of logic or specific class or method properties. And because it's a core JVM feature and therefore guaranteed to always be there.
1 day ago
OK, let me first bring up a reminder that the actual topic of this thread has to do with static variable and thread safety. We have diverged from this because you assert that is no place in Java (despite the language designers' support) for static variables.

I offered some examples of real-world use cases. They were not meant to be exhaustive and I'm sure that plenty of people out there could offer more if they wished.

Now, first of all, on the topic of databases. In the Real World, we are not always given the choice of what database we may use. We have to work within its limitations. Some cases I've dealt with did not allow me to employ database-generated keys. They were paying me money to do a job, not to switch databases, so I did so and the simplest solution was a static variable.

On GUIDs and their virtues and vices. Why not use a separate sequence field from a GUID key? Because for one thing, you just kicked the can down the road. We still need an unique sequence number but now we also have a GUID which is totally useless except as a designator of uniqueness, which is something that you can do on any database index field by meta-designating it as unique. I come from a background where online storage was so expensive that we begrudged every byte and back then, something as long and ugly as as a GUID would have made management very unhappy. Storage is cheap these days, but it still adds up when you're talking billions of records. And, as I said earlier, there's no meaningful way to slice databases for optimal archiving and optimization when the key is basically random, so the operations staff doesn't care for that either.

On the other hand, there are also systems where there is no good central authority to hand out keys. I had particular grief with QuickBooks and transactions coming from satellite offices, for example, trying to get all the servers (including in-house apps) in sync without ID collisions (and Intuit assigned IDs and defined the APIs to sync, not me, so I couldn't control that). GUIDs would have been a big help here. Closer to home, I have a "to-do" app that allows me to enter and read notes from multiple sources - tablet, mobile phone, desktop. In order to ensure that each of the preceding gets exactly one and only one copy of each note without demanding continuous connection, a GUID makes sure that every note is universally unique.

JUava, incidentally has a core class to generate GUIDs. So somebody thought that applications generating GUIDs wasn't such a bad idea. Besides, if the app doesn't do it, where do you get them? Especially since if a DBMS (assuming you're connected to one) has trouble generating single sequences, something as messy as a GUID is probably not going to be available either.

I'm not sure about your point on singletons, but I do know that "lazy programming" is considered a virtue by some of the major names in the business, including Larry Wall, who designated it as one of the Three Virtues of a Great Programmer. Not sloppy programming - which is all too common, but programming that is simple, neat, and wherever possible steals from good, simple, neat - and well-debugged - sources. Coupling is bad in software. It reduces portability and it makes both changes and testing harder because of the ripple effects.

Finally, on injection. To inject something you either have to have an external agency that introspects the class to look for injectable stuff or you have to publish an explicit contract saying that you'll accept injection - a superclass, interface or annotation. The first method is high overhead. The second is mostly incompatible with POJOs, since POJOS aren't supposed to (by definition) have infrastructure-related property mandates. Yes, you can annotate a POJO for injection, but that's no good unless there's an injection framework willing to accept the annotation - CDI, Spring, or the like. Not every application runs under an IoC framework, and the loggers do not limit themselves to IoC environments. Hence the use of static locators, which are guaranteed to function in even the most basic Java run environments. And here again, although I use loggers as an example, they're not the sole example. JSF was designed to work with POJOs specifically because Struts, its predecessor, was so awful to work with thanks to all the superclass and interface mandates. Some of the same people who developed Struts also developed JSF and they were determined not to repeat the same mistakes.

Bottom line, though, is that I'm not exactly alone here. I'm quoting established and extremely popular precedents. I've no objection if you decide to write a book on Application Programming Without Static Variables, or even design and implement a programming language that excludes static variables. You could be on to something. Djikstra, after all, got a lot of static for insisting that the "go to" statement was bad. But the challenge here to provide something better. Something simpler, something cleaner, more reliable and more bug-proof. If you can do that, you, too can gain fame and possible fortune as a shaper of modern technology.

On the other hand, too many times I've had poor junior programmers post after solutions in my forums because their management arbitrarily forbade some industry-standard practice, so I tend to be a bit reactive about adding limitations unless they're probably beneficial.
2 days ago
Consider yourself lucky.

I one took over a web app that would take 20 minutes to start up. The original author was fool enough to attempt to load half the database into RAM in the init method of one of his servlets. I modified it to use just-in-time fetching and the startup time dropped to 30 seconds.

One of the things that made Tomcat (and jetty) so popular was that the full-stack J2EE servers like WebSphere did take an excruciatingly long time to start. But Tomcat itself only takes maybe 20 seconds. All the other time is in the starting of the webapps. Ideally a single webapp would take no more than 60 seconds to launch, but that depends on how the app was designed, not on Tomcat.
2 days ago
I think that this is actually a grammatical problem. The word "Exception" in the message means "An exception was thrown", not that specifically a "java.lang.Exception" was thrown. Both checked and unchecked Exceptions and Throwable are all exceptions in the abstract sense of the word.

And in the fundamental mechanisms which handle them.
3 days ago
Try the "git status" command. It should either indicate that the file hasn't been added to git (in which case, the "git add" command should cure that), or show it as an uncommitted file.

If neither of the above, either something's obscuring the file (I had one project I moved and there was another git repository within the set of files I moved), or it probably already committed.
3 days ago
SOAP (you poor creature!) is XML and technically XML isn't supposed to have newlines in it at all. If you put newlines between body tags, then the newline is considered as part of the body text itself (payload). If you put newlines between elements, that's technically part of the parent element body; bodies can be fractured into more than one part if there's a sub-element(s) present. So while a "pretty" SOAP packet may have newlines, a "pure" SOAP packet would not (unless you really want newlines as part of your text.

In the Real World, a lot of that means that you just ignore stuff you don't want to see, newlines included.

Having said that, if it's essential that you have control over breaks in your SOAP, then I suppose the best thing to do would be to code it into your SOAP generation process. If you cannot do that, then changing the line.separator internally is probably the best bet.
3 days ago
If you're using JEE standard container security, you cannot select a login page as a navigation target. That is because login is handled automatically by the webapp server and it doesn't use any application logic at all (which is one reason it's more secure). The only way to get a login page to work properly when using JEE (or J2EE) container security is to navigate to a secured page (using the "redirect" option if you're using JSF). The server will automatically check to see if the user is logged in, present the login sequence if not, then proceed to the secured page once the user has logged in. The application never sees the actual login process. The login page itself cannot be manually requested via URL, since accessing it that way won't have caused the server to enter the login process. You'll see a form, and you can submit it, but the server won't check it for proper userid and password.

If, on the other hand, you're trying to write your own security system, well, don't. Unless you're a full-time security expert chances are very high that you won't know all the necessary processes that need to be attended to to stay secure. Nor will your application be able to use the standard security functions. Do-it-Yourself security has a very poor security record, from what I and others here have seen. Like about 95% of them have at least one loophole, which is usually something a non-technical person can bypass in 15 minutes or less. And that includes the systems done by the local "expert" or "genius" in the shop.
3 days ago
One other thing.

To the best of my knowledge, Java does not normally "load a JAR file into memory". The Java classloaders use a URL locate the resources related to a class when that class is required. Many JARs have lots of classes in them that are not used in all applications. So loading the entire JAR into memory would likely be a big waste of one of the scarcest of resources (RAM).

So I think it likely that when the class resource URL is used by the classloader, if that resource references a member of a JAR (and all public classes are discrete "files" within a JAR), then the classloader is more likely to open ONLY that resource and load from it.

Meaning that a given JAR might have hundreds of "open" events, but not for the same class.

The thing that's actually more dangerous is if a JAR (or more accurately a class) appears more than once in a classpath. That's because in some cases, different classloaders/classpaths will be involved, causing an mixup of what parts of the class are being referenced where. This can cause issues in the case of static variables within the class (since there'd be more than one copy of the class itseld) and with colliding versions of a class.
3 days ago
Java Virtual Machines aren't supposed to do things differently. That's why they're implemented as Virtual Machines.
3 days ago
Java webapp servers maintain multiple classpaths. At least one classpath for the server itself plus one classpath for each web application. Each web application's classpath is hermetically isolated from every other application's classpath except for the parts that are inherited from the common server classpath. A special classloader adds the contents of the webapp's WEB-INF/classes and each of the WEB-INF/lib jar files to that webapp's classpath.

Because of this, yes, a given JAR may be "loaded" multiple times, but it will be loaded only once per classloader (absent any classloader mods that the webapp itself might invent).

The server-provided segment of the classpath is shared, which is why it's not recommended to plop just any classes into, say, the TOMCAT_HOME/lib directory. Because those classes (stuff like the JDBC drivers and J2EE API jars) will be shared, and not only that, will be shared by multiple threads, with all the perils for class state variables that that implies.
3 days ago
The official floating-point spec for Java is IEEE 754-2008. The JVM is a virtual machine, and processors such as IBM's 32-bit mainframes that do not incorporate IEEE 754 in hardware are obliged to do it in the hard way via custom software or microcode.

If the overflow behavior varied depending on the hardware, that would violate Java's "write-once/run-anywhere" reproduciblity standard. Only if you override for a "native" floating-point architecture would it be permissible to allow for variances.
3 days ago
I'm not an expert on Spring Security, but my understanding is that at least in some cases, it works alongside the J2EE standard (container-managed) security system. CM security wasn't really designed for a "login" button, because it automatically forces you to login whenever you submit a secured URL, as defined in the web.xml security URL pattern set. This avoids the very common security hack where people simply bypass the login and go straight to (allegedly) secured pages.

Somewhere about JEE 6, however, the Enterprise Java spec introduced an explicit login command that could force login from application program logic. I haven't had much luck with this, although then again, I never had need to try.

One thing that you do have to remember, however, when using container-managed security in JSF is that the JSF URL isn't a direct URL, but rather more of a "handle" on the JSF session. So it often doesn't reflect the actual page requested. The CM security system, however, looks at the URL and only at the URL to determine security requirements, so to force the URL and requested resource into sync, you need to navigate using the "redirect" option. It's a little extra overhead, but that way container security is enforced properly.

Please note, however that when you do form-based logins using container-managed security, the operative word is Container managed. The container (web server) is NOT routing the login through application logic, and in particular, not through the FacesServlet. Your login form must be either straight HTML or at least straight JSP (NOT JSF). Because while you can format what goes out, what comes back goes directly to the webapp server, and not to program code, and all the webapp server will do is pluck the userid and password from the security form and feed them to the internal security Realm processor. That's part of what makes container security more secure than Do-It-Yourself code - if the login isn't done with user code, then it cannot exploit user code.

Additionally, please note that the client cannot force login by using the login form page path as a URL. The page will display, but since the container didn't request it, the mechanisms for processing the login form will not be returned to the login processor in the container. The container itself is the sole determinant of when to invoke the login form and the actual process of login is completely transparent to the application. No events are fired or methods invoked on login. The only actual change is that magically the remote user ID and userPrincipal fields in the HttpRequest are no longer going to be blank.
4 days ago