Skip to content

Five minutes quick start

itstamen edited this page Mar 24, 2012 · 39 revisions

#Five minutes quick start Case desc: We need to create new account through Rop framework. #Create a rest api:

Step 1:create the rop request of create new user:

    package com.rop.sample.request;

import com.rop.RopRequest;
import org.springframework.format.annotation.NumberFormat;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Pattern;

public class CreateUserRequest extends RopRequest {

@Pattern(regexp = "\\w{4,30}")//① constraint of the field
private String userName;

@Pattern(regexp = "\\w{6,30}")//②
private String password;
 
@DecimalMin("1000.00")
@DecimalMax("100000.00")
@NumberFormat(pattern = "#,###.##")//③
private long salary;

//getter and setter...
}

The ①、② and ③ is the JSR 303 annotation,ROP use the JSR 303 to validate the request data.If the request datais invalid ,ROP will generate the standard error respone(see the ROP error system for detail).

Step 2:create rop response of create new user

package com.rop.sample;

import com.rop.RopResponse;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD) //①
@XmlRootElement(name = "sampleRopResponse1")
public class CreateUserResponse implements RopResponse{
	@XmlAttribute
	private String userId;
	@XmlAttribute
	private String createTime;
   //getter and setter...
}

The ① is the JAXB annotation,ROP use the JAXB to marshaller respone to corresponding format respone message.currently ROP supoort xml and json format message.

Step 3:create the rop rest service:

package com.rop.sample;

import com.rop.ApiMethod;
import com.sample.rop.request.CreateUserRequest;
import com.sample.rop.response.CreateUserResponse;
import org.springframework.stereotype.Service;

@Service//① Let it be a Spring Bean
public class UserRestService {

	@ApiMethod("user.add")//② Let this method service the 

sample.user.add method
	@ApiMethod("user.add")//② Let this method service the sample.user.add method
	public RopResponse addUser(CreateUserRequest request) {
		if(reservesUserNames.contains(request.getUserName())){ //如果注册的用户是预留的帐号,则返回错误的报文
			return new ServiceErrorResponse(
					request.getMethod(), USER_NAME_RESERVED,request.getLocale(),request.getUserName());
		}else{
			CreateUserResponse response = new CreateUserResponse();
			//add creaet new user here...
			response.setCreateTime("20120101010101");
			response.setUserId("1");
			return response;
		}
	}
}

The last thing we need to to is create Rest service to handle the rest request and return respone.

First in the ① ,we put the @Service to make the UserRestService be a Spring Bean,so ROP can scan for candidate api handler.Secondly,create a rest api handler method which is addUser,the method 's input parameter must extends from the RopRequest.The method's return Class must be RopResponse.

Step 4:write the appKey secret file

we put the appKey secret file in rop-sample\src\main\resources\rop.appSecret.properties,defined two test appKey:

	00001=abcdeabcdeabcdeabcdeabcde
	00002=abcdeabcdeabcdeabcdeaaaaa

Step 5:write the spring config os rop-sampe:

	<?xml version="1.0" encoding="UTF-8" ?>
	<beans xmlns="http://www.springframework.org/schema/beans"
		   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		   xmlns:context="http://www.springframework.org/schema/context"
		   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

		<!--① 扫描Web类包-->
		<context:component-scan base-package="com.rop.sample">
			<!-- 假设所有的服务方法都放在rop包下-->
			<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
		</context:component-scan>
	</beans>

Step 6:write web.xml of rop-sampe:

	<?xml version="1.0" encoding="UTF-8"?>
	<web-app xmlns="http://java.sun.com/xml/ns/javaee"
			 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
			  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
			 version="2.5">
		<context-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>
				classpath*:sampleRopApplicationContext.xml
			</param-value>
		</context-param>

		<filter>
			<filter-name>characterEncodingFilter</filter-name>
			<filter-class>
				org.springframework.web.filter.CharacterEncodingFilter
			</filter-class>
			<init-param>
				<param-name>encoding</param-name>
				<param-value>UTF-8</param-value>
			</init-param>
			<init-param>
				<param-name>forceEnCoding</param-name>
				<param-value>true</param-value>
			</init-param>
		</filter>
		<filter-mapping>
			<filter-name>characterEncodingFilter</filter-name>
			<url-pattern>/*</url-pattern>
		</filter-mapping>

		<listener>
			<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
		</listener>
		<listener>
			<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
		</listener>

		<!--ROPsalk-->
		<servlet>
			<servlet-name>rop</servlet-name>
			<servlet-class>
				com.rop.RopServlet
			</servlet-class>
			<!--可通过如下初始化参数配置ROP的个性化信息,以下是内置默认的匹配-->
	<!--        <init-param>
				<param-name>sessionCheckerImpl</param-name>
				<param-value>com.rop.validation.DefaultSessionChecker</param-value>
			</init-param>
			<init-param>
				<param-name>appSecretManagerImpl</param-name>
				<param-value>com.rop.validation.FileBaseAppSecretManager</param-value>
			</init-param>-->
			<init-param>
				<param-name>ropErrorBaseName</param-name>
				<param-value>i18n/rop/serviceError</param-value>
			</init-param>
			<load-on-startup>2</load-on-startup>
		</servlet>

		<servlet-mapping>
			<servlet-name>rop</servlet-name>
			<url-pattern>/router</url-pattern>
		</servlet-mapping>

		<welcome-file-list>
			<welcome-file>index.html</welcome-file>
		</welcome-file-list>
	</web-app>


 So far web have finished the rest api.We start the web container using:
   mvn jetty:run

the sampel rop service is repare for service.

write client code

client just send the corresponding HTTP request using like following:

http://localhost:8088/router?method=user.add&param2=value2...

The serverHost url is the ROP running server' url.now the key point is the parameter list which contains twoparts: one part is the system level parameters:

No	parmName	paramType	required 	desc
1.	method	        String	        Y	API method name(sample.user.add)
2.	appKey	        String	        Y	design to application's appKey,you can define in rop.
                                        appSecret.properties which is in classpath.
3.	v	            String	        Y	API version,now only support:1.0。
4.	sign	        String	        Y	API parameters's sing,Use SHA1 encryption algorithm
5.	sessionId	    String	        N	use's sessionId.you can provide a rest api so client can 
                                        get it and maintain locally.
6.	format	        String	        N	Optional, designated response format. The default XML, 
                                        currently  support for an XML format, json
7.	locale	        String	        N	locale,such lick cn_ZH,en...

How to sign the parameter just see:Sign the parameters.

the other part is the application level parameters,different from rest api.in the sample,we have three app parameters:

userName String 
password String
salary float

We write client code:

package com.rop.sample;

import com.rop.validation.DefaultRopValidator;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;

public class UserRestServiceClient {

	public static void main(String[] args) {
		RestTemplate restTemplate = new RestTemplate();
		MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
		form.add("method", "sample.user.add");//<--Specified method api name
		form.add("appKey", "00001");//<--now the rop.appSecret.properties only 
									//defined two appKey the other is 00002.
		form.add("v", "1.0");

		form.add("sessionId", "test");//must be the valid sessionId 
		form.add("format", "xml");
		form.add("locale", "en");

		form.add("userName", "tomson");
		form.add("password", "123456");
		form.add("salary", "2,500.00");
 
		//sign the parameters,the "abcdeabcdeabcdeabcdeabcde" is secret of the 
		//"00001" appKey
		String sign = DefaultRopValidator.sign(new ArrayList<String>(
						 form.keySet()), form.toSingleValueMap(),
						 "abcdeabcdeabcdeabcdeabcde");

		form.add("sign", sign);

		String response = restTemplate.postForObject(
				"http://localhost:8088/router", form, String.class);
		System.out.println("response:\n" + response);
	}
}

the respone xml is:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<sampleRopResponse1 createTime="20120101010101" userId="1"/>

If you change the format to "json" ,then the respone message is :

{"sampleRopResponse1":{"userId":"1","createTime":"20120101010101"}}

If you make the "salary" parameter mistake eg."FFFF", the the error response is:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error solution="Invalid Arguments" message="Invalid Arguments " code="34">
	<subErrors>
		<subError>
			<code>isv.parameters-mismatch:salary-and-aaa0</code>
			<message>incoming parameter salary and aaa0 does not match, both 

have a certain correspondence between</message>
		</subError>
	</subErrors>
</error>