Common place to add methods - grails

I am a newbie to Grails and still learning the ropes! The application that i work on uses services.
My task is to add a new method in one of the services and have it get called from clients.
This new method is going to be pretty long and i don't want all the method body to be in the service class.
I would like to add another method in a place other than this service to do all the calculations for this new method.
Which is the best place to add a method like that? Should i add a new domain? Or just a controller class?
I don't want any of the information in the new method to be saved to database.
A sample code look like this:
class MyService {
String getDomainName(String ID) {
return domainNameGenerator(ID);
}
}
Now i want to put the domainNameGenerator method into another place.

Place your standalone code in src/groovy or src/java depending on the actual language of your code, but there's nothing wrong with putting code in the service class itself. If the new class and the service package is the same, you don't even have to add an import.

Related

Shorten Controller method in MVC

So I am writing an ASP.NET Core MVC application where users should be able to upload an Excel file, when a file gets uploaded I need to read the uploaded file an create a Model of the data inside the file.
I am currently creating this model in my Controller method but this made my method quite long.
My current solution is creating a class inside my Controller which deals with creating a model from an Excel file but I feel like this is the wrong way to do it.
So my question is: What is the right place to put the code that reads my excel file and puts it inside a model?
You should create a new .NET Standard library and create there the class that builds the model.
The recommended way is to use the class as an implementation and an interface (IExcelModelBuilder) that exposes all the public methods of that class (ExcelModelBuilder). This way you can inject this service into your controller constructor and, as a bonus, you can easily unit test it too.
You can read more about Dependency Injection in .NET Core.
You can register the service in your startup file:
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
{...}
services.AddTransient<IExcelModelBuilder, ExcelModelBuilder>();
}
Step 1:Create a new .NET Standard library (Services)
Step 2:Add the reference into the mvc application of that library.
Step 3:Step two create a class that will be dealing with all the stuff like that if you have a limited number of tasks to perform ,
but if you want to separate it and wants a generic solution then Create an Interface (IUpload) and then implement all its methods in a class (Upload).also register the service in your startup file:

Where to put object-cache in Grails?

I want to use some caching from the Guava-library in my Grails app. Is a service class with a non-static field and some getter the best place to put this cache into? Or should it be static or declared somewhere else?
Basic Example:
class TestService {
def getCachedValue(Test test) {
return testCache.get(test)
}
def testCache = new CacheBuilder()
.maximumSize(2000)
.weakKeys()
.weakValues()
.expireAfterWrite(30, TimeUnit.SECONDS)
.build(
new CacheLoader<Test, Date>() {
...
Using a service is the best idea for this. However, making it static is a bit unnecessary since by default services are singletons.
The fact a service is a singleton, and is exposed to not only your controllers but other artifacts within your Grails application make it a perfect fit for accessing an object cache. A single point of access.

ZF2 override framework classes via autoloader classmap

Is it possible to override the class file location of a framework class via classmap and autoloader? If yes, then how?
Example: I want to override Zend\Form\Fieldset, so that everywhere in the framework where Zend\Form\Fieldset is referenced, I want it to use my own class file instead of the original.
Motivation: When updating the framework, I want to keep my modifications safe from getting overwritten.
Known alternative: Modify the code in the framework.
Disadvantage: Modification gets lost when updating the framework.
writing the same class (FQCN) at another location is generally a bad idea. This causes two classes which are equally named to live in two separate locations. It's a much better idea to create your own Fielset in your own namespace. Say, Application\Form\Fieldset.
You can extend the ZF2 fieldset by your own. Then reference this new fieldset class and its all much more maintainable.
The downside of this method is you don't automatically use the new fieldset class. You have to reference the Application\Form namespace in every form you use. On the other hand, this makes it much more clear to other users of you code what exactly happens: there are no unexpected consequences using ZF2 code.
The only remark I have to make here is, for what do you need another fieldset? If you think you need that for view helpers, that's not true. You can modify the view helper to render fieldsets without modifying the Fieldset form class itself.

Symfony2 dependencies in class

I try to create a class to manage some part of my app
but I need to access the configuration in resources/config.yml
I tryed to extends my class with containerAware as a controler
But he container is not set...
I would like to be able to do something like that:
class MyClass extends ContainerAware
{
public function myFunciton()
{
$em = $this->get('Doctrine')->getEntityManager();
}
}
any suggestion is welcome
Extending ContainerAware does not automatically grant access to the service container - you would need to inject the container into your class. There are two ways to do that:
If your class is registered as a service, you can inject #service_container
If your class is not a service, but is being accessed from a class that does have access to the container (like a controller), you can explicitly call setContainer()
That being said, you should not inject the container into your classes. This makes it harder to test your classes. There are a few exceptions to this, but they don't come up often.
Instead, you should only inject services you need. In the case of the entity manager, you would inject #doctrine.orm.default_entity_manager.
In regards to accessing data from a config.yml, I would suggest including the file (which can be done when defining a service) and parsing the yml using either Symfony\Component\Yaml\Parser or Symfony\Component\Yaml\Yaml. The parsers converts a yml string to a PHP variable that you can then easily work with.

How to avoid having injector.createInstance() all over the place when using guice?

There's something I just don't get about guice: According to what I've read so far, I'm supposed to use the Injector only in my bootstrapping class (in a standalone application this would typically be in the main() method), like in the example below (taken from the guice documentation):
public static void main(String[] args) {
/*
* Guice.createInjector() takes your Modules, and returns a new Injector
* instance. Most applications will call this method exactly once, in their
* main() method.
*/
Injector injector = Guice.createInjector(new BillingModule());
/*
* Now that we've got the injector, we can build objects.
*/
RealBillingService billingService = injector.getInstance(RealBillingService.class);
...
}
But what if not all Objects I ever need can be created during startup? Maybe I want to respond to some user interaction when the application is running? Don't I have to keep my injector around somewhere (e.g. as a static variable) and then call injector.getInstance(SomeInterface.class) when I need to create a new object?
Of course spreading calls to Injector.getInstance() all over the place seems not to be desirable.
What am I getting wrong here?
Yes, you basically only should use the Injector to create get the instance for the root-object. The rest of the application shouldn't touch the Guice-Container. As you've noticed, you still need to create some objects when required. There are different approaches for doing that, each suitable for different needs.
Inject a Provider
Provider is a interface from Guice. It allows you to request a new instance of a object. That object will be created using Guice. For example.
class MyService{
private Provider<Transaction> transactionProvider;
public MainGui(Provider<Transaction> transactionProvider){
this.transactionProvider = transactionProvider;
}
public void actionStarted(){
Transaction transaction = transactionProvider.get();
}
Build a Factory
Often you need some kind of factory. This factory uses some injected services and some parameters and creates a new object for you. Then you use this factory for new instances. Then you inject that factory and use it. There also help for this with the AssistedInject-extension
I think with these two possibilities you rarely need to use the Guice-Injector itself. However sometimes is still appropriate to use the injector itself. Then you can inject the Injector to a component.
To extend on the answer Gamlor posted, you need to also differentiate between the object types you are using.
For services, injection is the correct solution, however, don't try to always make data objects (which are generally the leafs in your object graph) injectable. There may be situations where that is the correct solution, but injecting a Provider<List> is probably not a good idea. A colleague of mine ended up do that, it made the code base very confusing after a while. We just finished cleaning it all out and the Guice modules are much more specific now.
In the abstract, I think the general idea is that if responding to user events is part of the capabilities of your application, then, well...
BillingService billingService = injector.getInstance(BillingService.class);
billingService.respondToUserEvent( event );
I guess that might be a little abstract, but the basic idea is that you get from Guice your top-level application class. Judging from your question, I guess that maybe BillingService isn't your top-level class?

Resources