Run/Execute a query in gsp/view in Grails - grails

Image controller has a function
def scaled = {
log.debug("SCALED IMAGE " + params)
response.setContentType('image/jpeg')
response.setHeader('Cache-control', 'no-cache')
def userId = session.selectedUser.id
if(params.userId){
userId = params.userId
}
if(params?.id != null && !(params?.id.empty)){
params.maxWidth?: 20.00
params.maxHeight?: 20.00
response.outputStream << imageProxyService.loadImage(params.id, securityService.passwordEncoder(userId.toString()),params.maxWidth, params.maxHeight)
}
}
and profile photo's filename are stored in user table.
User has many status and i want to load user's profile photos depending on the statuses displayed. My status gsp looks like this:
<g:each in="${statusList}" status="i" var="status" status="i">
<tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
<tr><td><img id="profile_photo" src="${createLink(controller:'image', action:'profilePhoto', id:status.photo)}" alt="" title="" />
</td></tr>
</tr>
</g:each>
query I used in status controller:
def alllist = {
log.debug("BEGIN IWI PROFILE")
def statusList = []
def sql = new Sql(dataSource);
def statusQuery = """SELECT c.id, c.status_message, c.status_type as profile, se.id, se.photo FROM user_account se, status c
WHERE
c.user_account_id = se.id
GROUP BY se.id, c.id, c.status_message, c.status_type, se.photo"""
def result = sql.rows(statusQuery);
def userQuery = """not sure """
if (result){
log.debug("GOT SOME RESULTS IN PERSONAL user" + result)
result.each() { status ->
def userResult = sql.firstRow(userQuery, [status.id])
if (userResult){
status['userId'] = userResult.id
} else {
status['userId'] = ""
}
statusList += status
}
}
render(template: "alllist", model: [statusList: statusList])
Please Note: This way I am getting all the photos all right but photos display only for the session user.
<img id="profile_photo" src="/myApp/image/profilePhoto/9edd692580d148c791c6c2aa3510605a95ba6de6.jpg" alt="" title=""/>

I would create a TagLib. How you actually render the photo depends on what is stored in the UserAccount.photo field. I'll assume it's an absolute URL to an image.
class UserTagLib {
def photo = {attrs ->
UserAccount u = attrs.user
out << "<img src=${u.photo}/>"
}
}
You would use it in your GSP like:
<user:photo user="${status.userAccount}"/>
..assuming you are looping over a list of Status objects in a variable called status

You can use this one:
<img src="http://applicationUrl/images/${u.photo}" />
or
<img src="${createLink(dir:'images',file: u.photo}" />
they can be used but as create link is deprecated now, I recommend using:
Resource for the same
<img src="${resource(dir: 'images', file: 'file.jpg')}"/>
More information can be found at:
http://grails.org/doc/2.2.1/ref/Tags/resource.html
about the resources

Related

groovy error MissingPropertyException No such property: result for class: hudson.model.CauseAction

we use using mail-ext and robot frame work to try to format all test suits detail in jenkins, and send out the report.
here is the groovy email-template we used now, its downloaded from github, https://github.com/JMcn/jenkins-email-ext-templates/blob/master/robot.groovy.
but this template reported following exception as below, i did not get similar error via googling, anything we missed for this template, thanks for any hint on this error.
<%
import java.text.DateFormat
import java.text.SimpleDateFormat
%>
........
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
def robotTestResultAction = it.getAction("hudson.plugins.robot.RobotBuildAction")
actions.each() { action ->
if( robotTestResultAction != null ) {
//if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
%>
<TABLE width="100%">
<TR><TD class="bg1" colspan="4"><B>test results</B></TD></TR>
<TR style="border:1px solid #000;height:25px">
<TD>total</TD>
<TD>passed</TD>
<TD>failure</TD>
<TD>passrate</TD></TR>
<TR style="border:1px solid #000;height:25px">
<TD>${robotTestResultAction.getTotalCount()}</TD>
<TD style="color:green"><%=robotTestResultAction.getTotalCount() - robotTestResultAction.getFailCount()%></TD>
<TD style="color:red"><a style="color:red" href="${rooturl}${build.url}/${robotTestResultAction.urlName}">${robotTestResultAction.getFailCount()}</a></TD>
<TD>${robotTestResultAction.overallPassPercentage}%</TD></TR>
</TABLE>
<TABLE cellspacing="0" cellpadding="4" border="1" align="center">
<thead>
<tr bgcolor="#F3F3F3">
<td><b>test case name </b></td>
<td><b>state</b></td>
<td><b>execute duration</b></td>
</tr>
</thead>
<tbody>
<% def suites = action.result.allSuites
suites.each() { suite ->
def currSuite = suite
def suiteName = currSuite.displayName
// ignore top 2 elements in the structure as they are placeholders
while (currSuite.parent != null && currSuite.parent.parent != null) {
currSuite = currSuite.parent
suiteName = currSuite.displayName + "." + suiteName
} %>
<tr><td colspan="3"><b><%= suiteName %></b></td></tr>
<% DateFormat format = new SimpleDateFormat("yyyyMMdd HH:mm:ss.SS")
def execDateTcPairs = []
suite.caseResults.each() { tc ->
Date execDate = format.parse(tc.starttime)
execDateTcPairs << [execDate, tc]
}
// primary sort execDate, secondary displayName
execDateTcPairs = execDateTcPairs.sort{ a,b -> a[1].displayName <=> b[1].displayName }
execDateTcPairs = execDateTcPairs.sort{ a,b -> a[0] <=> b[0] }
execDateTcPairs.each() {
def execDate = it[0]
def tc = it[1] %>
<tr>
<td><%= tc.displayName %></td>
<td style="color: <%= tc.isPassed() ? "#66CC00" : "#FF3333" %>"><%= tc.isPassed() ? "PASS" : "FAIL" %></td>
<td><%= execDate %></td>
</tr>
<% } // tests
} // suites %>
</tbody>
</TABLE>
<%
} // robot results
}
if (!robotResults) {
%>
<TABLE width="100%">
<TR><TD class="bg1" colspan="2"><B>接口测试结果</B></TD></TR>
<TR><TD colspan="2">robotTestResultAction is null</TD></TR>
</TABLE>
<%
}
%>
<BR/>
Exception raised during template rendering: No such property: result for class: hudson.model.CauseAction groovy.lang.MissingPropertyException: No such property: result for class: hudson.model.CauseAction at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53) at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:66) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296) at
after adjust script using Krzysztof Błażełek's suggestion, we got following error.
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
//def robotTestResultAction = it.getAction("hudson.plugins.robot.RobotBuildAction")
actions.each() { action ->
//if( robotTestResultAction != null ) {
if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
Exception raised during template rendering: Cannot get property 'simpleName' on null object java.lang.NullPointerException: Cannot get property 'simpleName' on null object at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60) at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174) at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296) at SimpleTemplateScript211$_run_closure6.doCall(SimpleTemplateScript211.groovy:403) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ....
You have modified the template you have provided and that causes the problem. I believe you are iterating over all actions (not only hudson.plugins.robot.RobotBuildAction) and that is causing the exception. Try changing this part:
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
def robotTestResultAction = it.getAction("hudson.plugins.robot.RobotBuildAction")
actions.each() { action ->
if( robotTestResultAction != null ) {
//if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
%>
into
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
actions.each() { action ->
if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
def robotTestResultAction = action
%>
Your code needs refactoring, but that's the quickest way to test if it works.
Revise as below,which solved my problem.
if( action.class && (action.class.simpleName.equals("RobotBuildAction") ) )

Rails JSON API: Updating picture in view doesn't show

New to Rails API's. I want to have an updating picture displayed in my views. The JSON data I'm pulling from can be found here
My Model
def self.get_api_info
helio_api = "http://www.lmsal.com/hek/her?cosec=2&cmd=search&type=column&event_type=fl,bu&event_starttime=2017-03-01T00:00:00&event_endtime=2017-03-08T00:00:00&event_coordsys=helioprojective&x1=-1200&x2=1200&y1=-1200&y2=1200"
request_to_helio_api = Net::HTTP.get(URI(helio_api))
JSON.parse request_to_helio_api
end
My Controller
def index
#helio_info = HelioApi.get_api_info
end
And my View
<img src="<%= #helio_info["gs_thumburl"] %>" />
The structure of the API you're accessing is
{
"result": [
{ "gs_thumburl": "some_string", ... },
{ "gs_thumburl": "some_string", ... },
{ "gs_thumburl": "some_string", ... }
]
}
So to go from #helio_info to some_string you need to grab the result array #helio_info["result"] and then an element in that array #helio_info["result"][0], and finally grab the url #helio_info["result"][0]["gs_thumburl"]. Ruby said no implicit conversion of String into Integer because you tried to access an array using a string key, and it expects integer keys.
Thanks for the insight Pavan. Here's what I ended up doing:
Model kept the same
Controller
def index
#helio_info = HelioApi.get_api_info['result']
puts "!!!!!!!!!!!!!!*********!!!!!!!!!********!!!!!"
puts #helio_info
end
View
<% #helio_info.each do |info| %>
<% if info['gs_thumburl'] != "" %>
<img src="<%= info['gs_thumburl']%>"/>
<%end%>

No such property: id for class: java.lang.String

I am sending the employee object from the Project_level controller to the _add_members view and then from there I am sending the employee object to the Project_permission controller. while saving the id the following error is coming: No such property: id for class: java.lang.String in the line :proj_permission.setId_of_employee(emp.id)
class Project_levelController {
def auth_after_create_level(){
//creating a level under the above level
def res=Project_level.findByLevel_nameAndLevel_no(params.level_name,params.level_no)
// def res=null
if(res)
{
flash.message='level name has already been taken'
redirect(action:'_right')
}
else{
if(params.enter=="NEXT")
{
def proj_lev_right = new Project_level_right(params["project_level_right"])
proj_lev_right.save()
proj_lev_right.errors.allErrors.each { println it }
session.proj_lev_right = proj_lev_right
def proj_lev = new Project_level(params["project_level"])
proj_lev.setProj_lev_right_id("${proj_lev_right.id}")
proj_lev.id_of_project=session.id_of_project
proj_lev.mem_added = 0
proj_lev.save()
proj_lev.errors.allErrors.each { println it }
session.proj_lev = proj_lev
def emp = Employee.findAllByLevel(proj_lev.level_no)
render(view: "add_members", model: [proj_lev:proj_lev , proj_lev_right:proj_lev_right , employee:emp])
}
}
}
def _right(){
}
}
/*****************************************************************************/
class Project_permissionController {
def add_employee_to_project()
{
def emp = params.employee
def proj_permission=new Project_permission()
proj_permission.id_of_project=session.id_of_project
proj_permission.setId_of_employee(emp.id)
proj_permission.id_of_poject_level=session.proj_lev.id
/* def employee_proj_level= Project_level.get(proj_permission.id_of_project_level)//making a empty project_project and saving the project level field that belong to id_of_project_level
def employee_proj_level_right= new Project_level_right()//making a empty project_level_right
employee_proj_level_right= Project_level_right.get(employee_proj_level.proj_lev_right_id)//empty project_level_right is used to store the default right for that particular level that is given by "proj_lev_right_id"
proj_permission.setId_of_project_level_right("${employee_proj_level_right.id}")//saving employee project_level_right in id_of_proj_level_right
*/
proj_permission.id_of_project_level_right=session.proj_lev_right.id
render "Hari"
}
/**********************************************************/
<g:each var="emp" in="${employee}">
<g:link controller="project_permission" action="add_employee_to_project" params="[employee:emp]">
<button class="btn btn-block btn-info btn-sm">Add to Project</button>
</g:link></td>
</a>
</div>
</div>
</div>
</g:each>
</ul>
</div>
</div>
</div><!-- /.box-body -->
</div><!-- /.box -->
The problem is on this code:
def emp = params.employee
....
proj_permission.setId_of_employee(emp.id)
You get emp from params which is a string ( probably employee id) then you are trying to access id field from it, id field from string object? that is the problem.
Possible solution:
replace def emp = params.employee with def emp = Employee.get(params.employee)

Is there a way to render a Map as an HTML table in Grails?

I was wondering if there was a nice way to render a Map to an HTML table within a .gsp page.
An example Map:
def map = ['Mammals':['Unicorn','Chimpanzee','Goat'],
'Reptiles':['Snake','Turtle']];
This would render to something like this:
<table>
<thead>
<tr>
<th>Mammals</th>
<th>Reptiles</th>
</tr>
</thead>
<tbody>
<tr>
<td>Unicorn</td>
<td>Snake</td>
</tr>
<tr>
<td>Chimpanzee</td>
<td>Turtle</td>
</tr>
<tr>
<td>Goat</td>
<td></td>
</tr>
</tbody>
</table>
Ideally I could then create my own custom tag, so I could do this:
<stackOverflow:tablizer map="${map}" />
Something like this - Probably a better way to do it, but this was what I came up with first.
def mapToTable = { attrs ->
StringBuilder output = new StringBuilder()
if ( attrs.map instanceof Map )
{
Map map = attrs.map
if ( map.size() > 0 )
{
output.append("<table><thead><tr>")
ArrayList[] values = map.values()
int max = values.collect{it.size()}.max()
map.each { key, val ->
output.append("<th>${key}</th>")
}
output.append("</tr></thead><tbody>")
(1..max).each { num ->
output.append("<tr>")
values.each {
if ( it.size() >= num )
{
output.append("<td>${it.get(num-1)}</td>")
}
else
{
output.append("<td></td>")
}
}
output.append("</tr>")
}
output.append("</tbody></table>")
}
}
out << output
}
I can't comment on #James Kleeh's answer, but I modified his code to print a list of Maps, such as what you get back from Groovy Sql results:
protected String mapToTable(List<Map> list) {
StringBuilder output = new StringBuilder()
Map first = list.first()
output.append("<table><thead><tr>")
first.each { key, val ->
output.append("<th>${key}</th>")
}
output.append("</tr></thead><tbody>")
list.each { map ->
if (map.size() > 0) {
def values = map.values()
output.append("<tr>")
values.each {
output.append "<td>${it}</td>"
}
output.append("</tr>")
}
}
output.append("</tbody></table>")
output.toString()
}

Grails Validation : renderErrors not picking up after formRemote

This is in the gsp
<g:if test="${hasError}">
<div class="errors">
<g:renderErrors bean="${eventInstance}" />
</div>
</g:if>
<g:else >
<div id="messageBox" class="message" style="display:none;">
<g:message code="legalevent.save.success" args="[entityName]" default="Event saved successfully" />
</div>
</g:else>
<g:formRemote name="eventForm" id="eventForm" url="[controller : 'search', action : 'saveLegalEvent']"
update="eventFormDiv" action="${createLink(controller: 'search', action: 'saveLegalEvent')}" method="POST"
onSuccess="jQuery('#messageBox').show()">
I am rendering a page for update with this :
def saveLegalEvent = {
def paramsView = params
def eventPattern = /(event\.).*/
def event = LegalEvent.findByLevId(params["levId"])
def corrTxt = params["corrTxt"] as CorrectionText
if(corrTxt.getCorrId()){
corrTxt = CorrectionText.findByCorrId(corrTxt.getCorrId())
}
event.setCorrTxt(corrTxt)
event.properties = params["event"]
def dataList = []
def hasError = false
def validated = event.validate()
validated &= event.validateHistoryParams()
if(validated)
event.save(flush:true)
else
hasError = true
def errorsView = event.errors
render(view:'leform', model:[attributeDataInstanceList:event.tags, lecInstance:event.leCode, eventInstance:event, hasError: hasError])
}
validateHistoryParams validate some more params that are usually not needed in the domain class.
def validateHistoryParams = { ->
if(!changeRef || !changeRef.trim()) {
this.errors.rejectValue('changeRef', 'event.changeRef.blank')
}
if(!corrTxt || !(corrTxt.corrTxt.trim() || corrTxt.corrId )) {
this.errors.rejectValue('corrTxt', 'event.corrTxt.null')
}
!(this.hasErrors())
}
The problem with all this is that the errors are not rendered in the gsp.
All other tags are rendered fine, when debugging I can see that the errors are actually in the error stack. But in the end, the tag isn't rendering them.
As you can see, there is no redirection, so I can't understand why the errors would somehow be erased between the response creation and the rendering ...
In your Groovy code, parameter returned is named hasError, and GSP checks for hasErrors. I'd recommend not to use extra variables, and just query the bean itself in GSP.
I also believe that you need to have that errors div inside the formRemote element in order to re-render after form submission.

Resources