2013-03-28 1 views
0

몇 가지 단위 테스트로 철저하게 테스트 한 데이터베이스 백엔드가 있습니다. 컨트롤러는 다음과 같습니다 : I는 단위 테스트가 잘 작동하는지 확인했습니다SmartGWT RestDataSource 기존 REST 서비스 호출

@Test 
    public void testCreateUser() throws Exception 
    { 
     UserDTO userDto = createUserDto(); 
     String url = BASE_URL + "/rest/users/create"; 
     UserDTO newUserDto = restTemplate 
     .postForObject(url, userDto, UserDTO.class, new Object[]{}); 
    } 

, 실제 웹 서비스가 제대로라고하며, 데이터를 넣어 : 같은

@RequestMapping(value = "/create", method = RequestMethod.POST, produces = "application/json", headers = "content-type=application/json") 
public @ResponseBody UserDTO createUser(@RequestBody UserDTO user) 
{ 
    UserEntity userEntity = service.add(user); 
    return mappingUser(userEntity); 
} 

단위 테스트가 보인다 데이터베이스에 저장합니다.

이제 SmartGWT RestDataSource를 사용하고 있으며 RestDataSource를 올바르게 구성하여 요청 본문에 새 사용자를 전달하고 새 개체를 반환하려고합니다. 본문에 JSON으로 데이터를 보내고이 호출에서 JSON을 반환하려고합니다. 그래서 컨트롤러 자체를 데이터 소스와 일치하도록 변경해야 할 수도 있습니다. 여기

는 RestDataSource 확장 AbstractDataSource입니다 :

import java.util.Map; 

import com.google.gwt.http.client.URL; 
import com.smartgwt.client.data.DSRequest; 
import com.smartgwt.client.data.OperationBinding; 
import com.smartgwt.client.data.Record; 
import com.smartgwt.client.data.RestDataSource; 
import com.smartgwt.client.types.DSOperationType; 
import com.smartgwt.client.types.DSProtocol; 

public abstract class AbstractRestDataSource extends RestDataSource 
{ 
    public AbstractRestDataSource(String id) 
    { 
     setID(id); 
     setClientOnly(false); 

     // set up FETCH to use GET requests 
     OperationBinding fetch = new OperationBinding(); 
     fetch.setOperationType(DSOperationType.FETCH); 
     fetch.setDataProtocol(DSProtocol.GETPARAMS); 
     DSRequest fetchProps = new DSRequest(); 
     fetchProps.setHttpMethod("GET"); 
     fetch.setRequestProperties(fetchProps); 

     // set up ADD to use POST requests 
     OperationBinding add = new OperationBinding(); 
     add.setOperationType(DSOperationType.ADD); 
     add.setDataProtocol(DSProtocol.POSTMESSAGE); 
     DSRequest addProps = new DSRequest(); 
     addProps.setHttpMethod("POST"); 
     addProps.setContentType("application/json"); 
     add.setRequestProperties(addProps); 

     // set up UPDATE to use PUT 
     OperationBinding update = new OperationBinding(); 
     update.setOperationType(DSOperationType.UPDATE); 
     update.setDataProtocol(DSProtocol.POSTMESSAGE); 
     DSRequest updateProps = new DSRequest(); 
     updateProps.setHttpMethod("PUT"); 
     update.setRequestProperties(updateProps); 

     // set up REMOVE to use DELETE 
     OperationBinding remove = new OperationBinding(); 
     remove.setOperationType(DSOperationType.REMOVE); 
     DSRequest removeProps = new DSRequest(); 
     removeProps.setHttpMethod("DELETE"); 
     remove.setRequestProperties(removeProps); 

     // apply all the operational bindings 
     setOperationBindings(fetch, add, update, remove); 

     init(); 
    } 

    @Override 
    protected Object transformRequest(DSRequest request) 
    { 
     super.transformRequest(request); 

     // now post process the request for our own means 
     postProcessTransform(request); 

     return request.getData(); 
    } 

    /* 
    * Implementers can override this method to create a 
    * different override. 
    */ 
    @SuppressWarnings("rawtypes") 
    protected void postProcessTransform(DSRequest request) 
    { 
     StringBuilder url = new StringBuilder(getServiceRoot()); 

     Map dataMap = request.getAttributeAsMap("data"); 
     if (request.getOperationType() == DSOperationType.REMOVE) 
     { 
      // in case of remove, append the primary key 
      url.append(getPrimaryKeyProperty()).append("/").append(dataMap.get(getPrimaryKeyProperty())); 
     } 
     else if (request.getOperationType() == DSOperationType.UPDATE) 
     { 
      url.append("update"); 
      appendParameters(url, request); 
     } 
     else if (request.getOperationType() == DSOperationType.FETCH && dataMap.size() > 0) 
     { 
      url.append(getPrimaryKeyProperty()).append("/").append(dataMap.get(getPrimaryKeyProperty())); 
     } 
     else if (request.getOperationType() == DSOperationType.ADD) 
     { 
      url.append("create"); 
     } 

     System.out.println("AbstractRestDataSource: postProcessTransform: url=" + url.toString()); 
     request.setActionURL(URL.encode(url.toString())); 
    } 

    /* 
    * This simply appends parameters that have changed to the URL 
    * so that PUT requests go through successfully. This is usually 
    * necessary because when smart GWT updates a row using a form, 
    * it sends the data as form parameters. Most servers cannot 
    * understand this and will simply disregard the form data 
    * sent to the server via PUT. So we need to transform the form 
    * data into URL parameters. 
    */ 
    @SuppressWarnings("rawtypes") 
    protected void appendParameters(StringBuilder url, DSRequest request) 
    { 
     Map dataMap = request.getAttributeAsMap("data"); 
     Record oldValues = request.getOldValues(); 
     boolean paramsAppended = false; 

     if (!dataMap.isEmpty()) 
     { 
      url.append("?"); 
     } 

     for (Object keyObj : dataMap.keySet()) 
     { 
      String key = (String) keyObj; 
      if (!dataMap.get(key).equals(oldValues.getAttribute(key)) || isPrimaryKey(key)) 
      { 
       // only append those values that changed or are primary keys 
       url.append(key).append('=').append(dataMap.get(key)).append('&'); 
       paramsAppended = true; 
      } 
     } 

     if (paramsAppended) 
     { 
      // delete the last '&' 
      url.deleteCharAt(url.length() - 1); 
     } 
    } 

    private boolean isPrimaryKey(String property) 
    { 
     return getPrimaryKeyProperty().equals(property); 
    } 

    /* 
    * The implementer can override this to change the name of the 
    * primary key property. 
    */ 
    protected String getPrimaryKeyProperty() 
    { 
     return "id"; 
    } 

    protected abstract String getServiceRoot(); 

    protected abstract void init(); 
} 

을 그리고 여기 AbstractRestDataSource 확장 UserDataSource이다 : 나는 requestBody에 JSON으로 객체 인 UserDTO을 얻는 방법 찾아 낼 수있는 경우에

import java.util.Map; 

import com.google.gwt.http.client.URL; 
import com.opensource.restful.shared.Constants; 
import com.smartgwt.client.data.DSRequest; 
import com.smartgwt.client.data.fields.DataSourceBooleanField; 
import com.smartgwt.client.data.fields.DataSourceDateField; 
import com.smartgwt.client.data.fields.DataSourceIntegerField; 
import com.smartgwt.client.data.fields.DataSourceTextField; 
import com.smartgwt.client.types.DSDataFormat; 
import com.smartgwt.client.types.DSOperationType; 

public class UserDataSource extends AbstractRestDataSource 
{ 
    private static UserDataSource instance = null; 

    public static UserDataSource getInstance() 
    { 
     if (instance == null) 
     { 
      instance = new UserDataSource("restUserDS"); 
     } 

     return instance; 
    } 

    private UserDataSource(String id) 
    { 
     super(id); 
    } 

    private DataSourceIntegerField userIdField; 
    private DataSourceBooleanField userActiveField; 
    private DataSourceTextField usernameField; 
    private DataSourceTextField passwordField; 
    private DataSourceTextField firstnameField; 
    private DataSourceTextField lastnameField; 
    private DataSourceTextField emailField; 
    private DataSourceTextField securityQuestion1Field; 
    private DataSourceTextField securityAnswer1Field; 
    private DataSourceTextField securityQuestion2Field; 
    private DataSourceTextField securityAnswer2Field; 
    private DataSourceDateField birthdateField; 

    private DataSourceIntegerField positionIdField; 

    protected void init() 
    { 
     setDataFormat(DSDataFormat.JSON); 
     setJsonRecordXPath("/"); 

     // set the values for the datasource 
     userIdField = new DataSourceIntegerField(Constants.USER_ID, Constants.TITLE_USER_ID); 
     userIdField.setPrimaryKey(true); 
     userIdField.setCanEdit(false); 

     userActiveField = new DataSourceBooleanField(Constants.USER_ACTIVE, Constants.TITLE_USER_ACTIVE); 

     usernameField = new DataSourceTextField(Constants.USER_USERNAME, Constants.TITLE_USER_USERNAME); 
     passwordField = new DataSourceTextField(Constants.USER_PASSWORD, Constants.TITLE_USER_PASSWORD); 

     firstnameField = new DataSourceTextField(Constants.USER_FIRST_NAME, Constants.TITLE_USER_FIRST_NAME); 
     lastnameField = new DataSourceTextField(Constants.USER_LAST_NAME, Constants.TITLE_USER_LAST_NAME); 

     emailField = new DataSourceTextField(Constants.USER_EMAIL, Constants.TITLE_USER_EMAIL); 

     securityQuestion1Field = 
      new DataSourceTextField(Constants.USER_SECURITY_QUESTION_1, Constants.TITLE_USER_SECURITY_QUESTION_1); 
     securityAnswer1Field = 
      new DataSourceTextField(Constants.USER_SECURITY_ANSWER_1, Constants.TITLE_USER_SECURITY_ANSWER_1); 
     securityQuestion2Field = 
      new DataSourceTextField(Constants.USER_SECURITY_QUESTION_2, Constants.TITLE_USER_SECURITY_QUESTION_2); 
     securityAnswer2Field = 
      new DataSourceTextField(Constants.USER_SECURITY_ANSWER_2, Constants.TITLE_USER_SECURITY_ANSWER_2); 

     birthdateField = new DataSourceDateField(Constants.USER_BIRTHDATE, Constants.TITLE_USER_BIRTHDATE); 

     positionIdField = new DataSourceIntegerField(Constants.USER_POSITION_ID, Constants.TITLE_USER_POSITION_ID); 
     // positionActiveField = new DataSourceBooleanField(Constants.USER_ACTIVE, Constants.TITLE_USER_ACTIVE); 
     // positionCodeField; 
     // positionDescriptionField; 

     setFields(userIdField, userActiveField, usernameField, passwordField, firstnameField, lastnameField, 
      emailField, birthdateField, securityQuestion1Field, securityAnswer1Field, securityQuestion2Field, 
      securityAnswer2Field, positionIdField); 
    } 

    protected String getServiceRoot() 
    { 
     return "rest/users/"; 
    } 

    protected String getPrimaryKeyProperty() 
    { 
     return "userId"; 
    } 

    /* 
    * Implementers can override this method to create a 
    * different override. 
    */ 
    @SuppressWarnings("rawtypes") 
    protected void postProcessTransform(DSRequest request) 
    { 
     // request.setContentType("application/json"); 

     StringBuilder url = new StringBuilder(getServiceRoot()); 

     Map dataMap = request.getAttributeAsMap("data"); 
     if (request.getOperationType() == DSOperationType.REMOVE) 
     { 
      // in case of remove, append the primary key 
      url.append(getPrimaryKeyProperty()).append("/").append(dataMap.get(getPrimaryKeyProperty())); 
     } 
     else if (request.getOperationType() == DSOperationType.UPDATE) 
     { 
      url.append("update"); 
      System.out.println("UserDataSource: postProcessTransform: update: url=" + url.toString()); 
     } 
     else if (request.getOperationType() == DSOperationType.FETCH && dataMap.size() > 0) 
     { 
      url.append(getPrimaryKeyProperty()).append("/").append(dataMap.get(getPrimaryKeyProperty())); 
     } 
     else if (request.getOperationType() == DSOperationType.ADD) 
     { 
      url.append("create"); 
     } 

     System.out.println("UserDataSource: postProcessTransform: url=" + url.toString()); 
     request.setActionURL(URL.encode(url.toString())); 
    } 
} 

을 , 나는 나의 모든 문제를 해결할 것이라고 생각한다. 추가 정보를 알고 싶으면 springmvc-servlet.xml 파일에서 구성된 Spring 3.2 및 Jackson Message Converters를 사용하고 있습니다.

한순간에 모든 데이터가 URL에 추가되는 것을 보았지만 데이터가 URL에 매개 변수가 아니라 요청 본문에있는 경우를 선호합니다. 그래서 가능한지, 어떻게 할 수 있는지 알아야합니다.

도움 주셔서 감사합니다.

답변

0

이러한 수정 사항을 모두 실행 취소하고 RestDataSource.setDataFormat()을 호출하는 경우 이미 요청 본문을 JSON으로 전달한 기본 RestDataSource 프로토콜을 구현하는 것이 좋습니다. 당신이 만든 다른 문제 중

http://www.smartclient.com/smartgwtee/javadoc/com/smartgwt/client/data/RestDataSource.html

:이 샘플 JSON 메시지는 문서에

  1. 다른 CRUD 작업이 이제 별개의 URL로 가서 다른 HTTP 동사를 사용하므로 더 이상 단일 대기열에 결합하여 함께 보낼 수 없습니다. 이는 수행 할 수 없음을 의미합니다 트랜잭션에서 작성 및 업데이트 작업을 함께 수행하고, OrderItems와 함께 새 Order를 저장하거나 데이터를 저장하고 새 화면으로 전환하는 데 필요한 종속 데이터를 가져 오는 일도 있습니다.

  2. 당신이 "가져 오기"HTTP GET을 기반으로합니다 가정하고

    , 그러나 이것은 쉽게 최대 URL 길이를 칠 수 URL 매개 변수에 중첩 된 기준 구조 (AdvancedCriteria)의 어색한 인코딩을 필요로

이러한 이유로 인해 대부분의 생성 된 Java 서비스는 최신 UI의 요구 사항을 충족시키지 못하며 자동 생성 방식을 사용하지 않아야합니다.자주 묻는 질문에서 깊은 설명 :

http://forums.smartclient.com/showthread.php?t=8159#aExistingRest

+0

나는 도움 찰스 감사 할,하지만 정말 내 질문에 대답하지 않습니다. 그것이 나에게 말하는 것은 내가 잘못한 것이고, 직접적인 질문에 답하지 않습니다. 나는 당신의 답변 대부분이 SmartGWT 문서 또는 FAQ를 참조하는 것을 보았습니다 ... 그리고이 문서는 전체 이야기를 거의 이야기하지 않고 2009 년부터 SmartGWT를 사용하고 있습니다. – tjholmes66

+0

쇼케이스에서 SmartGWT 나머지 예제를 썼습니다 , 심지어 이러한 예제는 뚜렷한 URL을 보여주고 다른 동사를 사용합니다. 그래서, 나는이 코드가 어떻게 잘못되었는지를 알지 못합니다. 네, 가져 오기가 GET을 사용한다고 가정하고 있습니다. 어떻게하면 이것이 어색 할 지 모르겠지만, 여러분 자신의 예제들 모두 GET을 사용하여 가져 오기를 보여 주며, 쇼케이스 예제 후에 코드를 모델링하려고 시도했습니다. 다시 직접적인 질문은 다음과 같습니다. 객체 대신 String JSON을 전달해야 할 것으로 추측됩니다. 나는 이것을 다음에 시도 할 것이다. – tjholmes66

+0

샘플은 하드 코드 된 응답을 파일로 저장하기 때문에 고유 URL을 사용합니다. 실제 시스템은 위의 이유로 단일 URL을 사용해야합니다. 당신 말이 맞아요. 나는 당신의 즉각적인 질문에 대답하지 않았습니다. 제 대답은 더 좋았습니다. 그것은 당신이 취하는 접근법을 취하는 것이 나쁜 생각 일 것이기 때문에, 당신은 그 문제를 전혀 풀 필요가 없다는 것을 의미합니다. –

관련 문제