Following along with groovies docs on REST, i've setup a model like so:
import grails.rest.*
#Resource(uri='/books')
class Book {
String title
static constraints = {
title blank:false
}
}
I'd print out the parameters I receive when creating and saving. Is there away to override these methods created by the #Resource(uri='/books') annotation? Or handle the annotation a closure or something to do this?
I think you may have 2 choices if you wish to have a default RESTful interface and modify it somewhat for your needs.
Use the $ grails generate-controller [Domain Class Name] command that will generate the appropriate controller and change the generated file as needed.
Create a Book controller and extend the RestfulController; then override the default methods with the #Override annotation, print/log the params, and then call the matching super method.
import grails.rest.RestfulController
class BookController extends RestfulController {
static responseFormats = ['json', 'xml']
BookController() {
super(Book)
}
#Override
def save() {
println params
super.save params
}
#Override
def update() {
println params
super.update params
}
}
Related
I have my domain classes defined as follows, have no code in my controllers
import grails.rest.*
#Resource(formats=['json', 'xml'])
class Product {
String name
static hasMany = [productPrices: ProductPrice]
}
import grails.rest.*
#Resource(formats=['json', 'xml'])
class ProductPrice {
int price
static belongsTo = [product:Product]
}
My UrlMappings is defined as
"/products"(resources:"product")
{
"/productprices"(resources: "productprice")
}
I have also tried the following based on SO input - but it does not work
ProductPriceController extends RestfulController<ProductPrice> {
static responseFormats = ['json', 'xml']
ProductPriceController()
{
super(ProductPrice)
}
#Override def index()
{
def productId = params.productId
respond ProductPrice.where { product.id == productId }.list()
}
}
I can access my data using the urls /MyApp/products and /MyApp/products/1.
However I cannot access my data at the second level e.g. and /MyApp/products/1/ productprices – It gives me a 404. I am just trying to get my basic code skeleton to work.
I am referring primarily to the post nested RESTful resources.
Note: I know that long term I need to probably implement custom controllers as described in this article Grails get child domain objects, but before that I can't seem to get this basic code to work.
Pointers appreciated.
I have got one method say Login in "First class". Now in my "Second class" again Login is needed to be done, so can anyone tell me what's the easiest way to do this task ?
Should i create object of first class in second class and call to methods of first class.
Should i create base class and extend it ?
Please provide any example if possible
Thanks
Alright let me answer this here:
class MyBase
{
void Login()
{
// TODO base defined login here
}
}
class FirstClass extends MyBase
{
// Define your methods in any order it is fine
void Login()
{
// TODO firstclass defined login here
}
void addTest()
{
// Addtest code here
}
}
int main()
{
MyBase base;
FirstClass firstClass;
base.Login() // Will call the MyBase method for Login
firstClass.Login() // Will call the FirstClass method for Login
}
So the order of defining methods isn't important as long as you are doing them nicely. If possible read about Inheritance in Java to be more clear with your approach.
Do you understand this completely now..? If yes then start coding and if not then let me know and we'll go more deeper...
I would recommend implementing a Page Object Model, and refactor the login code to be a method of the object representing the login screen. That way, the login code will be most easily available to any testcase which needs to perform a login. The code will look something like this simplified version:
public class LogInScreen {
public void LogIn(String username, String password) {
userNameTextField.sendKeys(username);
passwordTextField.sendKeys(password);
loginButton.click();
}
public class MyTests {
#Test
public void testLoginNormalUser() {
String username = "userA";
String password = "badg3rs";
publicscreen.LogIn(username, password);
// carry on with the rest of the test.
}
#Test
public void testLoginAdminUser() {
String username = "userB";
String password = "3lk";
publicscreen.LogIn(username, password);
// carry on with the rest of the test.
}
Notice the benefits you get from this:
The code which interacts with the login controls is in a class representing the login screen; the testcase code doesn't need to concern itself with the UI details too much, so each #test can just concern itself with test logic.
Any testcase can call the login() method.
It's simple: there's no need for inheritance or overloading.
In my RestController which extends AbstractRestfulController, I can get the route params in the implemented functions such as...
public function create($data)
{
$entity = $this->params()->fromRoute('entity');
}
... but when I do the same in the constructor like this
public function __construct()
{
$entity = $this->params()->fromRoute('entity');
}
I get Call to a member function getParam() on a non-object.
Why is that? How can I get the route parameters in the constructor?
What I am trying to do
Since I'm trying to create a generic controller, there is a part of the restful route that is shared for all actions (resp. verbs). The entity for which the request is made. I'd like to store this in a class parameter for convenience.
Normally you'd write a method to proxy to whatever value you need, and just call that method, it's only a little more expensive to call $this->getEntity() than it is to call $this->entity, which, as far as I can tell is the stated aim
class RestController
{
protected $entity;
public function getEntity()
{
if (!$this->entity) {
$this->entity = $this->params()->fromRoute('entity');
}
return $this->entity;
}
}
If you really do want to pre-populate the entity property, the simplest method is to use an initializer, and move the code from your __constructor to init(). Have your controller implement \Zend\Stdlib\InitializableInterface
use Zend\Stdlib\InitializableInterface;
class RestController extends AbstractRestfulController implements InitializableInterface
{
protected $entity;
public function init() {
$this->entity = $this->params()->fromRoute('entity');
}
}
Add an initializer to the controller loader in your module boostrap
use Zend\Stdlib\InitializableInterface;
class Module
{
public function onBootstrap(MvcEvent $e)
$sm = $e->getApplication()->getServiceManager();
$controllers = $sm->get('ControllerLoader');
$controllers->addInitializer(function($controller, $cl) {
if ($controller instanceof InitializableInterface) {
$controller->init();
}
}, false); // false tells the loader to run this initializer after all others
}
}
That would not make any sense as the route is matched to a particular action.
You can't route to a constructor, therefore how could you get route parameters there?
If you give an idea of what you are trying to do then I could suggest a better/nicer way to do it
I want to mock a Class in Mockito. It will then have a .newInstance() call issued which will be expected to return an actual class instance (and will return a mock in my case).
If it was setup correctly then I could do:
ArrayList myListMock = mock(ArrayList.class);
when(myVar.newInstance()).thenReturn(myListMock);
I know I can set it up so that a new instance of class ArrayList will be a mock (using PowerMockito whenNew), just wondering if there was a way to mock this kind of a class object so I don't have to override instance creation...
Below is the real class I'm trying to mock, I can't change the structure it is defined by the interface. What I'm looking for is a way to provide cvs when initialize is called.
public class InputConstraintValidator
implements ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = cvs.newInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
Mockito is designed exclusively for mocking instances of objects. Under the hood, the mock method actually creates a proxy that receives calls to all non-final methods, and logs and stubs those calls as needed. There's no good way to use Mockito to replace a function on the Class object itself. This leaves you with a few options:
I don't have experience with PowerMock but it seems it's designed for mocking static methods.
In dependency-injection style, make your static factory method into a factory instance. Since it looks like you're not actually working with ArrayList, let's say your class is FooBar instead:
class FooBar {
static class Factory {
static FooBar instance;
FooBar getInstance() {
if (instance == null) {
instance = new FooBar();
}
return instance;
}
}
// ...
}
Now your class user can receive a new FooBar.Factory() parameter, which creates your real FooBar in singleton style (hopefully better and more threadsafe than my simple implementation), and you can use pure Mockito to mock the Factory. If this looks like it's a lot of boilerplate, it's because it is, but if you are thinking of switching to a DI solution like Guice you can cut down a lot of it.
Consider making a field or method package-private or protected and documenting that it's visible for testing purposes. Then you can insert a mocked instance in test code only.
public class InputConstraintValidator implements
ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = getCvsInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
#VisibleForTesting protected getCvsInstance()
throws InstantiationException, IllegalAccessException {
return cvs.newInstance();
}
}
public class InputConstaintValidatorTest {
#Test public void testWithMockCvs() {
final SafeString cvs = mock(SafeString.class);
InputConstraintValidator validator = new InputConstraintValidator() {
#Override protected getCvsInstance() {
return cvs;
}
}
// test
}
}
I think you just need to introduce an additional mock for Class:
ArrayList<?> myListMock = mock(ArrayList.class);
Class<ArrayList> clazz = mock(Class.class);
when(clazz.newInstance()).thenReturn(myListMock);
Of course the trick is making sure your mocked clazz.newInstance() doesn't end up getting called all over the place because due to type-erasure you can't specify that it's actually a Class<ArrayList>.
Also, be careful defining your own mock for something as fundamental as ArrayList - generally I'd use a "real one" and populate it with mocks.
I have a method which i'd like to refactor
Basically i want to split the top level method in a abstract and a final part.
The method in question is overridden in quite a few places where additional functionality is added, but eventualy the super call is always made.
The code now basically look like:
(not all Extending classes override but those that do, do it this way)
class Base {
public Object getStuff(String key) {
out = //code to get data from the Database.
return out
}
class Extended1 extends Base {
public Object getStuff(String key) {
if("some_non_db_value".equals(key)) {
return "some custom stuff";
}
return super.getStuff(key);
}
}
What i'd like as a result would be something like:
class Base {
public final Object getStuff(String key) {
out = getCustom(key);
if(out != null) {
return custom;
}
out = //code to get data from the Database.
return out
}
public abstract Object getCustom(String key);
}
class Extended1 extends Base {
public Object getCustom(String key) {
if("some_non_db_value".equals(key)) {
return "some custom stuff";
}
return null;
}
}
I was hoping there would be a refactor action (or partial refactor) to get to (or closer to) this point.
I would first rename getStuff() to getCustom() which would take care of all the extended classes. Then changing the Base class should be relatively easy.