Wednesday, April 15, 2009
Technical Lead
About the Job
The Technical Lead functions as the technical project leader for applications development projects. The Technical Lead leads and co-ordinates all development activities related to system design, construction, implementation and/or enhancement and serves as the primary contact between the Program Area users and IT staff for the design, development, testing and implementation phases of the Systems Development Life Cycle. The Technical Lead will work with the Applications Development Manager to ensure timely delivery of results and services that satisfy business and user requirements within the context of the IT&S architectural framework and policies/processes for Systems Development Methodology and Quality Assurance.
Duties and Responsibilities -
1. Acts as Technical Leader on selected projects and leads/coordinates all applications development activities. Activities include, but are not limited to, participation in requirements identification and feasibility analysis, generation of technical solutions and design, coding, testing, quality assurance, implementation and all supporting project artefacts and documentation.
2. Maintains ongoing contact with project team/ program area to ensure that users' needs are being addressed through timely delivery of results in the form of services and/or information systems. Maintains open lines of communication between user/client groups and project teams.
3. Interacts closely with other IT&S resources to ensure successful system development according to the detailed specifications and architectural frameworks.
4. Works with assigned IT&S project team/program area and project manager and provides leadership to other IT&S staff in the development of system designs and automated information flows/processes based on user requirements and specifications for system implementations, enhancements and/or customisations. As required, develops and oversees quality assurance strategies and protocols for user acceptance and implementation of new and enhanced systems/applications.
5. May act as Project Manager. In this role, leads a multi-disciplinary project team working within the project management guidelines. This role may include, but is not limited to project status and change request reporting, maintenance of project plans, monitoring project budget, issue identification and resolution management, risk mitigation and resource management.
6. Provides day to day supervision to the Applications development team assigned to the projects and acts as mentor and coach to supervised staff.
7. Ensures other IT&S resources receive the requisite information to perform their assigned project related tasks; coordinates and ensures timely delivery of these assigned task deliverables.
8. Prepares and delivers PMP evaluation and review documents for supervised staff, and provides input on the level of performance for assigned Applications development team members to the Applications Development Manager.
9. Participates in the recruitment and evaluation of Applications staff, as well as the selection of external contractors as required.
10. Develops and demonstrates a thorough understanding of IT&S systems development standards and methodologies, tools and techniques, and its underlying quality assurance principles and processes.
11. Demonstrates and maintains a thorough understanding and knowledge of policies that form the basis to existing business processes. Contributes to policy evolution and refinement and business and process re-engineering.
12. As required, works with program areas and IT&S Operations to plan, coordinate, develop and/or deliver training to users.
Knowledge and Experience -
University degree or equivalent experience/education in Computer Science, Mathematics or related discipline.
Minimum of six to eight years of IT experience in the generation and implementation of a technical solution for complex, multi-user information systems, four or more years of which are in a senior technical role with significant client/user interaction.
Web-based development expertise in UNIX-AIX, Oracle RDBMS,9i and up, Oracle developer, Oracle Suite of tools, Oracle iAS/Apache, Oracle Warehouse Builder, .NET Technologies.
Significant work experience with JSP, JAVA, J2EE, J2EE Patterns, HTML, JAVASCRIPT, PL/SQL; C#, UML, Use Case Tools; knowledge of and exposure to Web Services highly desirable.
Development expertise in XML, Struts Presentation Layer Framework, ETL Processes, iBatis, ETL Tools and Microstrategy.
Demonstrated working knowledge and experience in internet/networking technologies, including security and encryption on the internet and preventative management techniques for internet "hacker" attacks.
Practical knowledge of and demonstrated experience in cross-browser development techniques, browser degradation strategies and optimization techniques.
Extensive experience in a senior technical role with the ability to supervise and mentor staff.
Demonstrated experience with formal systems development life cycle methodologies, and training in data modelling and use case tools.
Excellent interpersonal, facilitation, presentation and communication skills, with the ability to communicate complex issues and processes in simple user terminology.
Project management experience a definite asset. Knowledge of Microsoft Office suite of products, including MS Project, Enterprise Architect and Visio.
Familiarity with health informatics is desirable.
Fluency in both official languages is an asset.
Tuesday, April 14, 2009
Usage of IBM HTTP Server
In clustered Application Server environments, IBM HTTP Servers spray Web requests to the cluster members for balancing the work load among relevant application servers. The strategy for load balancing and the necessary parameters can be specified in the plugin-cfg.xml file. The default and the most commonly used strategy for workload balancing is ‘Weighted Round Robin’. For details refer to the IBM Redbooks technote, Workload Management Policies.
Most commercial Web applications use HTTP sessions for holding some kind of state information while using the stateless HTTP protocol. The IBM HTTP Server attempts to ensure that all the Web requests associated with a HTTP session are directed to the application server who is the primary owner of the session. These requests are called session-ed requests, session-affinity-requests, and so on. In this document the term ‘sticky requests’ or ‘sticky routing’ will be used to refer to Web requests associated with HTTP sessions and their routing to a cluster member.
For more information, refer to:
http://www-01.ibm.com/support/docview.wss?rs=180&uid=swg21219567
http://www-01.ibm.com/support/docview.wss?rs=180&uid=swg21219808
2. Support SSL/HTTPS connection and user authentication with LDAP.
Monday, October 27, 2008
Sr Solutions Architect Position from RBC
Position Title: Sr Solutions Architect
Position Type: Full-Time
Position Category: Information Technology
Relocation: No
Job Description:
The Solution Architecture group of RBC's Enterprise Architecture Services is responsible for end to end solution architecture of all key initiatives across RBC's Global Technology Operations. We currently have several exciting opportunities for Senior Solution Architects to lead development of the end to end technical solution architecture for high complexity and high risk IT initiatives (i.e. $10 million - $25 million) that meet sponsor/stakeholder needs.
Requirements:
Our minimum requirements to ensure your success in this role are:
- Experienced with all aspects of architecture including application, data, security and infrastructure
- Total IT experience of at least 15 years out of which 5 years doing solution architectures on large projects. Proven experience at leading architecture of a large program from initiation to implementation
- Strong leadership skills (not a follower), comfortable managing large cross functional technical teams and ability to define, influence and impact the technical direction
- Ability to quickly evaluate options, make decisions and execute within an intense high-tech environment
- Solid experiences with a variety of technologies/approaches including J2EE, .NET, mainframe platform, packaged applications, multi-platforms applications, human workflow, EAI, SOA
- Experienced with program/projects involving complex integration of disparate types of technologies/platforms
- Solid understanding of RUP, UML and UML tools
- Knowledge of Enterprise Architecture frameworks: TOGAF, Zachman etc
- Experience with different architecture/design techniques (e.g. OO, Top-down, structured analysis, component-based design) and tools (e.g. RSM, RSA)
Additionally, and in anticipation of a high volume of applicants, consideration will be given to candidates who also possess the following:
- Project management experience
- Working knowledge of financial applications as well as host based systems
If you are a confident leader with outstanding conflict and negotiation skills, then we would be very interested in speaking with you. If you are looking for a highly rewarding career in the Solution Architecture group of RBC's Enterprise Architecture Services, please go directly to our careers site to apply.
Key Accountabilities:
Reporting to the Director of Solution Architecture, the Senior Solution Architect will be primarily responsible to:
- Define end to end technical solutions that take into account the enterprise architecture strategies, current state environment and constraints; analyze the viability of the solution to meet program timeline, budget and quality
- Develop and present solution alternatives along with recommendations to executives and senior management; presents program solution architecture at the Architecture review board
- Work with Data Architecture, Security Architecture and Infrastructure SME's to ensure that all aspects of the solution architecture are defined and elaborated
- Develop the architecture artifacts (Solution Architecture Document, Architecture Decisions) as defined by the PMF/SDLC and review with Enterprise Architecture, Lead Architects, Business Architects and the key program stakeholders
This unique career opportunity further allows you to utilize your full complement of skills and experience by playing the role of the lead technical authority on the program and being responsible for planning all activities leading to the development of the overall solution architecture. You will provide critical thinking and technical leadership to the program right from the idea creation stage.
Overall, your main accountabilities will be broken down as follows:
- End to end solutions architecture (60%)
- Technical leadership and mentoring (20%)
- Training and professional development (10%)
Friday, July 18, 2008
Cannot open the web.xml in Deployment Descriptor editor
When using IBM® Rational® Application Developer v7 to develop web projects, sometimes the Web Deployment Descriptor file (that is, the web.xml) cannot be opened in the Deployment Descriptor editor.
Symptom
The following Redirecting Editor error occurs when you try to open the web.xml file by double-clicking on it:
IWAE0028E The selected input is not valid for this type of editor. Redirecting to the XML editor.
This issue will also cause your web application to be unable to deploy onto the integrated WebSphere® Application Server.
Cause
The deploy path for the project in question is not set up to point to the default WebContent folder.
Resolving the problem
To fix this, switch to the Resource perspective, and open the web project's .settings/org.eclipse.wst.commmon.component file and change:
to:
This is what the project setting file should look like by default (that is, when creating a new Dynamic Web Project).
http://www-1.ibm.com/support/docview.wss?rs=2042&context=SSRTLW&context=SSJM4G&context=SSSTY3&context=SSCGQ7C&q1=IWAE0028E&uid=swg21272575&loc=en_US&cs=u%20tf-8&lang=en
Tuesday, June 24, 2008
Understanding Strong & Weak References and Caches
Some time ago I was interviewing candidates for a Senior Java Engineer position. Among the many questions I asked was "What can you tell me about weak references?" I wasn't expecting a detailed technical treatise on the subject. I would probably have been satisfied with "Umm... don't they have something to do with garbage collection?" I was instead surprised to find that out of twenty-odd engineers, all of whom had at least five years of Java experience and good qualifications, only two of them even knew that weak references existed, and only one of those two had actual useful knowledge about them. I even explained a bit about them, to see if I got an "Oh yeah" from anybody -- nope. I'm not sure why this knowledge is (evidently) uncommon, as weak references are a massively useful feature which have been around since Java 1.2 was released, over seven years ago.
Now, I'm not suggesting you need to be a weak reference expert to qualify as a decent Java engineer. But I humbly submit that you should at least know what they are -- otherwise how will you know when you should be using them? Since they seem to be a little-known feature, here is a brief overview of what weak references are, how to use them, and when to use them.
Strong references
First I need to start with a refresher on strong references. A strong reference is an ordinary Java reference, the kind you use every day. For example, the code:
StringBuffer buffer = new StringBuffer();
creates a new StringBuffer() and stores a strong reference to it in the variable buffer. Yes, yes, this is kiddie stuff, but bear with me. The important part about strong references -- the part that makes them "strong" -- is how they interact with the garbage collector. Specifically, if an object is reachable via a chain of strong references (strongly reachable), it is not eligible for garbage collection. As you don't want the garbage collector destroying objects you're working on, this is normally exactly what you want.
When strong references are too strong
It's not uncommon for an application to use classes that it can't reasonably extend. The class might simply be marked final, or it could be something more complicated, such as an interface returned by a factory method backed by an unknown (and possibly even unknowable) number of concrete implementations. Suppose you have to use a class Widget and, for whatever reason, it isn't possible or practical to extend Widget to add new functionality.
What happens when you need to keep track of extra information about the object? In this case, suppose we find ourselves needing to keep track of each Widget's serial number, but the Widget class doesn't actually have a serial number property -- and because Widget isn't extensible, we can't add one. No problem at all, that's what HashMaps are for:
serialNumberMap.put(widget, widgetSerialNumber);
This might look okay on the surface, but the strong reference to widget will almost certainly cause problems. We have to know (with 100% certainty) when a particular Widget's serial number is no longer needed, so we can remove its entry from the map. Otherwise we're going to have a memory leak (if we don't remove Widgets when we should) or we're going to inexplicably find ourselves missing serial numbers (if we remove Widgets that we're still using). If these problems sound familiar, they should: they are exactly the problems that users of non-garbage-collected languages face when trying to manage memory, and we're not supposed to have to worry about this in a more civilized language like Java.
Another common problem with strong references is caching, particular with very large structures like images. Suppose you have an application which has to work with user-supplied images, like the web site design tool I work on. Naturally you want to cache these images, because loading them from disk is very expensive and you want to avoid the possibility of having two copies of the (potentially gigantic) image in memory at once.
Because an image cache is supposed to prevent us from reloading images when we don't absolutely need to, you will quickly realize that the cache should always contain a reference to any image which is already in memory. With ordinary strong references, though, that reference itself will force the image to remain in memory, which requires you (just as above) to somehow determine when the image is no longer needed in memory and remove it from the cache, so that it becomes eligible for garbage collection. Once again you are forced to duplicate the behavior of the garbage collector and manually determine whether or not an object should be in memory.
Weak references
A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself. You create a weak reference like this:
WeakReference weakWidget = new WeakReference(widget);
and then elsewhere in the code you can use weakWidget.get() to get the actual Widget object. Of course the weak reference isn't strong enough to prevent garbage collection, so you may find (if there are no strong references to the widget) that weakWidget.get() suddenly starts returning null.
To solve the "widget serial number" problem above, the easiest thing to do is use the built-in WeakHashMap class. WeakHashMap works exactly like HashMap, except that the keys (not the values!) are referred to using weak references. If a WeakHashMap key becomes garbage, its entry is removed automatically. This avoids the pitfalls I described and requires no changes other than the switch from HashMap to a WeakHashMap. If you're following the standard convention of referring to your maps via the Map interface, no other code needs to even be aware of the change.
Reference queues
Once a WeakReference starts returning null, the object it pointed to has become garbage and the WeakReference object is pretty much useless. This generally means that some sort of cleanup is required; WeakHashMap, for example, has to remove such defunct entries to avoid holding onto an ever-increasing number of dead WeakReferences.
The ReferenceQueue class makes it easy to keep track of dead references. If you pass a ReferenceQueue into a weak reference's constructor, the reference object will be automatically inserted into the reference queue when the object to which it pointed becomes garbage. You can then, at some regular interval, process the ReferenceQueue and perform whatever cleanup is needed for dead references.
Different degrees of weakness
Up to this point I've just been referring to "weak references", but there are actually four different degrees of reference strength: strong, soft, weak, and phantom, in order from strongest to weakest. We've already discussed strong and weak references, so let's take a look at the other two.
Soft references
A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. An object which is only weakly reachable (the strongest references to it are WeakReferences) will be discarded at the next garbage collection cycle, but an object which is softly reachable will generally stick around for a while.
SoftReferences aren't required to behave any differently than WeakReferences, but in practice softly reachable objects are generally retained as long as memory is in plentiful supply. This makes them an excellent foundation for a cache, such as the image cache described above, since you can let the garbage collector worry about both how reachable the objects are (a strongly reachable object will never be removed from the cache) and how badly it needs the memory they are consuming.
Phantom references
A phantom reference is quite different than either SoftReference or WeakReference. Its grip on its object is so tenuous that you can't even retrieve the object -- its get() method always returns null. The only use for such a reference is keeping track of when it gets enqueued into a ReferenceQueue, as at that point you know the object to which it pointed is dead. How is that different from WeakReference, though?
The difference is in exactly when the enqueuing happens. WeakReferences are enqueued as soon as the object to which they point becomes weakly reachable. This is before finalization or garbage collection has actually happened; in theory the object could even be "resurrected" by an unorthodox finalize() method, but the WeakReference would remain dead. PhantomReferences are enqueued only when the object is physically removed from memory, and the get() method always returns null specifically to prevent you from being able to "resurrect" an almost-dead object.
What good are PhantomReferences? I'm only aware of two serious cases for them: first, they allow you to determine exactly when an object was removed from memory. They are in fact the only way to determine that. This isn't generally that useful, but might come in handy in certain very specific circumstances like manipulating large images: if you know for sure that an image should be garbage collected, you can wait until it actually is before attempting to load the next image, and therefore make the dreaded OutOfMemoryError less likely.
Second, PhantomReferences avoid a fundamental problem with finalization: finalize() methods can "resurrect" objects by creating new strong references to them. So what, you say? Well, the problem is that an object which overrides finalize() must now be determined to be garbage in at least two separate garbage collection cycles in order to be collected. When the first cycle determines that it is garbage, it becomes eligible for finalization. Because of the (slim, but unfortunately real) possibility that the object was "resurrected" during finalization, the garbage collector has to run again before the object can actually be removed. And because finalization might not have happened in a timely fashion, an arbitrary number of garbage collection cycles might have happened while the object was waiting for finalization. This can mean serious delays in actually cleaning up garbage objects, and is why you can get OutOfMemoryErrors even when most of the heap is garbage.
With PhantomReference, this situation is impossible -- when a PhantomReference is enqueued, there is absolutely no way to get a pointer to the now-dead object (which is good, because it isn't in memory any longer). Because PhantomReference cannot be used to resurrect an object, the object can be instantly cleaned up during the first garbage collection cycle in which it is found to be phantomly reachable. You can then dispose whatever resources you need to at your convenience.
Arguably, the finalize() method should never have been provided in the first place. PhantomReferences are definitely safer and more efficient to use, and eliminating finalize() would have made parts of the VM considerably simpler. But, they're also more work to implement, so I confess to still using finalize() most of the time. The good news is that at least you have a choice.
Conclusion
I'm sure some of you are grumbling by now, as I'm talking about an API which is nearly a decade old and haven't said anything which hasn't been said before. While that's certainly true, in my experience many Java programmers really don't know very much (if anything) about weak references, and I felt that a refresher course was needed. Hopefully you at least learned a little something from this review.
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
*
In reply to the implicit question from richunger: The Sun JRE does treat SoftReferences differently from WeakReferences. We attempt to hold on to object referenced by a SoftReference if there isn't pressure on the available memory. One detail: the policy for the "-client" and "-server" JRE's are different: the -client JRE tries to keep your footprint small by preferring to clear SoftReferences rather than expand the heap, whereas the -server JRE tries to keep your performance high by preferring to expand the heap (if possible) rather than clear SoftReferences. One size does not fit all.
A nit: since JDK-1.5.0, the java.lang.ref.Reference class has been generified. So, to create one you use
WeakReference
and weakWidget.get() returns a Widget, just you'd expect.
There are are some details about what the remove() method on a ReferenceQueue
Posted by: peterkessler on May 06, 2006 at 03:04 PM
*
I never really learned the difference between weak & soft until this guy ran into it: http://weblog.ikvm.net/PermaLink.aspx?guid=ec45dec2-ec22-4079-9b78-d06e15ddabe7 Thanks for bringing up Phantom References, I don't think I'd ever heard of them.
Posted by: ronaldyang on May 05, 2006 at 01:56 PM
*
Very nice writeup indeed. I must admit I was unaware of phantom references. I heard somewhere that sun's jre does indeed treat soft references as weak references. Don't know if that's still (or ever really was) the case, but I remember reading it somewhere.
One other common use of weak references is the WeakListener, which prevents an object from hanging around simply because another object is listening on it.
Posted by: richunger on May 05, 2006 at 01:03 PM
*
A very important use of PhantomReferences is in DGC (Distributed GC like in RMI). You most certainly do not want to perform remote notification in the GC thread.
Posted by: ianschneider on May 05, 2006 at 08:56 AM
*
Good blog. I have also found LinkedHashMap very useful for caching.
Posted by: abhijit_jadeja on May 05, 2006 at 06:46 AM
*
Nice entry about a not too well known feature of Java that come quite handy.
I fortunately discovered them long ago thanks to an article at java.com (when it was still called like that) and I've since used Soft References in a few occasions, like creating smart caches of pre-compiled objects (XSLT sheets in my case) that are able to be garbage collected if a sudden peak in memory usage occurs.
You simply re-create them the next time you need them and if the memory usage has gone down, you go back to normal.
I actually wrote an article about using Soft References for such purpose, but it's in spanish ;).
Implementación de Caches Inteligentes Mediante "Soft References"
Thanks again for spreading the knowledge!
D.
Posted by: greeneyed on May 05, 2006 at 04:57 AM
*
Good article. I must confess to being hazy as to the difference between Soft, Weak and Phantom - the API docs aren't terribly descriptive. It's also good to finally get some justification for why on earth anyone would want to use a PhantomReference.
Posted by: skaffman on May 05, 2006 at 12:04 AM
*
Very nice blog entry. I was talking with the development manager of a large all-Java shop one time and I asked him about his need for profiling tools to track down memory leaks. He replied, "We seem to not have a problem with memory leaks since we started using weak references."
Posted by: gsporar on May 04, 2006 at 06:57 PM
*
weak references are essential, alot of associative memory leaks can be removed just by using those babies. I also use them in simple test cases to show that leaks have been removed.
leouser
Posted by: leouser on May 04, 2006 at 05:24 PM
OpenSource Website Composing Tools
Drupal
http://drupal.org
WordPress
http://wordpress.org/
Monday, June 23, 2008
Visitor Pattern Vs. Double Dispatch
Deriving the Visitor Pattern: A Review and Discussion
Like most other self-respecting developers I had also read the GoF book, including the section on the visitor pattern. However, when a colleague came over to me with a question, I could not initially justify the complexity of the example code I saw in the book. What follows is a discussion of why the visitor pattern is the way it is.
Brief Review of the Pattern
The definitive description of the pattern is in the GoF book Design Patterns, Chapter 5 (pp 331-344)(see References section). The Wikipedia has a concise and good description, which formed the basis for my brief review here. The visitor pattern is classified as a Behavioral pattern, so the thing to notice is the way in which the classes and objects interact and distribute responsibility. A typical application of this pattern occurs in the following scenario: we have a number of elements in an object structure (common structures include trees & lists) and we want to perform a bunch of disparate operations (e.g. printing or cloning each element) on the elements of the structure.
The visitor pattern is a way of separating the operation from the object structure and a way of collecting together the different implementations of an operation for different kinds of elements in the object structure. A Visitor class is created which knows how to perform a particular operation on the different kinds of elements in the object structure. Each type of element in the structure defines an accept() method that can accept any kind of Visitor. The visitor is passed to each element in the structure in turn, by calling its accept() method and the Visitor then performs the operation on the visited element. One important consequence of this separation of object structure and operation is that we can later add a new operation (a new kind of Visitor) without having to modify the element classes of the object structure.
Each type of Visitor defines several visit()methods, one for each kind of element. The basic insight is that the precise set of instructions to execute (i.e. the method or function to call) depends on the run-time types of both the Visitor & the visited element. Java only lets us call different methods based on the run-time type of one object (via virtual functions), so the pattern advocates a clever solution: The second dependency on the type of element visited is first resolved by polymorphically calling the accept() method of the visited element. accept() then resolves the first dependency by turning around and polymorphically calling the visit()method for its class.
An Example
Before this description gets too confusing, let us study the pattern in the context of a concrete problem: Let us say we need to traverse a list collecting node-specific information. The list has two kinds of nodes, say, Red and Black, which needed to be processed differently. It seems like an ideal application for the visitor pattern. Listing 1 shows the code. (All code samples in this article use a J2SE 5.0 compatible compiler.)
To me and my colleague, this initially seemed like an overly complex solution for a simple problem. NodeVisitor.doVisit() calls into the Node's accept methods, which simply delegates back into NodeVisitor. Furthermore, the accept() methods of RedNode and BlackNode are almost identical. Finally, notice that if we now add a GreenNode class, we need to add a new visitGreen() method to the NodeVisitor class and re-compile it (not to speak of the almost redundant implementation of accept() in the GreenNode class). Ugh! This does not seem kosher by any OO standard.
The Need for the accept() Methods
Novice armchair Java developers might ask why we can't do something simpler, like Listing 2, for example, without touching the Node interface, or the classes RedNode and BlackNode which implement it.
Listing 2 has two significant differences from the previous. First, there is no redundant method (namely accept()) for each node type to implement. Second, we use function name overloading for the visit() implementations, thus enabling the "clever" foreach loop, which iterates over each node and calls the appropriate overloaded version of visit() depending on the type of the current element. With this, we hope to contain all the visiting logic within NodeVisitor.
Alas, real developers have a more difficult job than arm-chair developers! If you are using a language like Java or C++, an overloaded function name like visit() has to get resolved at compile time. Thus line 6.iii will not compile because none of the visit() methods provided in NodeVisitor know how to accept a generic "Node" as argument.
For line 6.iii to work the way we want it to, the decision on what operation needs to be performed has to be delayed until we can determine at runtime the type of the node n being examined in the current iteration of the for-each loop.
Traditional OO languages (Java, C++ etc) provide us with one standard tool for delaying function resolution until run-time: virtual functions. Thus, in Listing 1, 6.iii is modified to a virtual function call n.accept(nv). So the actual function that gets called is decided at run-time. The version called then delegates work by invoking the right version of NodeVisitor.visit().
So Why Not Just Use Plain Vanilla Inheritance?
The explanation I just gave is good, but not good enough. I can almost hear you ask: why doesn't accept() do the work itself? Why does it have to delegate back to NodeVisitor? There are three reasons:
1. Accumulating state: If you read the problem I presented closely, you will notice that I specified a need to collect node-specific information. Since the doVisit passes the same NodeVisitor instance to each accept(), the visitor can be used to accumulate state across the different Node objects. For example, say you have an Employee HR application where the Red nodes represent employees, the Black nodes represent managers, visitRed() calculates the pay raises for programmers, and visitBlack the pay raises for managers. The NodeVisitor nv could print a report of the total increase in salary expense at the end of the for loop.
2. Supporting more than one visitor (the need for double dispatch): Say the next version of your Employee HR application needs to add a new HRPolicyVisitor that checks for compliance with some HR policy and the implementation is different for managers and programmers.
To accommodate both the types of Visitors, we introduce an additional layer of indirection - an abstract EmployeeNodeVisitor interface with virtual visitXXX() functions for each type of element to visit, namely visitProgrammer() & visitManager(). The old PayRaiseVisitor and the new HRPolicyVisitor both implement EmployeeNodeVisitor. The decision on which version of visit() gets called now gets determined by a two-step process. The first step is as before. The node type of the visited element n in the foreach loop determines which version of the virtual function accept() gets called. In the second step, the type of the EmployeeVisitor passed in to accept() determines the (virtual function) version of visitXXX() called. The source files that come with this article show the skeleton of this implementation. Figure 1 illustrates the sequence of calls from both doPayHike(), which uses a PayRaiseVisitor to raise the pay of each employee, and doEnforcePolicy() which uses a HRPolicyVisitor to check HR policy compliance.
This technique, where the types of two objects are used to select the operation invoked is known as double dispatch. By contrast, single dispatch uses the type of one object to select the operation invoked. One known implementation of single dispatch is virtual functions. Since Java and C++ support only this form of single dispatch, the pattern simulates double dispatch by using single dispatch twice!
3. Separation of concerns: A concern is any focus of interest in a program. A classic tenet of good software design is that the different concerns of a program must be broken down into separate modules that have little or no overlap. In the Employee HR program , visitProgrammer and visitManager of a particular visitor have more commonality than the two visitProgrammers of the different visitors or the two visitManagers of the different visitors. In fact, the methods in a given visitor may even share state information as described in 1 above. This makes the Visitor pattern a good way to organize code by separation of concerns.
Notice also that as a consequence of this way of organizing code, it is extremely easy to add a new visitor operation, but adding a new kind of node requires adding a new visitXXX method to all the Visitors.
If none of the above three reasons apply, you would be better off not delegating the work of accept() back to a separate visitXXX() method.i.e. plain vanilla inheritance would be more appropriate than an application of the Visitor pattern. On the other hand, if any of the above reasons apply, the Visitor pattern would be a good solution for you.
But This Still Does Not Preclude Overloading the visit() Methods...
You might still have one lingering question about Listing 1: Why can't we use function name overloading instead of the different visit<
The short answer is that nothing prevents you from doing this; Listing 3 is just as correct as Listing 1 For the last word, however, I will have to defer to the GoF, who write the following in a footnote:
We could use function overloading to give these operations the simple name, like Visit, since the operations are already differentiated by the parameter they're passed. There are pros and cons to such overloading. On the one hand, it reinforces the fact that each operation involves the same analysis, albeit on a different argument. On the other hand, that might make what's going on at the call site less obvious tosomeone reading the code. It really boils down to whether you believe function overloading is good or not [in this situation].
Conclusion
In this article we reviewed the Visitor pattern and "derived" it from an armchair sketch of the functionality we wanted: the ability to accumulate state over elements of an object structure, the separation of the operations from the object structure, and the ability to add new operations without recompiling the element types. These requirements called for a "double dispatch"; i.e. the precise method to call for "visiting" each element in the structure depended on two runtime types: the type of Visitor and the type of the visited element. The Visitor pattern was shown to be a way to simulate double dispatch using virtual functions, a form of single dispatch.
References
* Gamma, et al. Design Patterns: Elements of Reusable Object-Oriented Software, 1995, Addison-Wesley, Reading, MA.
* Wikipedia contributors, "Visitor pattern," Wikipedia: The Free Encyclopedia, http://en.wikipedia.org/wiki/Visitor_pattern (accessed Aug 19, 2005)
© 2008 SYS-CON Media Inc.
Sunday, May 11, 2008
Spring: OpenSessionInViewInterceptor vs. OpenSessionInViewFilter
Problem: Assuming you're using an ORM, such as Hibernate, rendering the view with business objects that have many-to-one or one-to-one relationships might try to access a detached object with a lazy property and throw a LazyInitializationException. For this reason, we're provided with the Open Session In View pattern.
Solution: The Open Session In View pattern binds a Hibernate session to the thread to be used throughout the life of the request and closes any transactions when the response is sent. This is what allows your view to access model objects with lazily loaded properties after a transaction has been closed. This is nothing new and this is not what this post is about.
To setup the Open Session In View in your Spring application, you have two options. The OpenSessionInViewInterceptor and the OpenSessionInViewFilter. You can use either solution because the two classes serve the very same function. Well if this is the case, then why do they both exist? Why is there a filter option and an interceptor option? This is what I set to find out.
I've been searching Google all night. I've read through forums, I've read docs, and I've read blogs. Why? Because I want to use the better of the two options on my application. I want to ensure I am getting the best performance and the most reliability for my clients as I can. Anyway, the only thing that I could dig up was that they are equal in almost every way. The only consideration that you really need to make is what servlet spec you are using. If your servlet container support version 2.3 or later, you can use either one. If it's 2.2 or earlier, you'll need to go with the OpenSessionInViewInterceptor.
Surely there are other considerations. Maybe you want to keep your filters down to a bare minimum, or you think interceptors are confusing or messy. Or perhaps you like to keep your configuration files as small as possible. If you use annotations, you might want to go with the OpenSessionInViewInterceptor.
I hope I answered any questions you had about why there were two classes for implementing this pattern.
My tiny little blog here has been getting tons of hits because of my post titled OpenSessionInViewInterceptor vs. OpenSessionInViewFilter so I guess people are interested in these. I don't know why you all are comming here. I do know that I'd hate for you to come here looking for an example and then have to go looking elsewhere for it, so here is an example of each.
Interceptor Configuration (action-servlet.xml)
...
...
Filter Configuration (web.xml)
...
openSessionInViewFilter
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
...
...
I hope this is what you were looking for.
Lazy Initialization and the DAO pattern with Hibernate and Spring
(from: http://www.blogjava.net/vince/archive/2006/11/27/83850.html)
Hibernate and Lazy Initialization
Hibernate object relational mapping offers both lazy and non-lazy modes of object initialization. Non-lazy initialization retrieves an object and all of its related objects at load time. This can result in hundreds if not thousands of select statements when retrieving one entity. The problem is compounded when bi-directional relationships are used, often causing entire databases to be loaded during the initial request. Of course one could tediously examine each object relationship and manually remove those most costly, but in the end, we may be losing the ease of use benefit sought in using the ORM tool.
The obvious solution is to employ the lazy loading mechanism provided by hibernate. This initialization strategy only loads an object's one-to-many and many-to-many relationships when these fields are accessed. The scenario is practically transparent to the developer and a minimum amount of database requests are made, resulting in major performance gains. One drawback to this technique is that lazy loading requires the Hibernate session to remain open while the data object is in use. This causes a major problem when trying to abstract the persistence layer via the Data Access Object pattern. In order to fully abstract the persistence mechanism, all database logic, including opening and closing sessions, must not be performed in the application layer. Most often, this logic is concealed behind the DAO implementation classes which implement interface stubs. The quick and dirty solution is to forget the DAO pattern and include database connection logic in the application layer. This works for small applications but in large systems this can prove to be a major design flaw, hindering application extensibility.
Being Lazy in the Web Layer
Fortunately for us, the Spring Framework has developed an out of box web solution for using the DAO pattern in combination with Hibernate lazy loading. For anyone not familiar with using the Spring Framework in combination with Hibernate, I will not go into the details here, but I encourage you to read Hibernate Data Access with the Spring Framework. In the case of a web application, Spring comes with both the OpenSessionInViewFilter and the OpenSessionInViewInterceptor. One can use either one interchangeably as both serve the same function. The only difference between the two is the interceptor runs within the Spring container and is configured within the web application context while the Filter runs in front of Spring and is configured within the web.xml. Regardless of which one is used, they both open the hibernate session during the request binding this session to the current thread. Once bound to the thread, the open hibernate session can transparently be used within the DAO implementation classes. The session will remain open for the view allowing lazy access the database value objects. Once the view logic is complete, the hibernate session is closed either in the Filter doFilter method or the Interceptor postHandle method. Below is an example of the configuration of each component:
Interceptor Configuration
...
...
Filter Configuration
...
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
...
...
Implementing the Hibernate DAO's to use the open session is simple. In fact, if you are already using the Spring Framework to implement your Hibernate DAO's, most likely you will not have to change a thing. The DAO's must access Hibernate through the convenient HibernateTemplate utility, which makes database access a piece of cake. Below is an example DAO.
Example DAO
public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {
public Product getProduct(Integer productId) {
return (Product)getHibernateTemplate().load(Product.class, productId);
}
public Integer saveProduct(Product product) {
return (Integer) getHibernateTemplate().save(product);
}
public void updateProduct(Product product) {
getHibernateTemplate().update(product);
}
}
Being Lazy in the Business Layer
Even outside the view, the Spring Framework makes it easy to use lazy load initialization, through the AOP interceptor HibernateInterceptor. The hibernate interceptor transparently intercepts calls to any business object configured in the Spring application context, opening a hibernate session before the call, and closing the session afterward. Let's run through a quick example. Suppose we have an interface BusinessObject:
public interface BusinessObject {
public void doSomethingThatInvolvesDaos();
}
The class BusinessObjectImpl implements BusinessObject:
public class BusinessObjectImpl implements BusinessObject {
public void doSomethingThatInvolvesDaos() {
// lots of logic that calls
// DAO classes Which access
// data objects lazily
}
}
Through some configurations in the Spring application context, we can instruct the HibernateInterceptor to intercept calls to the BusinessObjectImpl allowing it's methods to lazily access data objects. Take a look at the fragment below:
When the businessObject bean is referenced, the HibernateInterceptor opens a hibernate session and passes the call onto the BusinessObjectImpl. When the BusinessObjectImpl has finished executing, the HibernateInterceptor transparently closes the session. The application code has no knowledge of any persistence logic, yet it is still able to lazily access data objects.
Being Lazy in your Unit Tests
Last but not least, we'll need the ability to test our lazy application from J-Unit. This is easily done by overriding the setUp and tearDown methods of the TestCase class. I prefer to keep this code in a convenient abstract TestCase class for all of my tests to extend.
public abstract class MyLazyTestCase extends TestCase {
private SessionFactory sessionFactory;
private Session session;
public void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
session = SessionFactoryUtils.getSession(sessionFactory, true);
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
}
protected Object getBean(String beanName) {
//Code to get objects from Spring application context
}
public void tearDown() throws Exception {
super.tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
}
}
Saturday, March 01, 2008
小资一下,侃侃股市
作者: Lonehand 龙汉
大凡留美之人,虽“来自五湖四海” ,但都是“为了一个共同的革命目标” ,走得基本上是同一条“革命路线” ,那就是:学业,工作,身份,房子,股。。。中间时不时加点儿爱情及色情,顺序可能有偏差,但都大同小异,八九不离十。前几年,借经济繁荣之东风,趁“达康”( 。COM) 泡沫之汹涌, 真个是男女老少齐上阵,没钱借贷也争先。整个儿一“祖国的大好形势是一派大好”。
星移斗转,“股” 随“市” 迁,“雨季不再来” ,昨日昙花现。大小股民人仰马翻,从几百块,到几十万,赔得这叫惨!痛定思痛之后,不尽扪心自问:我这里“千金一掷” 为哪般?难道股市真的有“红颜” ?
各位看官,以上对形势的分析,仅为洒家一孔之见,自是可“砸” 可点,下面咱书归正传。
先说说纽约股票交易市场(New Your Stock Exchange, NYSE,以下简称纽约股市),通常大家说的“华尔街” ,指的就是这个地方。它采用的是“拍卖制” :在大厅内设置多个“摊位”(Posts),每个摊位都有一个庄家 (Specialist) ,专营几种股票,大小股民,不论是你我这样的散户,还是大银行,共同基金,“海居”基金(hedge fund),只要是买卖在纽约股市上市的股票,都要经过庄家之手,无一例外。(近来有一新系统,叫NX,其功能是,如果交易不超过一千股,可直接用电脑接单。实际运作却大相径庭,NX经常被庄家关掉。) 当有人送单给庄家,他会首先喊出,三千美国在线(AOL),15。3,一旦有人(Floor Traders) 点头,庄家就说“卖了。” ,继续下一轮交易,此乃“拍卖制” 的来源。各位也许要问:为什么要庄家?都用电脑直接操作多好?就象纳斯达克(见下文)那样成不?不行。因在纽约股市上市的多为信誉不错的大公司,为维护其股票的流动性(Liquidity)及稳定性(LessViolatility),非庄家不可,举例说明:当一个公司有坏消息传出,其股票会一泄千里,买家廖廖无几,按纽约股市规则,庄家却是非买不可,价格随他出,以便稳定股价,让股市的革命群众出场。各位看官要问,那庄家不赔死了,不然,听我细细道来。假定“海居”张三要买十万股通用电器 (GE),单子下到庄家那里,按纽约股市规定,他有两分钟时间做决定,此时他会快速买进通用股票,再以高一点的价格转手卖给张三,一出一进,就是白花花的,且无风险,此为“前软”(Front run)客户,在纽约股市每天都有。那边说了,既然庄家的生意这么好做,咱也试试成不?否也,庄家的生意大都是家族世袭的,传子不传女,外人根本沾不上边儿。据洒家我在纽约股市门口与他们抽烟,聊天的两小时经验,多数庄家为意大利及犹太后裔。
再说说纳斯达克(NASDAQ) 。如你问一炒股老中,NASDAQ是“神马” 意思,相信能说上来的不多,龙某不 才,在此为大家“科普” 一哈,以正视听。NASDAQ是 National Association of Security Dealers Automatic Quotation 的缩写,有点语病。说白了就是:全国庄家协会自动报价盘。它采用“庄家”(Dealer) 制而不同于纽约股市,它没有交易大厅,所有交易全部由电脑完成,主服务器位于康乃狄格州,备用服务器位于马里兰州,时代广场上那个(常上电视的) 只是为了秀。与纽约股市不同,纳斯达克由众多股市经纪人 (Market Maker, 以下简称“那美媚”) 及ECN(Electronic Communication Network)组成。那美媚们多由各大银行 如美林(Merrill Lynch),高盛(Goldman Sachs), 李蔓兄弟(Lehman Brothers)等的顶级操盘手充当,用一种叫做“三级”( 见下文) 的终端,坑蒙拐骗,凶猛异常,整个一吃人不吐骨头。再说说ECN,几年前,共有九家,几经和并之后,只剩四,五家,最著名的有:“立马见效网” (Instinet) ,“岛屿网”(Island) ,“阿奇派勒狗”(Archipelgo, 由原来的“红迪”(Redi) 和“阿奇派勒狗”合并。(注:Archipelgo 现已成为Exchange) ,其他的还有Attain(ATTN,All –Tech Direct), Bloomburg Tradebook(BTRD),Brass Utility (BRUT), NexTrade (NTRD) and MartketXT(MKXT),以笔者之见, ECN为散户的真正朋友,因其没有人为干预,全由电脑自动运作。按执行速度排序,分, Island) ,Instinet ,Archipelgo, 为最佳, 又由于Instinet 多为大户 , 所以极少有部分执行(Partial Fill),举例来说,如你买一千股,Island虽快,却有可能只给你九百三 十七股,剩下的六十三股,你只好再下一张单子,多交一笔手续费。那边说了,你咋知道哪些股票是在纽约股市,哪些是在纳斯达克的呢?不难。纽约股市的
股票都是以一个,两个或三个字母为其符号(如A,GE,AOL等),而纳斯达克的股票都是以四个,或五个字母为其符号(如INTC,CMCSA等 - QQQ不算).
以上两大市场为最有影响的,其他的如美国股市(American Stock Exchange) 太平洋股市,及一些可有可无的股市如位于费城的,波士顿的。这里要说明一下,位于芝加哥的Chicago Board of Trade(CBOT) 和Chicago Mercantile Exchange(CME), 也为重量级市场,但因CBOT主要是经营债圈(BOND)的,CME主要是经营期货期权(OPTION,FUTURE),本文不再赘述。
说完股市,再说股民。除了大家熟知的银行,保险公司,共同基金,“海居”基金等大玩家,及你我这样的“革命群众” 外,这里着重侃侃鲜为人知的“第三梯队” -- “波派公司” (Proprietary Trading Firm) 。此类公司面向“工农” ,只要你智商高于“阿赣”(Forest Gump) ,再通过7,55系列考试,就可交一点钱或不交钱,加入公司,在公司的严格监督之下,用公司的资金炒股。此等“股手” 一但练成, 即为仅次于各大银行的顶级操盘手的股市江湖中的大侠。(成功率只有百分之十左右)
以上所说的只为一点预备知识,为下文打打基础,各位如果看到这还没打呼噜,说明你小子“可教”。咱这就说说那精彩的部份--如何炒股。
一提炒股,相信有九成的同志们有如下的概念:拿出万八千块来,在网上开个户头,看看电视,翻翻报纸,听听小道消息,网上搜索一哈,买他三,五百股之后,就开始守株待兔了。若运气好,股票涨了,我就小赚一笔,下回再如此这般。若运气不好,股票跌了,我就坚决闷住,来他个誓死捍卫---就不信马王爷三只眼, JDSU涨不回54!各位看官,老少爷儿们,您要是这么炒,就好比拿着菜刀去打伊拉克,若是在头几年,伊拉克人民都用螺丝刀打群架的年代,您一准成富翁,若是换了目前的股市,您连百分之一的希望都没有。。。下面从不同角度详细说说。
从时间上讲,分长期,中期,短期,超短期 (Day Trading)。长期一般为数月到数年不等。中期一般为数周到数月。短期为几天到数周。超短期是指从几秒钟到数小时。时间的化分,十分重要,入场前,一定要搞清楚,否则,泡妞泡成老公,炒股炒成股东。。。后果不堪设想。
从策略上说,分为买涨 (Long),买跌 (Short)及买差价 (Market Neutral)。那边说了,买涨 (Long) 咱懂,就是低买高卖。买跌 (Short) 也听说过,就是先借股卖掉,等股跌了,再买回来还上(Cover) ,这买差价(Market Neutral) 是“神马” 东东?且听洒家慢慢道来:
买差价(Market Neutral) 作为一种市场策略,有很多变种(Variations) ,这里仅以其最著名的“对炒” (Pair Trading)为例说明一哈:荷兰皇家(Royal Dutch -RD) 和壳牌 (Shell -SC) ,名为两家公司,实是源出一脉。换句话说,就是RD涨,SC就涨;RD跌,SC就跌;二者同步,即这两种股票的差价趋于一常量(RD-SC=N,N为一长期的平均值),不论市场是牛是熊, 此N应保持不变。但由于股票的瞬间波动, 有时两者出现偏差,(RD-SC大于N ) 或 (RD-SC小于N ),此时的做法是,若 RD-SC大于N,则同时Long SC(低的那个) ,Short RD(高的那个) ;反之,若RD-SC小于N,则同时Short SC(低的那个) ,Long RD(高的那个) ,因炒家心里清楚,RD_SC早晚会回到N来。。。Pair Trading不仅可用于股票,还可用于其他市场,如几年前以John Meriwether 为首的 Long Term Capital Management 就把Pair Trading 用于炒公债(Bond) 。须要说明的是,Pair Trading 需大量资金,不太适合革命群众,由其是刚参加革命工作的同志。
从战术上讲,分为“基础研究” (Fundamentalist) ,技术分析(Technical Analysis) 和看盘(Tape Reading) 。
基础研究指的是对公司的经营,财务,人事调动,产品开发等一系列基本设施进行深入细致的调查研究。其代表人物有如日中天的巴菲特(Buffet) ,及各大共同基金(Mutual Fund)。此类打法适用于长期投资,而绝大多数股民亦采用这类玩法。说几句题外话,相信各有工作的茶客都知道401K,而绝大多数401K实际上就是共同基金。共同基金的特点是,
1。它只能买涨(Long) ,而不能买跌(Short) ;
2。它的管理人(Fund Manager) 是拿工资的,即不论基金营亏,经理照拿不误。
3。它不允许把超过5%的资金投入任何一种Instrument(股票,债卷等) ,为的是多元化(Diversification) 。
而大市已连年走底,这就是为什么90% 401K 等近两年来都在赔钱。以洒家孔见,今年大市上扬,故力劝各位要Stick With 401K,不要失去信心。
技术分析(Technical Analysis) 作为一种与基础研究截然不同的战术,则侧重于对股价过去的表现进行分析,来短期预测股价的未来走势。它适用于中短期的操作,最著名的代表为Moving Average,Moving Average Convergence Divergence,Relative Strenth Indicator,Bowlinger Band,Elliot Wave,等诸多理论,这里不一一赘述,有兴趣的朋友可买本“大全”之类的书,自己研究研究。
看盘(Tape Reading) 是一类鲜为人知的高难技术,它是通过对股票现时的交易量,价格及参与者(Specailist and Market Maker)进行快速分析,从而预测股价的瞬间动态,来决定入场与出场的时机。 这种技术对工具的要求很高,二级(Level2) 软件及宽带网络联接为必备手段,最适合于超短期 (Day Trading) 的操作。洒家曾仔细研究过,还与一老美股友在YAHOO上开一聊天室现场(Real Time) 示范达半年之久。后因 Conflict Interest,只能作罢。那老美当年年仅二十,为一富家子弟,近来听说自己聚了几个Million,开了“海居”(Hedge Fund)基金,此题外话。
最后侃侃炒股所用的工具。在网络技术普及的今天,大多数股民都是在网上交易。网上工具按执行速度,价格及所提供的信息量又分三种,现分别介绍如下:
第一类,Web Based。此类多为股票中介公司提供的网站,其中以ETrade及(Datek-AmeriTrade) 为代表。其特点为,界面相对简单易懂,价格相对便宜,也提供Level2。不足之处为速度慢,经常出故障,用户服务跟不上---打电话过去,半天没人接。但适合中,长期的投资。
第二类为所谓的“直接连接” (Direct Access),采用Server/Client结构,股民须安装相应软件才能操作。此类软件速度快,信息多,Level2为标准设置,是真正炒家的必备。虽然贵一点,但绝对是物有所值。举几个例子:Real TickIII, Cyber Trader, e-Signal, DTN-IQ, TradeStation…这里着重要说的一个是IB(InteractiveBrokers), 它的特点是,价钱奇低无比,Java的界面也很快(用HotKey) ,可与 e-Signal 等联用 。美中不足的是,服务太差,有时很麻烦 。
第三类为专业炒手所用,除具有第二类的功能外,再加上现时新闻(Real Time News) , 洒家只是见过,从未有机会使用,没资格品头论足。此类的代表为,AT-Financial,Watcher等。
洋洋洒洒,码了几天,本打算写着玩玩,一不小心上了贼船,下不来了。弄了"懒婆娘的裹脚布--又臭又长"。还不知是否会误人子弟。。。下回一定写点轻松的。此文如能在各位入场之前,起到一路灯的作用,给大家照个三米五米的,也不枉我码这万八千Bytes。
后记:
此文为我之旧作。只凭记忆,没有参考任何资料,码错之处在所难免,更非号召大家入市一博,本欲与同道朋友切磋交流,看过反应,发觉又成龙汉“独” 家之言,(爱打架的比有功夫的人多?)故特在此声明:大千股市,风险多多。不论输赢,概凭各人修行,龙汉概不负责。
Saturday, February 23, 2008
2008 Study Plan:
Technical: Java
+ Multi-Thread
+ MQ & JMS
+ SOA & Web services & Modern Design Patterns
+ Sybase & other DB, data model, design, query optimization.
+ Trading platforms such as credit derivatives.
+ Real-time, high volume, distributed application.
+ Tibico
Management: PMP
==========================================================
Java Developer - Fixed Income
Location: Downtown Toronto
Salary: Commensurate with experience
Requirements:
5+ years experience developing and delivering high performance server side applications in Java. Experience on Servlet/JSP, Spring, AJAX, JavaScript, HTML/DHTML, CSS, XML, Tomcat.
Excellent communication skills, verbal and written, and ability to work in a fast-paced environment as a constructive team member.
Experience with real time, high volume, distributed applications.
Demonstrated usage of threading and asynchronous processing.
Expertise with RDBMS a plus, including database schema design, writing stored procedures, performance optimization, preferably using Oracle.
A general understanding of trade settlement in a financial environment.
Knowledge of Foreign Exchange products a major plus.
Experience using a continuous integration environment with tools such as Cruise Control, Ant and Junit a plus.
==============================================================
Senior Developer (J2EE) in RBC Fixed Income Product Technology group to develop, implement and support a first class risk monitoring application.
-10 years experience in system design and development
-Extensive understanding of latest J2EE, XML and Messaging technologies
-Extensive knowledge of Sybase (Sybase IQ preferred), Transact-SQL and stored procedures
-Ability to formulate and implement efficient algorithms for fast-time systems
-Solid understanding of multi-threaded application development
-Broad knowledge of Fixed Income Credit terminology and products, and Market Risk reporting
-Previous leadership or mentoring experience
-Excellent communication skills
==============================================================
A senior developer in Money Markets Sales and Trading Systems team, which supports the Fixed Income Business of RBC Capital Markets.
• 7+ years of experience in software development
• Extensive knowledge of core Java technologies (both server side and client side) and development tools
• Extensive knowledge of relational databases (that includes ability to write high-performing SQL queries, optimize performance of existing queries and ability to design database models)
• Extensive knowledge of messaging technologies (TibRV, MQ, JMS)
Business Knowledge
• Solid understanding of Money Markets business and general understanding of Fixed Income related businesses (bonds, repos, fixed income derivatives)
• Completion of Canadian Securities Course
==============================================================
Job Title Team Lead
Location Toronto, ON, CA
Organization Name Global Futures Technology
Department Description
The Futures Front Office technology group is part of Global Futures Technology within the Merrill Lynch Global Markets Technology organization. The group supports Futures Front to middle office trading and post-trade allocation for Merrill Lynch globally, with users and technology support located in the US, Canada, Europe and Asia.
Brief Description
The successful candidate will have a proven record of enterprise application development and delivery, preferably working in the financial services industry. The candidate will need to have excellent team management skills.
Job Responsibilities
Development of components to integrate with key Global projects. Candidate will have a proven track record in management, architecture and delivery of large scale trading front/back end/OMS applications. The candidate will focus on a number of key Global Futures initiatives for external clients, FIX trading and middle office functionality.
Qualifications
+Excellent team management skills
+Strong Socket programming
+Strong Multi-threading
+Trading system experience
+Experience in OMS design and coding
+Experience in Financial trading system
+Experience with Java client-server programming
+Experience in designing message-hub type of application (i.e. OMS, Router)
+Experience with Messaging (i.e. JMS, TIBCO)
+Oracle (SQL/JDBC)
+FIX protocol
+Good design pattern knowledge
========================================================
Job Title Sr. Java Developer
Organization Name Credit Trading Risk Technology Group
Department Description
The Credit Trading Risk Group was created in 2007 to server all risk applications development and maintenance support across all Credit trading business activity in all regions (AMRS, EMEA and PAC RIM)
This team has a global presence in AMRS, EMEA and PACRIM and serves Credit business (cash and derivatives including flow and structured) to deliver risk metrics using overnight batch or intraday calculation platforms all ML built in (incl some third party vendors for data caching and grid computing)
Brief Description
The Credit Trading Risk Technology group is looking to hire a Senior Java Developer to take the lead for the development and maintenance support of some specific Credit Risk applications
Job Responsibilities
+ Strong ability to analyze functional needs that drive the analysis and technical design of quality technical solutions.
+ Strong ability to work collaboratively with IT staff on development, troubleshooting and other technical efforts.
+ Responsible for design and development phases (inc technical testing phase and documentation)
+ Strong ability to face off business users for requirements gathering
Qualifications
+ 5-6 years experience.
+ Bachelors Degree or equivalent work experience in Computer Science, Information Systems or other related field.
+ JDK 1.4.2 and 1.5.
+ Weblogic 8.X
+ Spring Framework
+ Web Services
+ Design Patterns
+ TDBMS SQL (Oracle/Sybase)
+ RDBMS (Oracle or Sybase)
+ Strong analytical ability and problem solving skills.
+ Strong communication skills
Preferred Skills :
+ Knowledge of Service Oriented Architecture
+ Knowledge of any Data cache system
+ Credit business knowledge (or any Fixed income knowledge)
=================================================================
Job Title Java Developer
Department Description
Liquidity & Risk Technology (LRT) provides programs, applications and platforms that help report, monitor, manage, and measure risk. LRT is comprised of five major technology groups: Credit Risk, Market Risk, Regulatory, Finance, and Treasury.
Brief Description
The successful candidate will have a proven record of enterprise application development and delivery, preferably working in the financial services industry.
Job Responsibilities
The Java Developer’s role is to design, execute, and deliver components and/or solutions while adhering to strict project deadlines. In addition to technical and analytical skills, the developer must demonstrate strong communication skills and a “team player” attitude.
Qualifications
Core Competencies
* 5+ years experience with Java
* Demonstrated experience using Web Services
* Experience applying modern design patterns in building SOA components
* Demonstrated experience using JDBC and Oracle required (9i and 10g)
* Experience using one or more app servers like Weblogic, Websphere
* Experience in designing and implementing robust, highly scalable, n-tier transaction processing applications using J2EE
Good To Have
* Experience using OR tools such as Hibernate
* Experience with trading platforms, especially Credit Derivatives
=====================================================================
Thursday, January 25, 2007
Two Java Groups
http://tech.groups.yahoo.com/group/chicago-java-advertise/
Seattle Java User Group
http://www.seajug.org/
An interesting job opportunity
Software Group provides the foundation for On Demand Business. We
are the world's largest provider of middleware and the second-
largest software business in the world, contributing about 15% of
IBM's total revenue and one-third of its profits. We have
approximately 40,000 employees worldwide, including the world's
largest direct software sales force of 13,000 people. SWG works with
100,000 business partners worldwide, with more than 100 strategic
ISV alliances. We have 40 software research labs worldwide; more
than 25,000 developers, 24 on-demand software centers; and 14,000
employees dedicated to open software technologies, including Linux,
Java and XML.
This role is responsible for assisting IBM Banking Clients with
leading edge software solutions using IBM Software. The Industry
Architect will work with our Banking clients to establish
requirements, architect solutions, and lead First-of-a-kind solution
implementations (in coordination with BCS or SW Services teams). The
Industry Architect will also work closely with Product Development
teams to assure feedback of functional requirements from our Banking
clients into our product development process.
Must be a Banking industry domain expert and must also possess a
broad understanding of the SWG middleware porfolio. Excellent
customer and internal communication skills are mandatory. Candidates
can live anywhere in the U.S. Role requires travel to customer
sites. (40-50%).
Requirements include: producing FSS IT architectures; Disciplined,
method-driven execution; Full life cycle experience; Banking
Industry expertise; Strong communication and professional skills;
Technical Leadership; SOA, WebServices);
J2EE and J2EE App Servers; RUP or equivalent architecture
methodology; Deep banking domain expertise, preferably developed
through employment in the IT architecture function at a large
banking institution or through 10 or more years of professional
services work at Banking clients. Experience in designing and/or
implementing complex banking applications (core
banking/payments/lending/branch & multichannel). Real experience in
architecture design using Global Method, RUP, or equivalent.
IBM is committed to creating a diverse environment and is proud to
be an equal opportunity employer. All qualified applicants will
receive consideration for employment without regard to race, color,
religion, sex or national origin. xallx xnationalx.
Apply:
http://careers.peopleclick.com/jobposts/Client40_GLDTR/BU1/External/1
39-12389.htm?ShowReturn=Yes
Saturday, September 09, 2006
How to use JCE - Part 2
http://www.phpwind.net/simple/index.php?t109465.html
对称密钥加密与解密
http://www.javatx.cn/clubPage.jsp?ccStyle=0&tID=798&ccID=16
Encrypt Sensitive Configuration Data with Java
http://www.devx.com/Java/10MinuteSolution/21385/1954?pf=true
Java Technology Forums - encrypt and decrypt sample code
http://forum.java.sun.com/thread.jspa?threadID=753209&tstart=135
探索 XML 加密,第 1 部分
http://www-128.ibm.com/developerworks/cn/xml/x-encrypt/index.html
Exploring XML Encryption, Part 2
http://www-128.ibm.com/developerworks/cn/xml/x-encrypt2/listing2.html
How to use JCE - Part 1
JAVA的安全盾牌-JAVA安全技术 java几乎成为网络程序的标准语言,java给我们提供了先进的应用技术的同时,同时给我们提供了非常强大的安全技术。这些技术主要包括: 1 加密和解密技术; 2 JAVA源代码保护技术; 3 数据完整性保护技术(数字签名和消息摘要); 4 数字证书技术; 5 其它更高级的技术(包括Kerberos技术和JAVA GSS-API技术等等); Java加密扩展即Java Cryptography Extension,简称JCE。它是Sun的加密服务软件,包含了加密和密匙生成功能。JCE是JCA(Java Cryptography Architecture)的一种扩展。 JCE没有规定具体的加密算法,但提供了一个框架,加密算法的具体实现可以作为服务提供者加入。除了JCE框架之外,JCE软件包还包含了SunJCE服务提供者,其中包括许多有用的密码算法和数字签名算法,例如DES、RSA、DSA、SHA、MD5等。使用JCE进行加密解密非常方便,在后面我们将详细的讲述这一技术。 4 如何最大限度的保证应用的安全性系统被挂了我们可以重装系统,但是应用程序和服务的敏感数据和信息被改了或者被盗窃了那我们只有祈祷上帝,希望攻击者能够良心发现。不过千万不要沮丧,我们可以利用JAVA为我们提供的一些武器来增强我们的信心,利用这些东西至少可以挡住99%以上的攻击行为,使我们的损失最小化。(1) 使用JCE技术来加密敏感信息和保护敏感信息的数字摘要;(2) 使用JAVA Logging API建立日志和审核机制;(3) 使用JAAS进行用户身份认证和授权;(4) 利用数字签名技术保证数据的完整性;(5) 利用自定义的类加载器来加载加密后的JAVA类文件以抗击JAVA源代码分析和攻击;(6) 使用JCE来构筑安全通讯协议来保证数据传输的安全。 5使用JCE技术来加密敏感信息和保护敏感信息的数字摘要目前SUN公司的最新版本的JDK(JDK1.5)包含以下几种密码算法:(1)DES:DES(数据加密标准)是由 IBM 于上世纪 70 年代发明的,美国政府将其采纳为标准。它是一种 56 位分组密码。(2)TripleDES:该算法被用来解决使用 DES 技术的 56 位时密钥日益减弱的强度,其方法是:使用两个密钥对明文运行 DES 算法三次,从而得到 112 位有效密钥强度。TripleDES 有时称为 DESede(表示加密、解密和加密这三个阶段)。(3)AES:AES(高级加密标准)取代 DES 成为美国标准。它是由 Joan Daemen 和 Vincent Rijmen 发明的,也被称为 Rinjdael 算法。它是 128 位分组密码,密钥长度为 128 位、192 位或 256 位。(4)RC2、RC4、和 RC5:这些算法来自领先的加密安全性公司 RSA Security。(5)Blowfish:这种算法是由 Bruce Schneier 开发的,它是一种具有从 32 位到 448 位(都是 8 的整数倍)可变密钥长度的分组密码,被设计用于在软件中有效实现微处理器。(6)其它:包括RSA、MD5、SHA、DAS等。除此而外,由于JCE的开放性,JDK还支持第三方提供的密码算法。在系统中,我们首先应该搞清楚的问题是:(1)该对什么数据加密?(2)选择什么样的加密算法?(3)如何实现加密?回答这三个问题对于不同的系统有不同的说法,通常是根据应用来定的。打个比方,银行系统有两个字段:开户人帐号和开户人密码,那我们再权衡后会选择开户人密码。对于数据库系统而言,大规模加密会导致系统反映迟钝,严重影响效率。因此选择加密算法的时候必须考虑这点,对于数据加密我们用对称加密算法,对于对称加密算法密钥等信息我们可以使用公钥加密算法,对于流媒体我们可以采用流加密方法。下面我们来回答第三个问题,如何实现加密。通过JCE使用对称加密算法的过程一般是这样的: 1 引入JCE加密算法库; 2 将要加密的数据变成一个字节数组; 3 调用Cipher.getInstance建立一个Cipher实例; 4 选择加密模式,调用init方法传递密钥并初始化Cipher; 5 调用doFinal方法,传递要加密的字节数组进行加密; 6 将加密后的字节数组转变为普通的字符串类型。需要注意的是因为加密后的密文是未知的,其中可能出现对应于ASCII行尾符或者文件尾符的密文,因此一般在应用中我们采用BASE64编码进行处理。下面我们给出示范源代码(实际使用的代码比这个要复杂得多,并要使用BASE64编解码): /* writer:fleshwound
/
package myprojects.jce_smatrix; import javax.crypto.*; import java.security.*; import java.io.*; public class Jce_smatrix { public static String s="welcome to smatrix!";
public Jce_smatrix()
{
System.out.println("A JCE example begin:\n");
System.out.println("plain text is:"+s+"\n");
}
public static void main(String args[]) throws Exception
{
Jce_smatrix jceexa=new Jce_smatrix();
//初始化密钥
KeyGenerator kg=KeyGenerator.getInstance("Blowfish");
kg.init(128);
SecretKey key=kg.generateKey();
//加密
Cipher c=Cipher.getInstance("Blowfish/ECB/PKCS5padding");
c.init(Cipher.ENCRYPT_MODE,key);
byte[] content=s.getBytes("UTF8");
System.out.println("before ENCRYPT:");
for(int i=0;i
(reference: http://www.secwiki.com/wiki/index.php/æ°æ®å å¯)
1. 配置jce开发环境
虽然JDK1.4将java安全包包含在核心库中,但如果不对jce进行配置,也没办法使用jce进行开发。
首先从sun网上下载jce1.2.2(我在网上看到的都是下载一个包,没用sun默认的),然后把解压得到的lib里面的所有jar文件拷到your_jdk\jre\lib\ext(your_jdk为你的jdk安装目录),编辑your_jdk\jre\lib\security\java.policy文件,在最后加上
grant codeBase "file:${java.home}/lib/ext/sunjce_provider.jar" { permission java.io.FilePermission "file:${java.home}/lib/ext/sunjce_provider.jar", "read"; permission java.lang.RuntimePermission "getProtectionDomain"; permission java.security.SecurityPermission "putProviderProperty.SunJCE";};
给sunjce_provider授予访问权限 your_jdk\jre\lib\security\java.security里面配置了可选的provider类型,这里用默认配置就行了。(这里的provider也可由用户自己用别的厂商提供的包替换,我不是太清楚怎么作)。 由于我是用Jbuilder开发,必须加上对相关库的链接。所以就在Project下面的properties的library设置里面加上对jce1_2_2.jar、sunjce_provider.jar的引用,配置完毕之后,就可以进行JCE相关的程序编写了。
我用jce写了一个des加解密的小程序,不知道为什么,运行起来很慢。感觉是装载provider花时间。偶N不了解为什么sun会用provider这种安装组件的方式,很麻烦,也很没必要。我在eclipse下配置了半天都没弄好,郁闷死了
(Reference: http://www.cnblogs.com/lzcarl/archive/2005/07/27/201477.html)
2. 使用JCE进行DES加密
1、 引言
随着科技的日益发达,人们在对方便性要求逐渐提高的同时,对安全性的要求也日益提高。而使用加密的方法保护文件已成为计算机安全应用中重要的组成部分。DES加密方法作为一种世界标准的加密形式, 已经15 年历史了,虽然有些老, 可还算是比较可靠的算法,因此在加密应用中还是有一定的市场。
2、 DES算法简介
DES是一个分组加密算法,他以64位为分组对数据加密。同时DES也是一个对称算法:加密和解密用的是同一个密钥。它的密钥长度是56位(因为每8位的最后一位都用作奇偶校验),密钥可以是任意的56位的数,而且可以任意时候改变。其中有极少量的数被认为是弱密钥,但是很容易避开他们,所以保密性依赖于密匙。虽然DES算法实现起来比较简单,加解密速度也比较快,但是因为密钥过短,比较容易被破解,地位就逐渐被其他的加密算法取代。
3、 JCE简介及配置见http://www.cnblogs.com/archive/2005/07/27/201477.html
4、 DES加密程序
这个加密程序的密钥采取自动生成的方式,并把生成的密钥保存在文件中。这样只要拥有密钥文件就可以加解密从而避免了用户忘记密钥的问题,同时,由于每次加密使用的密钥都不相同,提高了安全性。
在设计这个加密程序的时候,考虑到以后这个程序的复用性,我将程序分为三个类:
BytesCipher:提供了对byte型数组进行加解密的功能,同时还可以生成DES密钥。
FileCipher:提供了对文件加解密的功能(先将文件转换成byte型数组),同时可以保存、读取密钥。
DESCipher:主程序类。我将整个程序设计成命令行形式,仿照dos命令,用户输入命令和相应的参数就可以执行程序,同时可以查看帮助。
在异常处理方面,我把程序执行过程中抛出的异常进行了二次处理,加上了自己赋予的异常信息,再发送到主函数中统一处理。
BytesCipher类代码:
import java.security.*;import javax.crypto.spec.*;import javax.crypto.*;public class BytesCipher { //默认使用des加密 private static String algorithm = "DES"; /** *//** * 使用JDK中的JCE生成密钥 */ public static byte[] generateKey() throws Exception { try { //生成一个可信任的随机数源 SecureRandom sr = new SecureRandom(); //为我们选择的DES算法生成一个KeyGenerator对象 KeyGenerator kg = KeyGenerator.getInstance(algorithm); kg.init(sr); //生成密钥 SecretKey key = kg.generateKey(); //返回密钥的二进制形式 return key.getEncoded(); } catch (Exception e) { throw new Exception("没有这种加密算法"); } } /** *//** * 根据密钥对明文进行加密,返回密文 */ public static byte[] encrypt(byte[] plaintext, byte[] key) throws Exception { try { //产生一个可信任的随机数源 SecureRandom sr = new SecureRandom(); //从原始密钥数据创建DESKeySpec对象 DESKeySpec dks = new DESKeySpec(key); //创建一个密钥工厂,然后用它把DESKeySpec转换成Secret Key对象 SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm); SecretKey keySpec = keyFactory.generateSecret(dks); //Cipher对象实际完成加密操作 Cipher cipher = Cipher.getInstance(algorithm); //用密钥初始化Cipher对象 cipher.init(Cipher.ENCRYPT_MODE, keySpec, sr); //执行加密操作 byte[] cryptotext= cipher.doFinal(plaintext); return cryptotext; } catch (InvalidKeyException e) { throw new Exception("密钥非法"); } catch (NoSuchAlgorithmException e) { throw new Exception("没有这种加密算法"); } catch (BadPaddingException e) { throw new Exception("加密失败"); } } /** *//** * 根据密钥对密文进行加密,返回明文 */ public static byte[] decrypt(byte[] cryptotext, byte[] key) throws Exception {//上面与加密代码相同 cipher.init(Cipher.DECRYPT_MODE, keySpec, sr); //执行解密操作,下面与加密代码基本相同}
FileCipher类代码:
import java.io.*;import java.nio.*;import java.nio.channels.*;public class FileCipher { //明文 private static byte[] plaintext=null; //密文 private static byte[] cryptotext=null; //密钥 private static byte[] key; /** *//** * 从文件中读数据,返回byte型数组 */ private static byte[] readFile(String filename) throws Exception { try { File f = new File(filename); FileInputStream fs = new FileInputStream(f); FileChannel fc = fs.getChannel(); //只要文件大小不超过2G(int的范围)即可加密 int size = (int) fc.size(); //采用DirectBuffer的方式读文件数据,属于JDK1.4的API,处理大容量数据更快 ByteBuffer buffer=ByteBuffer.allocateDirect(size); //通过文件通道将文件内容读入ByteBuffer fc.read(buffer); //buffer操作完一次必须flip回到最初位置,才能再进行操作 buffer.flip(); byte[] byteArray=new byte[size]; //将缓冲区内容存入数组 buffer.get(byteArray); buffer.clear(); fc.close(); fs.close(); return byteArray; } catch (FileNotFoundException e) { throw new Exception("文件未找到"); } catch (IOException e) { throw new Exception("文件操作错误"); } } /** *//** * 将byte型数组内容写入文件 */ private static void writeFile(String filename,byte[] byteArray) throws Exception { //与读文件类似、省略 } /** *//** * 根据密钥对制定文件加密 */ public static void fileEncrypt(String filename,byte[] key) throws Exception { plaintext=readFile(filename); cryptotext=BytesCipher.encrypt(plaintext,key); writeFile(filename,cryptotext); } /** *//** * 根据密钥对指定文件解密 */ public static void fileDecrypt(String filename,byte[] key) throws Exception { cryptotext=readFile(filename); plaintext=BytesCipher.decrypt(cryptotext,key); writeFile(filename,plaintext); } /** *//** * 将得到的密钥保存到文件 */ public static void saveKey(String filename,byte[] key) throws Exception { writeFile(filename,key); } /** *//** * 从文件中读出密钥,返回byte数组形式 */ public static byte[] loadKey(String filename) throws Exception { key=readFile(filename); return key; }}
DESCipher类代码:
import java.io.*;public class DESCipher{ /** *//** * 打印命令的帮助信息 */ public static void printHelp() { //都是输出函数、省略 } public static void main(String[] args) { try{ //用户没有输入参数,则打印帮助 if(args.length==0) { printHelp(); return; } //用户输入参数个数不够,则提示用户,并打印帮助 if(args.length<3) key="BytesCipher.generateKey();" key2="FileCipher.loadKey(args[2]);" href="http://www.cnblogs.com/lzcarl/archive/2005/09/24/243471.html">http://www.cnblogs.com/lzcarl/archive/2005/09/24/243471.html)
Wednesday, June 28, 2006
Consultant opportuties in BJ
IBM,China is seeking for a Senior Consultant for Global Technology Service
which is located in Peking.
As a Senior Consultant you will be engaged in business critical projects for
clients, who include many of the leading Chinese
banking,telecommunication,industrial,government customers. The responsibility
of a consultant may include engaging as a member of the project team, ability
to lead and manage others as appropriate, assist in the specification of
deliverables, provision of estimates and plans and progress reporting;
building and maintaining the personal expertise needed to provide expert
support to agreed service with the client and play an active part in the
internal structure of the practice.
Job Requirements (skills/experiences)
The consultants will also have experiences with analyzing complex IT and
business problems and designing IT strategy and solutions to help the
customers to solve the problems and support their business growth. The
consultants are also expected to lead a team to engage and deliver complex
solutions and perform delivery management for complex projects.
Requirments
Bachelor Degree in IT Management or Computer Science
MBA preferred
The annual package is around 600k
Position 2
BEA company
Field Engineers – Telecommunications Products
Location: Beijing, China
Requirment
7-10 years telecommunications industry experience
6 years experience as an systems engineer, consultant with customer focus, or
equivalent experience
Position3
Lucent Company
Title: Software Engineering Manager - Telecommunications Technology Centre
Location: Beijing, China
REQUIREMENTS:
.MS/PhD Computer Science, Engineering, or MBA with a science BS; 6-8 years of commercial software development experience on preference
in telecom domain (Telecom operator, Telecom equipment supplier…etc) with at
least 3-4 years as project manager for a team more than 8-10 people;
Strong verbal and written English skills.
If u have interests, pls send me your updated resume asap.Thanks
Contact ways:
0086 010 85999792
msn: lily81_europe@hotmail.com
Thursday, May 11, 2006
POJO Handling in J2EE environment
Prerequisite: The object is statelss. (The object may have its own internal state, but does not maintain caller specific states.)
Example 1:
For POJO service facade implemented by Singleton, there is only one object instance of the facade class. For each user request, container will dispatch it to a thread picked from a thread pool. These threads will access this facade object instance concurrently. (Needs to be confirmed in WPS environment).
Example 2:
The default (MultiThreaded) mode of Servlet.
Case 2. Mutiple class instances to serve client requests.
Prerequistie: The object is stateful. And it is expensive to syncronize method access.
Example 1:
In SCM Sorter, since InterestLevelComparator is stateful object (to maintain cookie values), a new object instance is created per user request.
Example 2:
SingleThreaded model of Servlet. Servlet container may create multiple instances of the servlet class to serve multiple requests simultaneously.
Case 3. Partial/Whole Synchronization.
Prerequisite: The object is stateful. And it is expensive to create object instance per user request.
* Local variables: Each thread gets its own copy of the local variables, and changes made to these variables do not affect the copies of the local variables of other threads.
* Instance variables: there is only one copy of the instance variables per instance of the servlet, and all of the threads share this copy.
* Class variable: only one copy of a class variable exists across all the instances of the object
belonging to the class for which it is declared. Not surprisingly, just like instance variables, class
variables are not thread safe. In fact, class variables are unsafe even for the singlethreaded
model, because multiple threads may access the same class variable from different
servlet instances. Class variables are used to store “read-only,” or constant, data. Such data is
usually hard-coded in the class.
Pojo-based Middle Tier Vs. Thread Safe
In my consulting work, I've been asked exactly this same question: When you're talking about a web-tier interfacing with a co-located, POJO-based middle tier, what does it mean to be "thread safe"? When do you have to worry about concurrency?
A guiding principle to heed is "never share caller specific (aka request specific) state between threads". Local variables are one way of achieving this (for example, declared within a thread-safe method of a request handler or servlet). ThreadLocals are another. A third is use of stateless service collaborators, the subject of this blog.
When you're talking about a traditional stateless service object--which is typically what these POJOs business facades are--a single instance typically serves all client requests. While such a singleton service may have its own internal state, it doesn't manage caller-specific state. Everything it needs from callers it gets within a caller's local thread of execution via method parameters. In addition, the internal collaborators these shared services often deal with: data sources, caches, transaction managers, or other resources, are already thread safe themselves (or they sure as heck better be!) :-)
Hence, there is no need to worry about synchronization within your service facades unless you manage shared read/write state yourself (an exceptional case in my experience). There is also no value in service instance pooling: a singleton stateless service object can serve all clients, and can easily be scaled across a cluster. There is value in resource pooling, but that's typically already handled transparently for you, by good infrastructure providers (like jakarta common's dbcp, for database connection pooling).
So, in summary, there is often no need to create a new, local service object per request (e.g a one shot "command object") unless there is caller specific state that object needs to be initialized with (in cases where the command pattern makes sense.) In the case where the per-request Command pattern does make sense, you can easily implement this "one-shot command" in Spring by declaring a prototype bean definition, retrieving a new instance instantiated, configured, and wired by the Spring IoC container on a per-request basis.
How to make a program thread-safe
First method to make a program threadsafe: Avoidance
To ensure we have our own unique variable instance for each thread, we simply move the declaration of the variable from within the class to within the method using it. We have now changed our variable from an instance variable to a local variable. The difference is that, for each call to the method, a new variable is created; therefore, each thread has its own variable. Before, when the variable was an instance variable, the variable was shared for all threads processing that class instance. The following thread-safe code has a subtle, yet important, difference. This only applies to primitives. When it comes to actual Objects, the local variable does not make the program thread-safe since the variable just holding the reference to the unique object.
Second defense:Partial synchronization
Thread synchronization is an important technique to know, but not one you want to throw at a solution unless required. Anytime you synchronize blocks of code, you introduce bottlenecks into your system. When you synchronize a code block, you tell the JVM that only one thread may be within this synchronized block of code at a given moment. If we run a multithreaded application and a thread runs into a synchronized code block being executed by another thread, the second thread must wait until the first thread exits that block.
It is important to accurately identify which code block truly needs to be synchronized and to synchronize as little as possible. In our example, we assume that making our instance variable a local variable is not an option.
Third Defence: Whole synchronization
Here u should implement an interface which make the whole class a thread safe on or synchronized