2013-05-06 44 views
3

需要你的幫助我親愛的朋友。我爲每個模塊(項目,產品,...)使用相同的代碼來導出pfd。所有地方工作正常,但一個地方,PDF文件創建和下載成功,但在控制檯它給這樣的錯誤。Grails導出:已針對此響應調用getOutputStream()。 Stacktrace如下:

getOutputStream() has already been called for this response. Stacktrace follows: 
java.lang.IllegalStateException: getOutputStream() has already been called for this response 
    at net.bull.javamelody.FilterServletResponseWrapper.getWriter(FilterServletResponseWrapper.java:121) 
    at grails.converters.JSON.value(JSON.java:199) 
    at grails.converters.JSON.render(JSON.java:134) 
    at grails.converters.JSON.render(JSON.java:150) 
    at com.****.***.RoomController$_closure2.doCall(RoomController.groovy:78) 
    at net.bull.javamelody.JspWrapper.invoke(JspWrapper.java:117) 
    at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:233) 
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:197) 
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:171) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:722) 
2013-05-06 17:38:54,381 ERROR [http-bio-8080-exec-5] GrailsExceptionResolver       IllegalStateException occurred when processing request: [GET] /****/room/listByCompanyJSON - parameters: 
extension: pdf 
format: pdf 




package com.company.pro 

import grails.converters.JSON 
import grails.plugins.springsecurity.Secured 

import java.sql.Timestamp 

import com.company.pro.constants.CommonSearchParams 
import com.company.pro.constants.TicketType 
import com.company.pro.decorator.JQGridDecorator 
import com.company.pro.search.RoomSearch 


class RoomController extends BaseController 
{ 
    def debugOn = log.isDebugEnabled() 

    static defaultAction = "list" 

    def userService 
    def inventoryJMSService 
    def filterUtilService 
    def accountJMSService 
    def ticketingJMSService 
    def minutesUntilStale = 5 //TODO: make this configurable? 
    def millisUntilStale = minutesUntilStale * 60 * 1000 

    def proExportService 


    @Secured(['ROLE_TelePresenceReportUser']) 
    def list(){ 
     def colNames="'${g.message(code:'common.status')}','${g.message(code:'rooms.label')}','${g.message(code:'user.details.site')}','${g.message(code:'device.city')}','${g.message(code:'common.stateProvince')}','${g.message(code:'common.country')}'" 
     def colModel="{name:'status', editable: false, fixed: true, width:'60px'},{name:'room', editable: false, fixed: false, width:'200px'},{name:'siteName', editable: false, fixed: false, width:'350px'},{name:'city', editable: false, fixed:true, width:'125px'},{name:'state', editable: false, fixed: true, width:'150px'},{name:'country', editable: false, fixed: true, width:'150px'}" 

     [colNames:colNames, colModel:colModel] 
    } 

    @Secured(['ROLE_TelePresenceReportUser']) 
    def listJSON = { 
     chain(action: 'listByCompanyJSON', params: params) 
    } 

    @Secured(['ROLE_TelePresenceReportUser']) 
    def listByCompanyJSON = { 
     params.companyId= filterUtilService.getCurrentCustomer()?.id 
     params.monitoringStatus = CommonSearchParams.MONITORING 

     if(params.format!=null && params.format != "html"){ 
       downloadList(session, params) 

     } 
     session.setAttribute("lastSearchParams", params) 

     def findRoomsResponse = inventoryJMSService.findRooms(params) 
     def search = new RoomSearch() 
     search.params = params 
     search.doSearch() 
     session.setAttribute("lastRoomsSearch", search.data?.collect {it.room}) 
     def decorator = new JQGridDecorator(search) 

     def data = decorator.asRoomsListGrid() 

     def up = message(code:"status.up") 
     def down = message(code:"status.down") 
     data.rows.each {row -> row.cell[0] = row.cell[0] ? up : down } 

     render data as JSON 
    } 

    private downloadList(javax.servlet.http.HttpSession session, Map params) { 
     String cname = filterUtilService.getCurrentCustomer()?.name 
     cname = cname.replaceAll(" ","_") 
     def arrRooms =session.getAttribute("lastRoomsSearch") 
     def deviceArray = getAllDevices().findAll { device -> arrRooms.find({currRoom -> device.room == currRoom})} 
     def siteMap = getSiteMap(deviceArray) 

     deviceArray.each({ 
      it.siteName = it.siteName?.split(":")[1]; 
     }) 
     //populate device array with site map 
     deviceArray.each({ 
      it.metaClass.city = siteMap[it.siteId]?.city 
      it.metaClass.state = siteMap[it.siteId]?.state 
      it.metaClass.country = siteMap[it.siteId]?.country 
      it.metaClass.countryAbbrev = siteMap[it.siteId]?.countryAbbrev 
      it.metaClass.companyId = siteMap[it.siteId]?.companyId 
      it.metaClass.companyName = siteMap[it.siteId]?.companyName 

     }) 

     def idList = deviceArray.collect({ it.deviceId}) 
     def arrId = idList.toArray(new String[0]) 
     //get url information for all device id's and populate that in deviceArray 
     params.deviceIds =arrId 
     params.populateSoldServices = false 
     def respo2 = inventoryJMSService.findDevicesByKeys(params) 
     def deviceByKeysSO = respo2.getDevices() 
     deviceArray.each({ 
      def parentRec = it 
      def record = deviceByKeysSO.find {parentRec.deviceId == it.deviceHeaderMgmtSysSO.deviceId} 
      it.metaClass.deviceURL = record.deviceURL 
      it.metaClass.region = record.region 
      it.metaClass.floor = record.floor 
     }) 

     List fields = ["city","state","companyId","companyName","countryAbbrev","country", 
      "productCategorization.tier1","productCategorization.tier2","productCategorization.tier3", 
      "deviceId", "deviceName","siteId", "siteName", 
      "mgmtSysAddIPSO.description","mgmtSysAddIPSO.ipAddress", 
      "mgmtSysAddIPSO.deviceExternalSysRefKey","mgmtSysAddIPSO.ipAddressTypeId", 
      "deviceURL", 
      "productCategorization.manufacturer","productCategorization.productModelVersion", 
      "region","floor","room" 
     ] 



     Map labels = ["city" : message(code:"device.city"), 
      "state" : message(code:"common.stateProvince"), 
      "companyId" : message(code:"reports.telepresence.cdr.columns.COMPANYID"), 
      "companyName": message(code:"reports.telepresence.cdr.columns.COMPANYNAME"), 
      "countryAbbrev" : message(code:"common.country.abbrev"), 
      "country":message(code:"common.country"), 
      "deviceId": message(code:"device.label.id"), 
      "deviceName": message(code:"device.label.name"), 
      "siteId": message(code:"common.siteId"), 
      "siteName": message(code:"site.name"), 
      "deviceURL" : message(code:"device.url"), 
      "productCategorization.manufacturer": message(code:"device.detail.manufacturer"), 
      "productCategorization.productModelVersion": message(code:"device.detail.model.version"), 
      "region": message(code:"site.region"), 
      "floor":message(code:"site.floor"), 
      "room": message(code:"site.room")] 

     Map parameters 
     def title = message(code:"rooms.label.plural") + "    " + message(code:"common.downloadDateTime") + " "+new Date() 
      if(params.extension == TicketType.EXPORT_EXCEL){ 
      parameters = [title: title, "column.widths": [0.1, 0.2, 0.1, 0.2, 0.2, 0.3, 0.3, 0.2, 0.3, 0.3, 0.3,0.3,0.3,0.3,0.3,0.3,0.3, 0.2, 0.2, 0.2,0.2,0.2]] 
      labels << ["productCategorization.tier1": message(code:"device.product.categorization.tier1"), 
          "productCategorization.tier2": message(code:"device.product.categorization.tier2"), 
          "productCategorization.tier3": message(code:"device.product.categorization.tier3"), 
          "mgmtSysAddIPSO.description": message(code:"device.mgmt.system"), 
          "mgmtSysAddIPSO.ipAddress": message(code:"device.mgmt.system.address"), 
          "mgmtSysAddIPSO.deviceExternalSysRefKey": message(code:"device.mgmt.system.refc"), 
          "mgmtSysAddIPSO.ipAddressTypeId": message(code:"device.mgmt.system.ipAddress.typid")] 

      } else{ 
       parameters = [title: title] 
       labels << ["productCategorization.tier1": message(code:"device.product.categorization.pc.tier1"), 
          "productCategorization.tier2": message(code:"device.product.categorization.pc.tier2"), 
          "productCategorization.tier3": message(code:"device.product.categorization.pc.tier3"), 
          "mgmtSysAddIPSO.description": message(code:"device.mgmt.sys"), 
          "mgmtSysAddIPSO.ipAddress": message(code:"device.mgmt.sys.address"), 
          "mgmtSysAddIPSO.deviceExternalSysRefKey": message(code:"device.mgmt.sys.refc"), 
          "mgmtSysAddIPSO.ipAddressTypeId": message(code:"device.mgmt.sys.ipAddress.typid")] 
      } 
      downloadDataToFiles(params.format, params.extension, "Room_List_" + cname,deviceArray, fields, labels, null, parameters) 
     return 
    } 

    /** 
    * This behavior has been moved to the JQGridDecorator object. 
    * Must remove this later, when there is time to test thoroughly 
    */ 
    private formatPanelResults={ findRoomsResponse -> 
     session.setAttribute("lastRoomsSearch", findRoomsResponse?.collect {it.room}) 
     def allRows = findRoomsResponse?.collect { 
      [ 
        cell: [ 
         it.status, 
         it.room, 
         it.siteName, 
         it.city, 
         it.state, 
         it.country 
         ], 
        id : it.room 
      ] 

     }.unique() 

     def totalRows = allRows.size() 
     def maxRows = Integer.valueOf(params.rows?:1) 
     def currentPage = Integer.valueOf(params.page?:1) 
     def numberOfPages = Math.ceil(totalRows/maxRows).toInteger() 
     def rowOffset = ((currentPage - 1) * maxRows) 

     def maxIndex = rowOffset + maxRows 
     if (maxIndex > totalRows) { maxIndex = totalRows } 

     [rows:allRows, records: totalRows, page: currentPage, total:numberOfPages] 

    } 
    @Secured(['ROLE_TelePresenceReportUser']) 
    def listDevicesByRoomJSON() { 
     if (params.room == null) {render ''} 

     def devicesForRoom = getRoomDeviceList().findAll { it.room == params.room } 

     if (debugOn) log.debug('devicesForRoom: ' + devicesForRoom) 

     def totalRows = devicesForRoom.size() 
     def maxRows = Integer.valueOf(params.rows?:1) 
     def currentPage = Integer.valueOf(params.page?:1) 
     def numberOfPages = Math.ceil(totalRows/maxRows).toInteger() 
     def rowOffset = ((currentPage - 1) * maxRows) 

     def maxIndex = rowOffset + maxRows 
     if (maxIndex > totalRows) {maxIndex = totalRows} 
     if (debugOn) log.debug ("totalRows: $totalRows, maxRows: $maxRows, currentPage: $currentPage, numberOfPages: $numberOfPages, rowOffset: $rowOffset, maxIndex: $maxIndex") 
     def roleArr = session.getAttribute("roles") 
     def svcRole = roleArr.findAll{ it.name.equalsIgnoreCase('RequestServiceUser')} 
     def validRoleExists = false 
     if(svcRole.size == 1) 
      validRoleExists = true 

     def rows = devicesForRoom[rowOffset ..< maxIndex].collect() { 
      [ 
       cell: [ 
        it.deviceId, 
        it.deviceName, 
        it.status?'Up':'Down', 
        "<a href=" + createLink(controller:'requestService', action:'create',absolute:true, params:[thisDevice:it.deviceId, requestType:14, showDevSel:false]) + ">" + message(code:'default.button.create.label') + "</href>" 
       ], 
       id:it.deviceId 
      ] 
     } 

     def jsonData = [rows:rows, records: totalRows, page: currentPage, total:numberOfPages,showSvcReq:validRoleExists] 
     render jsonData as JSON 
    } 

    private uniqueRoomData() { 
     def deviceList = getRoomDeviceList() 
     def downRooms = deviceList.findAll { !it.status }.collect { it.room } 
     if (debugOn) log.debug("downRooms: $downRooms") 

     /* Added the below code for Download functionality */ 

      //for the room list, we do not want device data 
      def temp = deviceList?.collect { 
       [ 
        'status' : downRooms.contains(it.room) ? 'Down' : 'Up' , 
        'room' : it.room, 
        'siteName' : it.siteName, 
        'city' : it.city, 
        'state' : it.state, 
        'country' : it.country 
       ] 
      } 

      temp = sortList(temp) 

      //if more than one device in a room, there will be duplicate data. Remove it. 
      def rows = temp.unique().collect { 
       [ 
        cell: [ 
         it.status, 
         it.room, 
         it.siteName, 
         it.city, 
         it.state, 
         it.country 
         ], 
        id : it.room 
       ] 

      } 

    } 
    private sortList(list) { 
     def asc = params['sord']=='asc' 
     def idx = params['sidx'] 
     if (asc) { 
      return list.sort { a, b -> 
       a[idx].compareToIgnoreCase(b[idx]) 
      } 
     } 
     else { 
      return list.sort { a, b -> 
       b[idx].compareToIgnoreCase(a[idx]) 
      } 
     } 
    } 

    private getRoomDeviceList() { 
     def roomDeviceList = session.getAttribute("roomDeviceList") 
     def roomDeviceListCreated = session.getAttribute("roomDeviceListCreated") 
     def refreshNeeded = false 
     //check for null or stale list 
     if (roomDeviceList != null && roomDeviceListCreated != null) { 
      def now = new Timestamp(System.currentTimeMillis()) 
      refreshNeeded = (now - roomDeviceListCreated > millisUntilStale) 
     } 
     else { 
      //roomDeviceList or roomDeviceListCreated *is* null, generate new list 
      refreshNeeded = true 
     } 
     if(debugOn) log.debug("refreshNeeded: " + refreshNeeded) 
     if (refreshNeeded) roomDeviceList = populateRoomDeviceListForSession() 
     if(debugOn) log.debug('roomDeviceList: ' + roomDeviceList?:"<null>") 
     return roomDeviceList 
    } 

    private populateRoomDeviceListForSession() { 
     //def devices = devicesInRooms(getAllDevices()) 
     def devices = getAllDevices().findAll { it.room } 
     def alarmMap = getAlarmMap() 
     def siteMap = getSiteMap (devices) 

     def results = devices?.collect {    
      [ 
       room : it.room, 
       deviceId : it.deviceId, 
       deviceName : it.deviceName, 
       siteName : it.siteName == null ? null: it.siteName.substring(it.siteName.indexOf(":")+1), //strip companyId & ':' from site name, 
       city : siteMap[it.siteId].city, 
       state : siteMap[it.siteId].state, 
       country : siteMap[it.siteId].country, 
       status:!(alarmMap?.values()?.contains(it.deviceId)) 
       //status: message(code:alarmMap.values().contains(it.deviceId)?'status.down':'status.up') 
      ]  
     } 

     session.setAttribute("roomDeviceList", results) 
     session.setAttribute("roomDeviceListCreated",new Timestamp(System.currentTimeMillis())) 
     return results 
    } 

    private getAllDevices() { 
     //AuthenticatedUser usr = springSecurityService.getPrincipal() 
     params.companyId= filterUtilService.getCurrentCustomer()?.id //usr.getCompanyId() 
     params.totalDeviceCountNeeded=true 
     params.monitoringStatus = CommonSearchParams.MONITORING 
     def tempRowParam = params.rows //need to store this value - will restore it later 
     params.rows = 9999 //we need all devices to find those with rooms... 
     def resp = inventoryJMSService.searchDevices(params) 
     params.rows = tempRowParam //restore original value so that pagination will work properly on first call 
     log.info("getAllDevices params:$params") 
     return resp?.getSearchDevices() 

    } 

    private getSiteMap(devices) { 
     String[] siteIds = (devices*.siteId).unique() 
     def siteMap = [:] 
     if (!siteIds) { 
      return siteMap 
     } 
     def resp = accountJMSService.findSitesByKeys([siteIds:siteIds]) 
     resp?.sites?.each { 
        siteMap.put(it.id, [ 
         name: it.name == null ? null: it.name.substring(it.name.indexOf(":")+1), //strip companyId & ':' from site name, 
         city:it.city, 
         state:it.stateProvince, 
         //country:it.countryAbbrev,//updated 
         countryAbbrev:it.countryAbbrev, 
         country:it.country, 
         companyId: it.companyId, 
         companyName:it.companyName 
        ] 
       ) 
      } 
      if (debugOn) log.debug(siteMap) 


     return siteMap 

    } 

    private getAlarmMap() { 
     def tempRowParam = params.rows //need to store this value - will restore it later 
     params.rows = 9999 
     if (debugOn) log.debug("getAlarmMap params: $params") 

     def resp = ticketingJMSService.searchAlapro([companyId:params.companyId, monitoringStatus:CommonSearchParams.MONITORING, ticketState: 'OPEN']) 
     def map = [:] 
     params.rows = tempRowParam //restore original value so that pagination will work properly on first call 
     log.info("getAlarmMap params:$params") 
     resp?.alapro?.each { 
       map.put(it.id, it.deviceId) 
      } 
      if (debugOn) log.debug("getAlarmMap map: $map") 

     return map 
    } 

    def listAll = { 
     def customer = filterUtilService.getCurrentCustomer()?.id 
     def search = new RoomSearch(customer) 
     render search.parseDataAsJSON() as JSON 
    } 

    def lastSearchFullDataset = { 
     def params = session.getAttribute("lastSearchParams"); 
     params.loadonce = true 
     def search = new RoomSearch() 
     search.params = params 
     search.doSearch() 

     render search.data as JSON 
    } 

    def getRoomsByGroup = { 

     def rooms = [] 
      def group = params.group=='Group 1'?'0':'1' 
      getAllDevices().collect{ 
       if(group == it.group){ 
        if(it.room !=null && it.room.trim() !="" && it.room.trim().length()>0){ 
         rooms.add(it.room) 
        } 
       } 
      } 
     render rooms as JSON 
    } 
} 
+0

請顯示您的代碼 – 2013-05-06 14:18:09

+0

從提供的代碼示例中不清楚哪種方法拋出此異常。請提供更多詳細信息,並請刪除所有不相關的代碼。 – 2013-05-06 15:10:26

回答

0

listByCompanyJSON有一個錯誤:調用downloadList後,你應該停止處理請求,並作出新的迴應:

if(params.format!=null && params.format != "html"){ 
    downloadList(session, params) 
    return // <-- like this 
} 
3

當你直接渲染東西時,讓grails知道不要渲染視圖。使用:

//outputStream - make sure you close it 
OutputStream out 
try { 
    out = response.getOutputStream() 
    out << bytes 
} catch (IOException ioe) { 
    //gulp - can't send to the browser 
} finally { 
    try { 
     out?.close() 
    } catch (IOException ioe) { 
     //gulp - can't close 
    } 
} 
//or render input stream 
    render (file: <InputStream>, contentType: '<content/type>') 
//or render byte array 
    render (file: <byte[]>, contentType: '<content/type>') 
//or just tell Grails that you don't want the view rendered. 
    GrailsWebRequest webRequest = 
      (GrailsWebRequest) RequestContextHolder.currentRequestAttributes() 
    webRequest.setRenderView(false) 

讓我知道它是否適用於任何人。

相關問題