I am using spring caching in my project using annotations. Based on profile I am using Elasticache and SimpleCacheManager. The annotations used are
//For the initial configuration settings in some class when profile is cloud.
#EnableElastiCache({#CacheClusterConfig(name = "MyCache", expiration = 86400)})
// For the initial configuration settings in some class when profile is non-cloud.
SimpleCacheManager simpleCacheManager = new SimpleCacheManager();
simpleCacheManager.setCaches(newArrayList(new ConcurrentMapCache("MyCache")));
#CacheConfig(cacheNames = {"MyCache"})
public class CachingRequiredClass{
........
#Cacheable
public String blablaMethod(String id){
.....
}
}
public class SomeOtherClass{
......
#Caching(evict={
#CacheEvict(value="MyCache", key="T(com.myclass).myMethod()+':blablaMethod()'"),
#CacheEvict(value="MyCache", key="T(com.myclass).myMethod()+':blablaMethod()+':blablabla2Method()'")
})
public void logout(){
......
}
}
I am forced to hard code cache name "MyCache" everywhere which I dont like. Is there a way to make this configurable. Somehow coming from a property file??
You have several options.
First of all, it is Java so you can create a constant somewhere and refer to it. Then those places allow for SpEL so you can write ${myCache} and have a myCache property in the environment that has the value of your cache.
Finally, rather than specifying the cache names in code (be it using SpEL or not) you can implement CacheResolver and decide which cache to use programmatically. It's more work and probably overkill if you don't need to change the cache to use according to some business logic.
Part of the smell it annoys you is that you are maybe using the same cache for too many things. That key attribute in your last example looks mental to me: if you need to add the name of the class and the method to the key, it tells me you're trying to put way too many things in the same cache. You shouldn't design your cache like that: do not forget it is just a shortcut so that you don't have to do this manually. If you want to query the cache for a value, are you seriously going to use the name of the class and the method to compute the key?
Related
I'm looking for a way of condensing some of my AS3 code to avoid almost duplicate commands.
The issue is that I have multiple variables with almost the same name e.g. frenchLanguage, englishLanguage, germanLanguage, spanishLanguage
My Controller class contains public static variables (these are accessed across multiple classes) and I need a way to be able to call a few of these variables dynamically. If the variables are in the class you are calling them from you can do this to access them dynamically:
this["spanish"+"Language"]
In AS3 it's not possible to write something like:
Controller.this["spanish"+"Language"]
Is there any way to achieve this? Although everything is working I want to be able to keep my code as minimal as possible.
It is possible to access public static properties of a class this way (assuming the class name is Controller as in your example:
Controller['propertyName']
I'm not sure how this helps to have "minimal code", but this would be a different topic/question, which might need some more details on what you want to achive.
Having said that, I like the approach DodgerThud suggests in the comments of grouping similar values in a (dynamic) Object or Dictonary and give it a proper name.
Keep in mind, that if the string you pass in as the key to the class or dynamic object is created from (textual) user input you should have some checks for the validity of that data, otherwise your programm might crash or expose other fields to the user.
It would make sense to utilize a Dictionary object for a set of variables inherited: it provides a solid logic and it happens to work...
I do not think this is what you are trying to accomplish. I may be wrong.
Classes in AS3 are always wrapped within a package - this is true whether you have compiled from Flash, Flex, Air, or any other...
Don't let Adobe confuse you. This was only done in AS3 to use Java-Based conventions. Regardless, a loosely typed language is often misunderstood, unfortunately. So:
this["SuperObject"]["SubObject"]["ObjectsMethod"][ObjectsMethodsVariable"](args..);
... is technically reliable because the compiler avoids dot notation but at runtime it will collect a lot of unnecessary data to maintain those types of calls.
If efficiency becomes an issue..
Use:
package packages {
import flash.*.*:
class This implements ISpecialInterface {
// Data Objects and Function Model
// for This Class
}
package packages {
import...
class ISpecialInterface extends IEventDispatcher
In one of my extbase models, I want to initialize some properties derived from the properties that are saved in the database. The computation of these virtual properties is time consuming, so I'd like to cache them. Thus my program flow should look somehow like this:
Load the domain object as usual from the database
Check if the virtual property is available in cache. If so, fetch it from there, otherwise compute and cache it.
I first thought the method "initializeObject" is what I need, but it is not: It is called before any property is initialized from the database. So I came up with two other ways:
I can call an initialization-method manually from the repository after fetching the object, but that seems weird and would break if someone adds another find* method to the general repository.
Another idea is to add a boolean "virtualPropertiesInitialized" to the model, query it whenever one of the virtual properties is accessed and initialize the virtual properties if needed. Also seems weird, but would not break if someone adds another "find"-method to the generic repository.
My question is:
Is there a default/best-practice how to do what I want to do?
If reading the final value from disk or database is less computationally intensive, then store the value using the TYPO3 caching framework or by your own caching method of a static class and restore it in the getter of the virtual property. Doing it in the getter method public mixed getYourPropery() will give you the feature that the value is only get from the cache when you call it.
On the second call, just return the value you stored previously:
private $myValue = NULL;
public function getMyValue() {
if($this->myValue != NULL) return $this->myValue;
$this->myValue = "test";
return $this->myValue;
}
I am trying to implement a distributed cache with spring-memcached. The docs suggest that
to use an object as the key I need to have a method in my domain class with #CacheKeyMethod
annotation on it.
But the problem is I am using the same domain class in different scenarios and the key to be generated in each case has different logic. For examples for a User class one of the scenarios requires the key to be unique in terms of city and gender and but in the other case it requires to be unique in terms of the user's email, it's essentially what your lookup is based on.
Although a user's email would determine the city and gender, so I can use email as the key in first case as well but that would mean separate cache entries for each user while the cached data would be same as long as the gender and city are same, which is expected to increase the hit ratio by a huge margin(just think how many users you can expect to be males from bangalore).
Is there a way I could define different keys. Also it would be great if the logic of
generating the key could be externalised from the domain class itself.
I read the docs and figured out that something called CacheKeyBuilder and/or CacheKeyBuilderImpl could do the trick but I couldn't understand how to proceed.
Edit..
ok.. I got one clue! What CacheKeyBuliderImpl does is, it calls the generateKey method on defaultKeyProvider instance which looks for #cachekeyannotation on the provided domain class's methods and executes the method found to obtain the key.
So replacing either the CacheKeyBuilderImpl with custom Impl or replacing KeyProvider's default implementation within CacheKeyBuilderImpl with yours might do the trick... but the keyprovider reference is hardwired to DefaultKeyProvider.
Can anybody help me implement CacheKeyBuilder(with respect to what different methods do;the documentation doesn't clarify it) and also how do I inject it to be used instead of ususal CacheKeyBuilderImpl
Simple Spring Memcached (SSM) hasn't be designed to allow such low level customization. As you wrote one of way is to replace CacheKeyBuilderImpl with own implementation. The default implementation is hardwired but it can be easily replaces using custom simplesm-context.xml configuration.
As I understand your question, you want to cache your User objects under different keys depends on use case. It's supported out of the box because by default SSM uses method argument to generate cache key not the result.
Example:
#ReadThroughMultiCache(namespace = "userslist.cityandgenre", expiration = 3600
public List<User> getByCityAndGenre(#ParameterValueKeyProvider(order = 0) String city, #ParameterValueKeyProvider(order = 1) String genre) {
// implementation
}
#ReadThroughSingleCache(namespace = "users", expiration = 3600)
public User getByEmail(#ParameterValueKeyProvider String email) {
// implementation
}
In general the #CacheKeyMethod is only used to generate cache key if object that contains the method is passed as a parameter to the method and the parameter is annotated by #ParameterValueKeyProvider
I'm trying to figure out to create a behavior that will copy a boolean site configuration value to an output model.
This way I don't have to copy the bool in each action who's view requires it, but can simply add the behavior to the controller actions that need this value.
In some of the older versions of FubuMVC, I believe behaviors could modify the output model after it's left the controller. But I'm not sure how to do this in the more recent versions of FubuMVC (or I've forgotten).
Can anyone give me an example of or point me in the direction of the best practice for copying a site configuration value to an output model?
Let's say I had an output model called HomeViewModel that had a property called FooterText that I wanted loaded from settings object (let's say HomeSettings) that was retrieved from the container (i.e. StructureMap).
The Behavior
My behavior would look something like this:
public class HomeFooterBehavior : BasicBehavior
{
private readonly HomeSettings _settings;
private readonly IFubuRequest _request;
public HomeFooterBehavior(HomeSettings settings, IFubuRequest request)
: base(PartialBehavior.Executes)
{
_settings = settings;
_request = request;
}
protected override DoNext performInvoke()
{
SetupFooter();
return DoNext.Continue;
}
public void SetupFooter()
{
var viewModel = _request.Find<HomeViewModel>().First();
viewModel.HomeFooterText = _settings.FooterText;
}
}
This behavior takes in the HomeSettings object and the IFubuRequest object (both injected dependencies) and then gets the HomeViewModel (output model) from the request and then sets the HomeFooterText property on the output model based on the value from the settings object.
NOTE: I'm assuming that you've already got your HomeSettings object wired up in the container (for example, using the ISettingsProvider stuff built into FubuMVC). If you don't already have this, let me know and I can post some code on how to do that.
Wiring Up The Convention
To wire up the behavior, you'll need to define the convention through an IConfigurationAction, for example:
public class HomeFooterBehaviorConfiguration : IConfigurationAction
{
public void Configure(BehaviorGraph graph)
{
graph.Actions()
.Where(x => x.HasOutput &&
x.OutputType().Equals(typeof(HomeViewModel)))
.Each(x => x.AddAfter(Wrapper.For<HomeFooterBehavior>()));
}
}
This is a real dumb convention for demonstration purposes. In your project, you might make it a little more generic. For example, any output model that has an attribute on it, or implements a specific interface, etc. In fact, you might want to inspect all output models to see if they contain any properties that match a certain criteria (for example, all properties that end with "Settings" - like "FooterSettings" or something).
Don't be afraid to define wide sweeping conventions like this due to performance concerns since all this convention code runs at start-up time and not on every request.
Note the "AddAfter" call and the "Wrapper.For" call. That's the key in that it places your behavior after the controller action is executed, but before the view is rendered.
Now that you have your behavior and your convention defined, it's time to wire it up in your FubuRegistry.
Wiring Up Your Convention in your FubuRegistry
After the call to "Routes." in your FubuRegistry, add a line like this:
ApplyConvention<HomeFooterBehaviorConfiguration>();
Recompile and it should work.
Please let me know if you run into any problems.
I have 2 databases that my site uses including a central user database that relates to other site-specific databases.
Sometimes it is adequate to call new User(array('db'=>'adapter1')); (but never convenient); other times, though, such as when declaring relationships between tables on different databases, there is no way to do this.
Does anyone know a way to specify which database adapter to use from within the Zend_Db_Table_Abstract class?
Thanks!
Getting back to this pretty late, but none of the answers here quite did it for me. A select few of my database models needed to use 'tdb' and the following code was added to each of those classes to have that happen automatically:
protected function _setupDatabaseAdapter()
{
$this->_db = Zend_Registry::get('tdb');
parent::_setupDatabaseAdapter();
}
I thank you all for your suggestions along the way!
Zend_Db_Table_Abstract provides a static method to set the default database adapter. Do this as follows:
Zend_Db_Table_Abstract::setDefaultAdapter($adapter);
Now, all your Table objects will use your adapter by default.
Note: the online docs sometimes don't make this obvious, so your second best place to check is in the API here: http://framework.zend.com/apidoc/core/
You could set the class variable $_db to the correct adapter in the constructor.
global $adapter1; //There are better ways than using a global variable
$this->_db = $adapter1;
Assuming the adapter object can be referenced in the constructor. That doesn't seem to portable, but I believe it would work.
The init function can be used, it is not used in Zend_Db_Adapter_Abstract, can be used in your class to setup whatever needs to be done. _setAdapter accepts a string naming a Registry Key.
public function init()
{
$this->_setAdapter('tdb');
}