We have a fairly complicated framework (made up of multiple plugins) that we've developed for all of our future Groovy/Grails applications. One aspect of this framework is the ability to retrieve user information from the various systems that we store this data in. Currently we have three classes that represent a user (one for LDAP (non AD), one for AD, and one for database). The reason for three separate classes is because they access totally disparate systems and are based on different base classes to provide various functionality need to access these systems. There's also dependencies, etc. that require this three class approach. One of these classes (the one for AD) is also used by Spring Security to represent a user. It is also possible to create any user object type from another user object type.
What I'm trying to create is a way for us to cache these objects. For example, during login, one class is always loaded (by Spring Security). However, throughout the process of using the application, another class (for database info for example) might get loaded temporarily. Ideally I'd like to cache these objects (that all represent the same user) so that we don't have to reload information.
In the end what I'm hoping to accomplish, is the ability to pass one user object (say AD) to another user class (say database) factory method, and have the database user class check if it has ever existed before for this user and if so, instead of recreating itself, just grab the cached copy. I'd rather not use a central cache to do all of this caching, but instead store the cached information in the actual objects (just seems cleaner that way).
What I can't figure out though is how to accomplish this (from a design perspective). So I'm looking for recommendation on which design patterns might help me to figure out an approach to creating this functionality.
P.S. Just in case it matters, all user classes extend different base classes, however, they all implement a shared interface.
Sounds like the appropriate caching at the various services that are responsible for looking up the related User instances would be the most appropriate approach. Using the Cache plugin would make this quite trivial.
Your factory method could delegate to the appropriate service method which would be annotated with the correct cache. Just keep in mind that you will need to invalidate items in the cache as well if they are subject to changes.
Related
We have a large application that allows the user to switch between different modules within the application. Each module needs to be able to save separately, so each module has it's own EntityManager.
There are some lookup tables, though, that we would like to use across the application. If we load the lookup tables at the application level, using a different EntityManager, they are not very usable then within the modules.
For example, if I want to load a 'Countries' lookup table at the application level, I then can't do something as simple as:
Person.Country = lookupDataContext.getCountry('Norway')
if Person is within a module's EntityManager. I will get something like:
"An Entity cannot be attached to an entity in another EntityManager. One of the two entities must be detached first."
Am I understanding BreezeJS correctly? If so, does that mean I need to have the Countries lookup within each module's EntityManager? This seems very limiting.
I believe this question is related to your other question about having multiple EntityManagers. Check out my general thoughts there which cover the scenario you describe here.
To be slightly more specific:
Breeze entities cannot navigate to related entities in a different EntityManager; that's what the error message is telling you.
You probably do want separate instances of the reference entities (such as Countries) in both managers.
You can easily copy any set of entities from one manager to another with export and import methods. You don't have to go back to the server.
Now, instead of a lookupDataContext, each sandbox datacontext can have a sandboxContext.lookups.countries method that delivers the appropriate entities from the proper sandbox manager.
Is this limiting? I don't think it's so bad as long as
you aren't duplicating an enormous amount of data across managers.
the reference entities are essentially immutable during a user session.
a user session doesn't keep too many sandbox managers alive at the same time
you dispose of or re-cycle the sandbox managers (and their datacontexts) when you're done with them.
You should be able to achieve your goal of loading lookups from the server once and managing them centrally in the master manager.
This approach has been very successful in a great number of applications over the last decade (pre-Breeze obviously).
HTH.
Having a bit of an issues on design, and was hoping I could ask for advice here. Accept that grails may be the completely wrong tool, but such is life.
So have been working away on a web app that basically just present a lot of information from a google spreadsheet and sends some updates back. I have managed to get most of it working but decided to rewrite it to get rid of my ridiculous spaggeti code as well as the many pieces of broken code that lays strewn throughout the project.
The system is relatively small, two-three users. The amount of data is small as well. One worksheets with max 500 rows (four columns) and another one with potentially 5000 (four columns). So all small, but I need it (well, want it) to stay in the google spreadsheet and the application feeding from there.
There are three classes I need for this to work,
Google authentication class keeps information on keys and tokens to speak to google
Google Spreadsheet class keeps information on the source spreadsheet
Google Data Entry keeps information from the two spreadsheets based on a unique id
So here is my question, what should I define these classes as. Thought I would use Domain classes, but then realised that these are stored in a database. Is there a way of keeping domain classes session dependent, I.E., that two users can use the same app on the same server but never see each others data and that the data is destroyed on logout. If not, is there some other class I can use that works similar to Domain class but kept in memory user/session specific.
I'm not really sure what exactly your requirements for those classes, but here are some thoughts anyway.
First, you may want to ask if they can't just be "normal" classes in src/groovy. I say "normal" here in the sense that they may just encapsulate some data and behavior, and you are responsible to create instances of them and call the methods appropriately when needed.
But, if you want to tie some data and behavior to the user session (as you seem to, because you asked for session dependent domain classes), you may want to use a Grails Service with session scope. When you do that, Grails will use a different instance of the service for each session of your application, and reuse the same instance for the same session until it ends.
You may also use a bit of each thing, using one service with session scope and have other classes representing the data that you pass around from the controllers to the service and vice-versa. These could actually be Command Objects if you needed validation and data binding, for example.
I’m working on a Grail’s project that has some Domain objects not persisted on the database. They are managed thru a REST API, so all their CRUD operations will be done with this API instead of the database.
The point is to still be able to use some interesting Grails plug-ins (like searching using Compass).
For instance, the administration the Domain objects Users is going to be managed with the REST API, so when the Users list is displayed a the REST method to retrieve the list of users will be invoked on the remote server. I hope this use case is clear enough :)
I can think on several ways to design that but I'm not sure what’s the best:
Should I create the Domain Objects in the controller (and delete the
previous Users stored in memory)?
It seems it’s possible to define a Domain Class not persistable (with
mapping I think) but I’m not sure if this is the best approach or
where to load the data.
It is better not to model as a Grails the User as Domain object?
Thanks in advance!
I would wrap the REST interactions in a service, and call the service from a controller. In that case, the service would get the response and create its objects, passing the list back to the controller. Controllers should just handle incoming requests, invoke application components, and return responses.
It seems you want models to represent the data in the other application, which is a good idea. Since you don't need GORM, you might want to define them in the 'groovy' folder of your app instead of the domain models folder. Then I think they will just be objects.
I'd go with non-domain objects in src folder - though, need to check if it's possible to use the mentioned plugins with them.
I wonder what domain class functionality you wish to get out of non-persistent classes?
I'd like to hear if anyone sees any problems with how I implemented the security in this Oracle based MVC.NET app, either security issues, concurrency issues or scalability issues.
First, I implemented a CustomOracleMembershipProvider to handle the database interface to the membership store.
I implemented a custom Principal named User which implements IPrincipal, and it has a hashtable of Roles.
I also created a separate class named AuthCache which has a simple cache for User objects. Its purpose is simple to avoid return trips to the database, while decoupling the caching from either the web layer or the data layer. (So I can share the cache between MVC.NET, WCF, etc.)
The MVC.NET stock MembershipService uses the CustomOracleMembershipProvider (configured in web.config), and both MembershipService and FormsService share access to the singleton AuthCache.
My AccountController.LogOn() method:
1) Validates the user via the MembershipService.Validate() method, also loads the roles into the User.Roles container and then caches the User in AuthCache.
2) Signs the user into the Web context via FormsService.SignIn() which accesses the AuthCache (not the database) to get the User, sets HttpContext.Current.User to the cached User Principal.
In global.asax.cs, Application_AuthenticateRequest() is implemented. It decrypts the FormsAuthenticationTicket, accesses the AuthCache by the ticket.Name (Username) and sets the Principal by setting Context.User = user from the AuthCache.
So in short, all these classes share the AuthCache, and I have, for thread synchronization, a lock() in the cache store method. No lock in the read method.
The custom membership provider doesn't know about the cache, the MembershipService doesn't know about any HttpContext (so could be used outside of a web app), and the FormsService doesn't use any custom methods besides accessing the AuthCache to set the Context.User for the initial login, so it isn't dependent on a specific membership provider.
The main thing I see now is that the AuthCache will be sharing a User object if a user logs in from multiple sessions. So I may have to change the key from just UserId to something else (maybe using something in the FormsAuthenticationTicket for the key?).
Why use a Hashtable for the roles? A plain list would likely be faster to search unless you expect people to have more than a handful of roles. If you can predict all roles in advance then using a bitmask/flags enumeration would be even better.
You should try to avoid writing your own locking mechanism, as it's fairly easy to get wrong. Use the new System.Collections.Concurrent classes, or if you must roll your own then be sure to use Interlocked (as all the other locking mechanisms are quite expensive).
Caching should use WeakReference encapsulation to allow entries to be GCed and support retrieving user information from the database if an entry is missing. Maybe have a look at Velocity if you need a distributed cache.
Sharing user objects might not be a problem, but is probably not a recommended strategy. Many database access frameworks will track objects retrieved in a session or unit of work, and sharing objects across sessions would then be problematic. If you do go for sharing user objects then be sure to make them immutable.
Last, I personally despise the whole Membership Provider API, because it uses GUIDs for identification and the default SQL Server database design for user profiles is just horrible (aka performance killer). This does not seem to be a concern for you as you've rolled your own (db and implementation) but you might want to evaluate whether there are any real benefits involved from implementing the API, or whether it's mostly shackles tying you to specific ways of doing things.
Problem: Our web console shows a list of all computers on which our application is installed. Each machine has some identification information that can be associated with it. Simple strings like department name, team name etc. We need to make it such that the user can change the name of these identification fields and add/remove as many as he wants. How can we best implement this?
Initially i thought that i could implement this as a singleton. In the application start, i could read the last set identity field names from the db and create a singleton instance of a list of strings. This could be passed around to all functions that need to display or access the identity information. The appeal in this option is that if the user changes the identity fields name from the ui or adds or removes the fields, i can simple modify the singleton object and the change will be reflected.
However i feel there must be a better way to achieve what i want. Because there a lot of such information that the user can modify at will and we need to track them.
Any suggestions?
Just use the objects from your ORM to maintain and use this information in the application. Many ORMs have the ability to cache this sort of thing, so it's not like you will lose any speed over it.
I'm not a big fan of using a Singleton to do this. It's hard to unit test, and you'll still have to persist it to the database eventually.