Struts2 Restful Mapping configuration - struts2

I'm new in struts2, I tried to use Restful but I can't config.
I have 2 Controllers:
UsersController
#Namespace("/api")
public class UsersController extends ActionSupport implements ModelDriven<Object> {
}
ListController
#Namespace("/api/users/{user_id}")
public class ListController extends ActionSupport implements ModelDriven<Object> {
}
I would like to create API like this:
/api/users/ -> method UsersController.index
/api/users/{user_id} -> method UsersController.show
/api/users/{users_id}/list -> method ListController.index
/api/users/{users_id}/list/{list_id} -> method ListController.show
I tried config struts.properties
struts.devMode = true
struts.convention.action.suffix = Controller
struts.convention.action.mapAllMatches = true
struts.convention.default.parent.package = rest-default
struts.convention.package.locators = controller
struts.rest.defaultExtension = json
struts.action.extension =
struts.mapper.alwaysSelectFullNamespace = false
struts.mapper.idParameterName = id
struts.patternMatcher = namedVariable
struts.mapper.class = org.apache.struts2.dispatcher.mapper.Restful2ActionMapper
struts.enable.SlashesInActionNames = true
It doesn't work like what I want.
Do you have any suggestion?

Related

Instantiate a class in MVC 5 gives error [class] does not contain a definition for [member] and no extension method [member] ... could be found

I have a class defined in a model:
public class OfficeData
{
public int ReportID;
public DateTime? LastReported;
public string ReportedBy;
}
and this method to instantiate the class in the model:
public IEnumerable<OfficeData> GetOfficeData(int OfficeId)
{
MyContext db = new MyContext();
var officeData = db.Database.SqlQuery<OfficeData>("get_data #OfficeID", new SqlParameter("OfficeID", OfficeId)).Select(data => new OfficeData { ReportID = data.ReportID, LastReported = data.LastReported, ReportedBy = data.ReportedBy};
return officeData;
}
and I am calling the method in a controller:
public ActionResult Create()
{
OfficeModel officeModel = new OfficeModel;
...
MyServiceLayer serv = new MyServiceLayer; // the service layer class holds the method
var officeData = serv.GetOfficeData(officeModel.OfficeID);
officeModel.ReportID = officeData.ReportID;
officeModel.LastReported = officeData.LastReported;
officeModel.ReportedBy = officeData.ReportedBy;
...
}
This is my first project in MVC and I'd like to understand what's going on here. Thanks in advance for any help.
GetOfficeData returns an IEnumerable<OfficeData>:
public IEnumerable<OfficeData> GetOfficeData(int OfficeId)
so the inferred type of officeData is also IEnumerable<OfficeData>. You can see this if you hover over the var keyword (or officeData, I forget which you have to hover over).
var officeData = serv.GetOfficeData(officeModel.OfficeID);
So the compiler is complaining that IEnumerable<OfficeData>.ReportID doesn't exist. Which it most likely doesn't. Did you mean to call FirstOrDefault() or possibly enumerate through the collection via a call to Select or a loop?

Pass value from grails controller to a class inside src/groovy

I have a Grails application. I want to use a value from Grails controller class (say MyController) inside a class in src/groovy/MyClass.groovy
How can I pass the value from Grails controller class to this class? I couldn't find anything relevant.
I tried this:
class MyController {
def name = "myapp"
}
Class MyClass{
def username = MyController.name
}
Please correct me . Thanks
It is hard to say for sure without knowing what you are doing but your probably want to pass the value as an argument to a method in MyClass and you probably don't want the value to be a field in the controller class.
class MyController {
def someControllerAction() {
def name = // I don't know where you are
// getting this value, but you got it from somewhere
def mc = new MyClass()
mc.someMethod(name)
// ...
}
}
class MyClass {
def someMethod(String name) {
// do whatever you want to do with the name
}
}
Or you could pass the value as a constructor argument:
class MyController {
def someControllerAction() {
def name = // I don't know where you are
// getting this value, but you got it from somewhere
def mc = new MyClass(name: name)
// ...
}
}
class MyClass {
def name
}
I hope that helps.

grails 2.2.2 service don't know domain model: "No signature of method"

I have a grails-plugin called "listadmin" there is a domain model "Liste":
package listadmin
class Liste {
String internal_name
String public_name
Boolean edtiable = true
Boolean visible = true
static hasMany = [eintrage : ListenEintrag]
static constraints = {
internal_name(unique : true , blank : false);
}
String toString() {
"${public_name}"
}
}
I have service called "SECO_ListenService" in the same module (grails-plugin):
package listadmin
class SECO_ListenService {
def getEntriesOfList(String intnalListName) {
def aList = Liste.findByInternal_name(intnalListName)
return aList
}
}
Now I try to call this service from an other module (grails-plugin) called "institutionadmin". The SECO_ListenService should return a list of strings for an select of a domain model in the inistitutionadmin:
package institutionadmin
import listadmin.SECO_ListenService
class Einrichtung {
Long einrichtungs_type
Long type_of_conzept
int anzahl_gruppen
int anzahl_kinder_pro_Gruppe
String offnungszeiten
static hasMany = [rooms : Raum]
static constraints = {
def aList = []
def sECO_ListenService = new SECO_ListenService()
aList=sECO_ListenService.getEntriesOfList("einrichtung_type")
einrichtungs_type(inList: aList)
}
}
If I try to run this application with the both modules. I get the following error:
Caused by MissingMethodException: No signature of method:
listadmin.Liste.methodMissing() is applicable for argument types: ()
values: []
It seemed to be that the service class don't know the "Liste"-domain-model. But I don't know where the error is. I also tried to call other standard methods like "findAll" but without any success.
Has anybody an idea where my mistake could be?
To get a service in a static context you need to access the grailsApplication spring bean. This can be done thought Holders. Example:
class MyService {
List<String> getAvailable() {
return ['A','B','C']
}
}
class MyDomainClass {
String something
static constraints = {
something inList: getSomethingList()
}
static List<String> getSomethingList() {
def myService = Holders.grailsApplication.mainContext.getBean('myService')
return myService.getAvailable()
}
}

Cannot use grails g.link in domain class

I have static method in a domain class that returns a url. I need to build that url dynamically but g.link isn't working.
static Map options() {
// ...
def url = g.link( controller: "Foo", action: "bar" )
// ...
}
I get the following errors:
Apparent variable 'g' was found in a static scope but doesn't refer to a local variable, static field or class. Possible causes:
You attempted to reference a variable in the binding or an instance variable from a static context.
You misspelled a classname or statically imported field. Please check the spelling.
You attempted to use a method 'g' but left out brackets in a place not allowed by the grammar.
# line 17, column 19.
def url = g.link( controller: "Foo", action: "bar" )
^
1 error
Obviously my problem is that I am trying to access g from static context, so how do I get around this?
The g object is a taglib, which is not available inside a domain class like it would be in a controller. You can get at it through the grailsApplication as shown here: How To Call A Taglib As A Function In A Domain Class
A better way to do this in Grails 2+ is through the grailsLinkGenerator service, like so:
def grailsLinkGenerator
def someMethod() {
def url = grailsLinkGenerator.link(controller: 'foo', action: 'bar')
}
In both cases, you'll need to do some extra work to get grailsApplication/grailsLinkGenerator from a static context. The best way is probably to grab it off the domainClass property of your domain class:
def grailsApplication = new MyDomain().domainClass.grailsApplication
def grailsLinkGenerator = new MyDomain().domainClass.grailsApplication.mainContext.grailsLinkGenerator
If you're using Grails 2.x you can use the LinkGenerator API. Here's an example, I am re-using a domain class I was testing with earlier so ignore the non-url related functionality.
class Parent {
String pName
static hasMany = [children:Child]
static constraints = {
}
static transients = ['grailsLinkGenerator']
static Map options() {
def linkGen = ContextUtil.getLinkGenerator();
return ['url':linkGen.link(controller: 'test', action: 'index')]
}
}
Utility Class with Static Method
#Singleton
class ContextUtil implements ApplicationContextAware {
private ApplicationContext context
void setApplicationContext(ApplicationContext context) {
this.context = context
}
static LinkGenerator getLinkGenerator() {
getInstance().context.getBean("grailsLinkGenerator")
}
}
Bean Def for New Utility Bean
beans = {
contextUtil(ContextUtil) { bean ->
bean.factoryMethod = 'getInstance'
}
}
If you need the base URL, add absolute:true to the link call.

Grails: find domain class by name

I want to allow users to traverse the domain classes and print out dumps of stuff. My frist problem: assuming the following works just fine:
//this works
class EasyStuffController{
def quickStuff = {
def findAThing = MyDomainClass.findByStuff(params.stuff)
[foundThing:findAThing]
}
}
What is the proper way to write what I am trying to say below:
//this doesn't
class EasyStuffController{ servletContext ->
def quickStuff = {
def classNameString = "MyDomainClass" //or params.whichOne something like that
def domainHandle = grailsApplication.domainClasses.findByFullName(classNameString)
//no such property findByFullName
def findAThing = domainHandle.findByStuff(params.stuff)
[foundThing:findAThing]
}
}
//this also doesn't
class EasyStuffController{ servletContext ->
def quickStuff = {
def classNameString = "MyDomainClass" //or params.whichOne something like that
def domainHandle
grailsApplication.domainClasses.each{
if(it.fullName==classNameString)domainHandle=it
}
def findAThing = domainHandle.findByStuff(params.stuff)
//No signature of method: org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass.list() is applicable
[foundThing:findAThing]
}
}
Those lines above don't work at all. I am trying to give users the ability to choose any domain class and get back the thing with "stuff." Assumption: all domain classes have a Stuff field of the same type.
If you know the full package, you can use this:
String className = "com.foo.bar.MyDomainClass"
Class clazz = grailsApplication.getDomainClass(className).clazz
def findAThing = clazz.findByStuff(params.stuff)
That will also work if you don't use packages.
If you use packages but users will only be providing the class name without the package, and names are unique across all packages, then you can use this:
String className = "MyDomainClass"
Class clazz = grailsApplication.domainClasses.find { it.clazz.simpleName == className }.clazz
def findAThing = clazz.findByStuff(params.stuff)

Resources