In grails 3, the default service scope is Singleton, the documents show it's easy to override this by defining
static scope='request'
in the service class. Is it possible to change the default service scope for an application similar to the way it is done for controllers in application.groovy?
The specific issue is a Service class in a plugin is calling application services (which are designed around request scope). This was working in grails 2, but with the upgrade to grails 3 it no longer does.
Is it possible to change the default scope for an application similar
to the way it is done for controllers in application.groovy?
There is no direct support for that, no. You could write a bean definition post processor that could impose that change.
Related
Reading form this http://docs.grails.org/3.3.10/ref/Services/scope.html
and By default services are "singleton",
So Does Grails automatically lock/Synchronize the service object if the scope is a singleton?
in case many requests using the same service a
Please advise
By default services are "singleton",
So Does Grails automatically lock/Synchronize the service object if
the scope is a singleton?
No. Grails configures Spring to create a single instance of your service and inject that instance everywhere it needs to be injected. In general services don't need to be synchronized if they are stateless but if you are doing something that calls for synchronization, do that.
My question is not only if action classes can be scoped to singleton, but I also want to know which are the best practices. Both in context of Struts2 and Spring. Best scope of VIEW (say request or session), for controller and model.
Struts2 Actions are managed by the Struts Container. They are ThreadLocal, hence every request has its own thread-safe copy of the Action.
If you use Spring to handle them through the Struts2-Spring-plugin, there are multiple levels of usage:
you can let the Struts container instantiate them, and handle them through Spring for the Dependency Injection, or
you can let Spring take over control and be fully responsible for the whole lifecycle of every Action. In this second case:
if you declare an action as a bean in a Spring XML configuration file, the action will get the default Spring scope, that is Singleton (scope="singleton"). THIS IS DANGEROUS, USELESS, and 99.99% of the times NOT WHAT YOU WANT, because you will lose a fundamental part of the framework capability, actions will be turned into kind-of servlets, thread-UNsafe, and many problems will arise;
to prevent that, you can put the scope="prototype" in the bean declaration, that will let Spring instantiate the action without affecting its nature.
If you are inside a container Java EE 6+ compliant (for example, Jboss 7, Wildfly 8, TomEE 1.7, Glassfish 3+, ecc...), the Contexts and the Dependency Injections are handled through CDI. If you want, you can use the Struts2-CDI-plugin to allow CDI to handle your actions and inject dependencies through the #Inject annotation (instead of the #Autowired one)
I've used Spring a lot in the past, then after discovering CDI and the CDI plugin, I've switched and never looked back, so I vote for the n.3
I started looking into Microsoft.Framework.DependencyInjection / Microsoft.Extensions.DependencyInjection (renamed post-beta 8) for usage in my own framework based on the MVC-paradigm.
For this I per request have 3 scoped levels in which I'm trying to use the new Microsoft DI. A shared root scope for my the entire application, a nested scope for every controller and a further nested scope for every view.
Even though this scoping works for resolving services from the root, I have no idea on how to inject services into the lower scopes. I want to be able to inject specific services for my controllers/views per request which are used during the lifetime of the request and then discarded.
The possibilities I've explored are IServiceScopeFactory and CreateScope, but that only gives me a read-only IServiceProvider. Other than that there's AddScoped but that just returns the original ServiceCollection.
Am still looking for a way to create the root containers, register its services for the entire application and then the ability to create a scope and register scoped only available in that scope (and its parents).
Any ideas on how to achieve this? The documentation for the Microsoft DI is scarce so far.
Is it possible to use the Grails Cache plugin's annotations (ie: #Cacheable) on methods in normal Groovy classes? The plugin's documentation doesn't mention anything about normal Groovy classes and based on my own tests the annotations have no effect when used in a normal class. So I'm just wondering if there's a way to get the annotations to work in a normal Groovy class.
The current alternative is to simply directly access the cache in the method via the Cache Manager bean, but it would be nice to use the annotations instead.
No, the annotation only works on services and controllers. The plugin detects the annotation and creates a proxy for the service which intercepts all method calls and does the cache-related work first. So if there is a value in the cache for that method, it won't bother calling your real method but return the cached value instead. But if it's not cached, it will call your method and use its return value, but cache that for later.
This works because you have to retrieve the service from the Spring ApplicationContext (or have Grails do that for you) and this gives Spring a chance to give you the proxy instead of the real implementation instance, but there's no way for Spring to know about access to regular Groovy classes without AOP or some other more invasive solution.
Having said that, the plugin is probably being overly strict in limiting to only controllers and services. It handles controllers specially because those involve caching web requests instead of method return values, but there shouldn't be much difference between a Grails service and any other annotated Spring bean as far as caching goes. You can add your own Spring beans, either manually in grails-app/conf/spring/resources.groovy or by adding them to the grails.spring.bean.packages list in Config.groovy, so the plugin should be updated to look for all annotated classes. You can request this in the plugin's JIRA at https://jira.grails.org/browse/GPCACHE
Imagine two Grails applications which share a domain class. Maybe a Book domain class.
One application is identified as the owner of the data, one will have to access the domain data. Something like amazon and the amazon web services.
I guess it is trivial that the owning application will use a normal domain class and will expose the data through web services - no problem in grails.
But what would be best practice to implement the domain in the other application?
use a service to access the remote domain and not implement a local domain class at all?
implement a local domain class, overwrite the get()-method in order to fetch the remote data and use the local database as cache?
what other solution comes to your mind?
Ryan Geyer has a very interesting article Modularizing your Grails application domain classes which lists 3 solutions to this problem:
As a RESTful JSON Service - easy to get this setup in Grails but then you lose the automatic GORM functionality.
Separate out the domain classes into a library JAR file and reference that library in both of my other applications. This is not as easy as it first sounds
Create a Grails plugin. Put the domain object in the plugin. Each of your applications can then import this plugin. You can then create different controllers with different functionality as required. The sample code for this is available at:
git clone git://ec2.nslms.com/grails/blog_example_modular
Ted Naleid gives a great tip later in the post and recommends...
"create a grails-app/conf/BuildConfig.groovy file and put the plugin name and path to the source in it. ... If you do this, your applications will see the live changes to your domain/controller/service/etc classes as if they were actually in current app and there isn't any need to repackage and reinstall the plugin when you make changes."
Using memcache should enable both applications to have a consistent view of the data and would avoid each individual application having it's own inconsistent cache.
I think you can make JAR file of your domain classes and add reference to other grails application .
Found another interesting solution:
Riak is a key/value database with a first class REST API. There is a grails plugin for riak which maps most of the GORM functionality (relations, dynamic finders etc) to the REST API of riak: http://grails.org/plugin/riak
Now comes the part which I haven't tested yet: if you make use of the DataSources feature of grails 2.0, it should be possible to only connect those "remote" domains to a riak database.
As a result, there would be a domain stored in a riak database and several applications would be able to access it via a clean REST API without effort.
OK. This also show how silly my question is - it would be the same if you connect several apps through the same SQL-database. But sometimes people want to have something more funky like webservices.