Store result into cache in Play 2.2 - caching

In Play framework 2.2 is very simple to create an result of the current request. We type just:
Ok(views.html.default.render())
And then to make it work is enough to wrap it by Action, so the final code looks like:
def index = Action {
Ok(views.html.default.render())
}
That is fine. But now, I want to store the response in cache to make it more scalable. I use EHCache. The issue is, that when I store it into cache, it throws
NotSerializableException: play.api.mvc.ActionBuilder$$anon$1
I tried to cache at least the result it self, but it throws
ERROR net.sf.ehcache.store.disk.DiskStorageFactory Disk Write of result-key failed:
java.io.NotSerializableException: play.api.libs.iteratee.Enumerator$$anon$18
I know, that the values are stored in the cache, but only in a memory, which might be very insufficient considering really high load and many distinct responses.
Question:
So my question is whether there is any way how to fully cache Play actions/results, including proper serialization?
Edit:
How I try to use the cache: I do not use Cached {} because it doesn't behave exactly how I need, so I try to designed it in my own way. So just for the testing purposes I use it more verbosely by now:
Cache.set("myaction", Action {
Ok(views.html.default.render())
})
or
Cache.set("myresponse", Ok(views.html.default.render()))
But both of these produces exceptions mentioned above.
About the cache: The Play cache API is not sufficient to me, so I extended it by another couple methods together with new plugin implementation. At first I tried to just copy default plugin and implement those extensions but there were some issues, so I fixed them is recommended here. It is the plugin fix. Since then it seems that it actually uses the EHCache (guessing from those exceptions).

It seems to me that you are not trying to store the results in the cache but the action, which then contains a closure that cannot be serialized, I guess this is not what you want to do anyways, I guess this is because you are using EHCache directly?
If you use the Play cache API it should help you do the right thing. You can find the docs for it here: http://www.playframework.com/documentation/2.2.x/ScalaCache
The response may still not be serializable though, if you really want a cache that serializes to disk you should be able to cache the HTML generated by the template as it is basically a string, and then re-use that but create a new response for every request.
(My gut feeling is that you would probably get better performance from rendering the template every time than the cache reading it from disk unless you have some really crazy complex templates)

Not sure it is suitable for 2.2, however according to this issue I reported
if you're calling set method directly from an implementation of CacheApi and the implementation expects a serializable object, use this wrapper which is also used by the #cached helper.

Related

YARN Rest API: XML as default

Is there a way to change the default response format for GET requests like /ws/v1/cluster/info to be XML?
I know that I can specify the Accept: application/xmlheader with my request. However I want to change the default value so that I can omit the header.
From my reading of the Yarn source code, the distinction between JSON and XML is completely delegated to the underlying JAX-RS infrastructure, with annotations like
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
all over the code. This mechanism (called "Static Content Negotiation") specifies that the first in the list is the default, which is consistent with behavior. One could use the javax.ws.rs.core.Variant class (and a technique called "Runtime Content Negotiation") to override this, but I can't find any use of it in the codebase.
If you're willing to make a small modification to the source and rebuild it, you could simply find all of these #Produces declarations and swap the order. If you decide to do this, you'll want to be mindful of the apparent bug described here. If it turns out to still be relevant (and it was recent), you may find you have to tackle all the complexity of runtime content negotiation anyway.
It should be simple enough to try it out, but if you don't have any other reason to build from sources it's probably overkill.

Which is the most efficient way to access the value of a control?

Of the two choices I have to access the value of a control which is the most efficient?
getComponent("ControlName").getValue();
or
dataSource.getItemValue("FieldName");
I find that on occasion the getComponent does not seem to return the current value, but accessing the dataSource seems to be more reliable. So does it make much difference from a performance perspective which one is used?
The dataSource.getValue seems to work everywhere that I have tried it. However, when working with rowData I still seem to need to do a rowData.getColumnValue("Something"). rowData.getValue("Something") fails.
Neither. The fastest syntax is dataSource.getValue ("FieldName"). The getItemValue method is only reliable on the document data source, whereas the getValue method is not only also available on view entries accessed via a view data source (although in that context you would pass it the programmatic name of a view column, which is not necessarily the same name as a field), but will also be available on any custom data sources that you develop or install (e.g. third-party extension libraries). Furthermore, it does automatic type conversion that you'd have to do yourself if you used getItemValue instead.
Even on very simple pages, dataSource.getValue ("FieldName") is 5 times as fast as getComponent ("id").getValue (), because, as Fredrik mentions, first it has to find the component, and then ask it what the value is... which, behind the scenes, just asks the data source anyway. So it will always be faster to just ask the data source yourself.
NOTE: the corresponding write method is dataSource.setValue ("FieldName", "NewValue"), not dataSource.replaceItemValue ("FieldName", "NewValue"). Both will work, but setValue also does the same type conversion that getValue does, so you can pass it data that doesn't strictly conform to the old Domino Java API and it usually just figures out what the value needs to be converted to in order to be "safe" for Domino to store.
I would say that the most efficient way is to get the value directly from the datasource.
Because if you use getComponent("ControlName").getValue(); you will do a get on the component first and then a getValue from that. So do a single get from the datasource is more efficient if you ask me.

Store a class instance in session server side w/ Padrino?

I have a class that reads from a DB on startup. I'd prefer to be able to store it in the session, but I get the following error when trying to do so:
ERROR TypeError: no marshal_dump is defined for class Mutex
Is what I'm doing possible/reasonable? If so how should I go about doing it? If not, whats a good alternative to storing the class instance in the session? Currently my workaround is just instantiating it whenever I need to use it, but that doesn't strike me as a good solution or one that will be able to scale.
A good alternative is to store the id of the record in the session. Then when you need that data again you'd use a helper to return the data either from memory or from the database. A perfect example is the pattern used in current_user helper methods found in many ruby authentication gems. You could modify this helper to use a cache layer if you find it to be a bottleneck, but I'd leave that as an optimization after the fact.
Issues of having to get the object into a marshaled format that will live happily in a session, there are issues with storage space, stale data and possibly unintentional exposure to confidential data.

What gotcha's exist when working with transient in Clojure 1.3?

I'm looking into techniques to speed up my application and I'm trying out Transients. I know I'm supposed to treat them with some caution, but what are the kinds of issues that arise?
Any advice would be appreciated!
Use transients like the usual persistent data structures - that is, always use the return value from a mutator instead of the structure you called the mutator on. However, don't trust that the old version stays the same, and don't access transients from other threads.

Symfony filter to run before and possibly skip the controller

The idea of the desired filter is to check the memcached for page content with url as a key and if found, return it to client directly from cache and skip the controller altogether. Storing would be done in separate filter, which is the easy part. I'm aware i could write it to action's preExecute() but filters would offer more elegant solution (could turn them off for dev envs).
In other words - is there a smart way for a filter to push the response to client and skip going to action?
Implementing such a filter is quite easy. Actually similar solution exists in symfony.
Look at the default caching filter (sfCacheFilter class). It's doing something similar to what you're looking for.
Alternative path
It is already possible to use memcache directly by changing the default file caching to memcache.
In your factories file you're able to switch cache driver (apps/yourapp/config/factories.yml or config/factories.yml):
all:
view_cache:
class: sfMemcacheCache
You could do the same with memcached but as symfony doesn't provide sfMemcachedCache class you would have to implement it on your own.
This way you could reuse existing caching framework and take advantage of cache.yml files.
I would suggest you have a look at overwriting the sfExecutionFilter.
It's the last filter in the default filters.yml, which means it's the first executed.
This is what is responsible for calling your action's executeXXX method and loading associated view and bunch of other things.
Presumably you could write your own filter the extends sfExecutionFilter and overwrite it's functionality to skip executing the controller it the output is cached.
You can find the default filters.yml # %SYMFONY_DIR%/config/config/filters.yml

Resources