В продолжении поста чирикает и Facebook поста , позволяет нам расширить OAuth службу , чтобы позволить нам статус обновления на Linkedin. Мы начинаем с создания LinkedinService
Так вот, сервис Linkedin
//interface public interface LinkedinService extends BaseOAuthService { } //implementation public class LinkedinServiceImpl extends BaseOAuthServiceImpl implements LinkedinService { private ApplicationStateManager stateManager; public LinkedinServiceImpl(OAuthConfiguration configuration, String apiPrefix, ApplicationStateManager stateManager) { super(configuration, LinkedInApi.class, apiPrefix); this.stateManager = stateManager; } @Override public String getAuthorizationURL() { Token requestToken = newRequestToken(); stateManager.set(Token.class, requestToken); return getOAuthService().getAuthorizationUrl(requestToken); } @Override public Token requestAccessToken(String oauthToken, String verifier) { Token requestToken = stateManager.getIfExists(Token.class); return getOAuthService().getAccessToken(requestToken, new Verifier(verifier)); } }
Linkedin использует токен запроса для получения токена доступа. Это требует от нас сохранения токена запроса в сеансе пользователя с помощью ApplicationStateManager. Далее идет OAuthResource для обновления статуса Linkedin.
public class LinkedinStatusUpdate extends AbstractOAuthResource { private String text; private String title; private String link; private String imageLink; public LinkedinStatusUpdate(Token accessToken, String text, String title, String link, String imageLink) { super(accessToken, Verb.POST, "people/~/shares"); this.text = text; this.title = title; this.link = link; this.imageLink = imageLink; } @Override public void process(Response response) { } @Override public void initialize(OAuthRequest request) { Document doc = new Document(); Element share = doc.newRootElement("share"); if(text != null) { share.element("comment").text(text); } Element content = share.element("content"); if(title != null) { content.element("title").text(title); } if(link != null) { content.element("submitted-url").text(link); } if(imageLink != null) { content.element("submitted-image-url").text(imageLink); } share.element("visibility").element("code").text("anyone"); String requestXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + doc.toString(); request.addHeader("Content-Length", Integer.toString(requestXML.length())); request.addHeader("Content-Type", "text/xml"); request.addPayload(requestXML); } }
Это обновление посвящено отправке xml с информацией о статусе в виде запроса POST людям / ~ / shares. например
<?xml version="1.0" encoding="UTF-8"?> <share> <comment>83% of employers will use social media to hire: 78% LinkedIn, 55% Facebook, 45% Twitter [SF Biz Times] http://bit.ly/cCpeOD</comment> <content> <title>Survey: Social networks top hiring tool - San Francisco Business Times</title> <submitted-url>http://sanfrancisco.bizjournals.com/sanfrancisco/stories/2010/06/28/daily34.html</submitted-url> <submitted-image-url>http://images.bizjournals.com/travel/cityscapes/thumbs/sm_sanfrancisco.jpg</submitted-image-url> </content> <visibility> <code>anyone</code> </visibility> </share>
Этот пример взят со страницы Share Share . Мы используем собственные классы DOM Tapestry для создания XML.
Наконец компонент
@Events( {OAuthConstants.CONNECTION_ESTABLISHED, OAuthConstants.CONNECTION_FAILED}) public class LinkedinConnect implements ClientElement { @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL, allowNull = false) private String clientId; private String assignedClientId; @Inject private JavaScriptSupport javaScriptSupport; @Inject private ComponentResources resources; @Inject private LinkedinService linkedinService; @AfterRender void addJavaScript() { assignedClientId = javaScriptSupport.allocateClientId(clientId); } @OnEvent("connectToLinkedin") URL getAuthorizationURL() throws MalformedURLException { return new URL(linkedinService.getAuthorizationURL()); } Object onAuthorize( @RequestParameter(value = "oauth_verifier", allowBlank = true) final String verifier, @RequestParameter(value = "oauth_token", allowBlank = true) String oAuthToken, @RequestParameter(value = "denied", allowBlank = true) String denied) { if(verifier != null) { return accessGranted(oAuthToken, verifier); } else { return accessDenied(denied); } } private Object accessGranted(String oAuthToken, String verifier) { Token accessToken = linkedinService.requestAccessToken(oAuthToken, verifier); CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>(); boolean handled = resources.triggerEvent(OAuthConstants.CONNECTION_ESTABLISHED, new Object[] { accessToken}, callback); if(handled) { return callback.getResult(); } return null; } private Object accessDenied(String denied) { CaptureResultCallback<Object> callback = new CaptureResultCallback<Object>(); boolean handled = resources.triggerEvent(OAuthConstants.CONNECTION_FAILED, new Object[] {denied}, callback); if(handled) { return callback.getResult(); } return null; } @Override public String getClientId() { return assignedClientId; } }
<t:container xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'> <a href='#' t:type='eventLink' t:event='connectToLinkedin'> <t:body/> </a> </t:container>
Это почти копия TwitterConnect. При щелчке по ссылке обработчик события возвращает URL-адрес авторизации, который перенаправляет браузер на авторизацию Linkedin. После авторизации Linkedin перенаправляет браузер по URL-адресу обратного вызова (указанному в конфигурации), который является нашим обработчиком события onAuthorize (). Обработчик событий, основываясь на параметрах запроса, решает, какой обратный вызов вызвать.
Наконец, вклад модуля
public LinkedinService buildLinkedinService(ApplicationStateManager stateManager){ OAuthConfiguration configurer = new OAuthConfiguration("app_id", "secret", "http://localhost:9090/linkedin.linkedinconnect:authorize", null); return new LinkedinServiceImpl(configurer, OAuthConstants.DEFAULT_LINKEDIN_API_PREFIX, stateManager); }
Использование компонента на странице очень похоже на предыдущий
public class Linkedin { @Inject private LinkedinService linkedinService; @SuppressWarnings("unused") @Property @Persist(PersistenceConstants.FLASH) private String message; @OnEvent(value = OAuthConstants.CONNECTION_ESTABLISHED) void changeStatus(Token accessToken) { linkedinService.send(new LinkedinStatusUpdate(accessToken, "Google", "Google", "http://www.google.com", "http://www.google.co.in/intl/en_ALL/images/logos/images_logo_lg.gif")); message = "Status Updated"; } void onConnectionFailed(String denied) { message = "Failed"; } }
<html xmlns:t='http://tapestry.apache.org/schema/tapestry_5_1_0.xsd'> <body> ${message}<br/> <a t:id='linkedinConnect' t:type='linkedinConnect'>Connect to Linkedin</a> </body> </html>