O repositório sd2019-tp1-api contém um projeto Eclipse (Java) com as interfaces dos vários serviços que compo~em o sistema.
-
Serviço Profiles Serviço relativo aos utilizadores; permite criar, procurar e consultar os perfis dos utilizadores registados na plataforma; permite seguir ou deixar de seguir um utilizador;
-
Serviço Posts Serviço relativo às publicações dos utilizadores; permite criar uma nova publicação, ou consultar uma publicação existente; permite atribuir (ou retirar) um "gosto" a uma publicação;
-
Serviço Media Storage Serviço focado no armazenamento das fotografias publicadas na plataforma; permite guardar uma fotografia, de modo a obter um URI/URL da mesma. Permite também obter ou apagar uma fotografia existente.
O repositório sd2019-tp1-code contém um projeto Eclipse (Java) com material de apoio para a realização do trabalho. A utilização deste código é opcional. O código é fornecido como forma de simplificar a realização do trabalho e fomentar boas práticas de programação.
O código relativo à implementação das funcionalidades dos vários serviços é disponibilizado nas seguintes classes:
-
Serviço Profiles
- Interface definida na classe microgram.api.java.Profiles sd2019-tp1-api
- Implementação definida na classe microgram.impl.srv.java.JavaProfiles sd2019-tp1-code. Nota: estado do serviço é mantido em memória.
- Interface definida na classe microgram.api.java.Profiles sd2019-tp1-api
-
Serviço Posts
- Interface definida na classe microgram.api.java.Posts sd2019-tp1-api
- Implementação definida na classe microgram.impl.srv.java.JavaPosts sd2019-tp1-code. Nota: estado do serviço é mantido em memóia.
- Interface definida na classe microgram.api.java.Posts sd2019-tp1-api
-
Serviço Media Storage
- Interface definida na classe microgram.api.java.Media sd2019-tp1-api
- Implementação definida na classe microgram.impl.srv.java.JavaMedia sd2019-tp1-code. Nota: estado do serviço é mantido em disco. Nota: Usado como exemplos das aulas práticas.
- Interface definida na classe microgram.api.java.Media sd2019-tp1-api
Interface da funcionalidade do serviço Profiles:
package microgram.api.java;
...
public interface Profiles {
/**
* Obtains a profile
* @param userId unique identifier of the requested profile
* @return result of (OK,Profile), or NOT_FOUND
*/
Result<Profile> getProfile( String userId );
...
}
Nota: todos os métodos devolve um objeto do tipo Result (que pode ser um Result.error ou um Result.ok).
Implementação da funcionalidade do serviço Profiles:
package microgram.impl.srv.java;
import static microgram.api.java.Result.error;
import static microgram.api.java.Result.ok;
import static microgram.api.java.Result.ErrorCode.NOT_FOUND;
...
public class JavaProfiles extends RestResource implements microgram.api.java.Profiles {
Map<String, Profile> users = new HashMap<>();
Map<String, Set<String>> followers = new HashMap<>();
Map<String, Set<String>> following = new HashMap<>();
@Override
public Result<Profile> getProfile(String userId) {
Profile res = users.get( userId );
if( res == null )
return error(NOT_FOUND);
res.setFollowers( followers.get(userId).size() );
res.setFollowing( following.get(userId).size() );
return ok(res);
}
...
}
O código relativo à implementação dos servidores REST dos vários serviços é disponibilizado nas seguintes classes:
-
Serviço Profiles
- Interface definida na classe microgram.api.rest.RestProfiles sd2019-tp1-api
- Código que inicia o servidor definido na classe microgram.impl.srv.rest.ProfilesRestServer sd2019-tp1-code.
- Recurso que implementa a interface REST do serviço definido na classe microgram.impl.srv.rest.RestProfilesResources sd2019-tp1-code. O código fornecido tem de ser renomeado e pode usar a implementação da funcionalidade do serviço (JavaProfiles).
- Interface definida na classe microgram.api.rest.RestProfiles sd2019-tp1-api
-
Serviço Posts
- Interface definida na classe microgram.api.rest.RestPosts sd2019-tp1-api
- Código que inicia o servidor definido na classe microgram.impl.srv.rest.PostsRestServer sd2019-tp1-code.
- Recurso que implementa a interface REST do serviço definido na classe microgram.impl.srv.rest.RestPostsResources sd2019-tp1-code. O código fornecido tem de ser renomeado e pode usar a implementação da funcionalidade do serviço (JavaPosts).
- Interface definida na classe microgram.api.rest.RestPosts sd2019-tp1-api
-
Serviço Media Storage
- Interface definida na classe microgram.api.rest.RestMedia sd2019-tp1-api
- Código que inicia o servidor definido na classe microgram.impl.srv.rest.RestMediaStorageServer @ aula 4.
- Recurso que implementa a interface REST do serviço definido na classe microgram.impl.srv.rest.RestMediaResources @ aula 4.
- Interface definida na classe microgram.api.rest.RestMedia sd2019-tp1-api
Classe microgram.impl.srv.soap.RestResource sd2019-tp1-code é uma classe auxiliar com métodos genéricos para devolver resultados a partir dum objeto Result, usado nas classes que implementam a funcionalidade dos serviços.
Código do RestProfilesResources:
public class RestProfilesResources extends RestResource implements RestProfiles {
final Profiles impl;
public RestProfilesResources(URI serverUri) {
this.impl = new JavaProfiles();
}
@Override
public Profile getProfile(String userId) {
return super.resultOrThrow( impl.getProfile(userId));
}
...
}
O código relativo à implementação dos servidores SOAP dos vários serviços é disponibilizado nas seguintes classes:
-
Serviço Profiles
- Interface definida na classe microgram.api.soap.SoapProfiles sd2019-tp1-api
- Código que inicia o servidor definido na classe microgram.impl.srv.soap.ProfilesSoapServer sd2019-tp1-code.
- Classe que implementa o web service do serviço definido na classe microgram.impl.srv.soap.ProfilesWebService sd2019-tp1-code. O código fornecido tem de ser renomeado e pode usar a implementação da funcionalidade do serviço (JavaProfiles).
- Interface definida na classe microgram.api.soap.SoapProfiles sd2019-tp1-api
-
Serviço Posts
- Interface definida na classe microgram.api.soap.SoapPosts sd2019-tp1-api
- Código que inicia o servidor definido na classe microgram.impl.srv.soap.PostsSoapServer sd2019-tp1-code.
- Classe que implementa o web service do serviço definido na classe microgram.impl.srv.soap.PostsWebService sd2019-tp1-code. O código fornecido tem de ser renomeado e pode usar a implementação da funcionalidade do serviço (JavaPosts).
- Interface definida na classe microgram.api.soap.SoapPosts sd2019-tp1-api
-
Serviço Media Storage
- Este serviço não será implementado em SOAP. O exercício da aula 3 serve para exemplificar como se criariam as classes com o código que inicia o servidor e com o código do web service respetivo.
Classe microgram.impl.srv.soap.SoapResource sd2019-tp1-code é uma classe auxiliar com métodos genéricos para devolver resultados a partir dum objeto Result ou lançar uma exceção MicrogramException, usado nas classes que implementam a funcionalidade dos serviços.
Código do ProfilesWebService:
package microgram.impl.srv.soap;
...
public class ProfilesWebService extends SoapService implements SoapProfiles {
final Profiles impl;
protected ProfilesWebService() {
this.impl = new JavaProfiles();
}
@Override
public Profile getProfile( String userId ) throws MicrogramException {
return super.resultOrThrow( impl.getProfile(userId));
}
...
}
O código relativo à implementação de clientes REST dos vários serviços é disponibilizado nas seguintes classes:
-
Serviço Profiles
Código da classe que permite invocar o serviço REST Profiles: microgram.impl.clt.rest.RestProfilesClient sd2019-tp1-code. Esta classe implementa a interface Profiles. O código fornecido tem de ser renomeado e completado.
-
Serviço Posts
Código da classe que permite invocar o serviço REST Posts: microgram.impl.clt.rest.RestPostsClient sd2019-tp1-code. Esta classe implementa a interface Posts. O código fornecido tem de ser renomeado e completado.
-
Serviço Media Storage
Código da classe que permite invocar o serviço REST Media: microgram.impl.clt.rest.RestMediaClient sd2019-tp1-code. Esta classe implementa a interface Media -- ver aula prática 2.
Código do RestProfilesClient:
public class RestProfilesClient extends RestClient implements Profiles {
public RestProfilesClient(URI serverUri) {
super(serverUri, RestProfiles.PATH);
}
@Override
public Result<Profile> getProfile(String userId) {
Response r = target.path(userId)
.request()
.accept(MediaType.APPLICATION_JSON)
.get();
return super.responseContents(r, Status.OK, new GenericType<Profile>() {});
}
...
}
A classe RestClient tem um conjunto de métodos genéricos para processar as respostas REST e convertê-las para um objeto que implementa a interface Result.
O pacote microgram.impl.clt.java tem o código para criar clientes REST que, em caso de falha de comunicação, re-executam o pedido até obter uma resposta. Ver aula 4, exercício suplementar 2, para um exemplo de como usar.
public class RestMediaClient extends RestClient implements Media {
public RestMediaClient(URI mediaStorage) {
super(mediaStorage, RestMediaStorage.PATH);
}
public Result<String> upload(byte[] bytes) {
return super.reTry(() -> _upload_v2(bytes));
}
Result<String> _upload_v2(byte[] bytes) {
Response r = super.target.request().accept(MediaType.APPLICATION_JSON)
.post(Entity.entity(bytes, MediaType.APPLICATION_OCTET_STREAM));
return super.responseContents(r, Status.OK, new GenericType<String>() {
});
}
...
}
O código relativo à implementação de clientes SOAP dos vários serviços é disponibilizado nas seguintes classes:
-
Serviço Profiles
Código da classe que permite invocar o serviço SOAP Profiles: microgram.impl.clt.soap.SoapProfilesClient sd2019-tp1-code. Esta classe implementa a interface Profiles. O código fornecido tem de ser renomeado e completado.
-
Serviço Posts
Código da classe que permite invocar o serviço SOAP Posts: microgram.impl.clt.soap.SoapPostsClient sd2019-tp1-code. Esta classe implementa a interface Posts. O código fornecido tem de ser renomeado e completado.
Código do SoapPostsClient:
public abstract class SoapPostsClient extends SoapClient implements Posts {
SoapPosts impl;
public SoapPostsClient() {
this( Discovery.findUrisOf("???", 1)[0]); //TODO
}
public SoapPostsClient(URI serverUri) {
super(serverUri);
}
@Override
public Result<Post> getPost(String postId) {
return super.tryCatchResult(() -> impl().getPost(postId));
}
private SoapPosts impl() {
if( impl == null ) {
//TODO
}
return impl;
}
}
As classes dos clientes de REST e SOAP implementam as interfaces que definem as funcionalidades dos serviços. Assim, é possível aceder de formar uniforme aos servidores REST e SOAP. Ver aula 4, exercício suplementar 2, para ver como isso pode ser feito.
public class MediaClientFactory {
private static final String REST = "/rest";
private static final String SOAP = "/soap";
public static Media getMediaClient(URI uri) {
String uriString = uri.toString();
if (uriString.endsWith(REST))
return new RestMediaClient(uri);
else if (uriString.endsWith(SOAP))
return new SoapMediaClient(uri);
throw new RuntimeException("Unknown service type..." + uri);
}
}