FAQ Colaborativo de AISS

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 26

FAQ Colaborativo de AISS

Este documento se elabora de forma colaborativa para dar respuesta a los


problemas más frecuentes que nos podemos encontrar en las prácticas y
trabajo de AISS. Es responsabilidad de todos el mantenerlo.

Recuerda: si tras una tutoría se resuelve tu duda, debes comentar la solución


aquí1.

Índice

Índice

P01 - “Al desplegar en me dice que no estoy autorizado”.

P02 - “Al intentar ejecutar la aplicación dice algo de JDK”.

P02.1 - “Habilitar librería JDK por defecto para el proyecto actual”

P02.2 - “Habilitar librería JDK por defecto para todos los proyectos que se
creen”

P03 - “No puedo arrancar el servidor, el puerto está en uso”.

P04 - “La consola dice algo sobre dependencias que no se descargan bien”.

P05 - “Añadir un Header personalizado”.

P06 - “Codificar en base64”.

P07 - “La página JSP no permite meter/mostrar tildes”.

P08 - “La API me devuelve text/plain y no puedo procesarlo”.

P09 - “La URL de autorización necesita una sintaxis que es distinta a la que se envía
por defecto”.

P10 - “Al lanzar StartDevServer, no se lanza correctamente el proyecto y me


muestra este error”.

P11 - “Al hacer algo de oAuth me salta un mensaje de session not enabled”.

P12 - “Al ejecutar StartDevServer, en la consola aparece un error de Maven”.

P13 - “Al intentar hacer una consulta de un recurso, el servidor entiende la petición
pero no las instrucciones que contiene”.

P14 - “Resumen de la pregunta P13: El objeto JSON que me devuelve el servicio


1
Puedes usar http://hilite.me/ para formatear los fragmentos de código.
1
RESTful empieza y termina con “[ ]” en vez de con “{ }”, por lo que me da error al
convertirlo a objeto Java”.

P15 - ”Cambio de ruta archivo JSON”

P16 - ”Cómo saber si la llamada a la API devuelve lo esperado”

P17-”Cabeceras a añadir para hacer un ‘post’ que requiere una api key de
autenticación y el cuerpo a enviar es en formato json”

P18 - “¿Cómo se añaden las cabeceras accept y authorization c(que contiene:


“Bearer {API Key}”) en una petición HTTP?”.

P19-”Al hacer una llamada a la api en rest client de mozilla me da el error 503
Service Unavailable”

P20 - “Mi mashup puede realizar llamadas a un servicio RESTful desde localhost.
Sin embargo, cuando lo despliego en servidor, las llamadas no devuelven el JSON,
sino un mensaje 1001. ¿Por qué?”

P21 - “Al autenticar con OAuth2, el servicio RESTful no devuelve el access_token


directamente, sino un parámetro ‘code’ en su dirección URL. Se necesita hacer un
POST con ese ‘code’ para obtener el access_token (mirar también respuesta a P24)”

P22 - “Problema autenticación Oauth2 GitHub”.

P23 - “Hay veces que el servidor devuelve una respuesta cuyo cuerpo es como un
JSON, pero en la cabecera se indica que es algo diferente (es decir, que no es
application/json). Al hacer ClientResource.get(ClaseJava.class) para obtener el
objeto java, obtengo el error Unable to find a converter for this representation...”.

P24 - “Cuando autentico con OAuth2, no recibo el access token directamente, sino
que recibo un ‘code’ que luego tendré que usar como parámetro de una URL. Tras
hacer POST a esa URL, el servicio nos devuelve finalmente el access token”.

P25 - “Aunque en RESTeasy defino todo lo necesario para que funcione con UTF-8,
los ejemplos precargados en el repository tienen tilde/ñ/nombres de mueble de
Ikea… me salen mal codificados.”

P26 - “Las llamadas a la API de Google Books funcionan en local, pero al tenerlo
desplegado sale un error 403 (forbidden) tras la llamada.”

P27 - “Al darle a StartDevServer sale un mensaje de An illegal reflective access


operation has occurred”

P28 - “Al acceder a la documentación de Swagger desplegada, salta el error ‘Failed


to load API definition’”

P29 - “Cuando uso alguna API con OAuth2… me sale un error 500”.

P30 - “Me da un error 503, ¿qué ocurre?”.

2
P31 - “Deployments using appcfg are no longer supported”.

P32 - “HTTP Request incluyendo cabecera (OTRA FORMA)”.

P33 - “La API que he elegido solo tiene OAuth 1 y no quiero usar ninguna otra API”

P34 - “Failed to execute goal com.google.cloud.tools: appengine-maven-plugin”

P35 - “Al probar mi API con SwaggerHub me salta algún mensaje que pone CORS?”

P36 - “Copio el ejemplo de la API (lab8) como en Wuolah/otros y no me funciona


con Swagger/OAS 3”

PXX - “¿Conoces algún otro problema habitual?”.

P01 - “Al desplegar en me dice que no estoy autorizado”.


Te aparece una mensaje como este en la consola:

Aquí pueden suceder tres cosas:


A) El id del proyecto introducido en tu proyecto no se corresponde con el de
AppEngine en Google Cloud. Recuerda que hay que introducir el ID u y no el
nombre del proyecto.

B) En tu navegador se encuentra abierta una sesión de Google distinta a la


tuya. Cierra sesión y vuelve a probar.

C) El token fue inicialmente generado con otra cuenta o ha expirado. En este


caso debes eliminar el fichero .appcfg_oauth2_tokens_java, que se
encuentra en el directorio principal de usuario (ten en cuenta que el fichero
puede estar oculto).

C:\Users\practica > del .appcfg_oauth2_tokens_java

P02 - “Al intentar ejecutar la aplicación dice algo de JDK”.


Al arrancar el servidor local o desplegar en AppEngine la consola te muestra un
error como este:

3
Por defecto, en muchos ordenadores, Eclipse apunta al JRE de Java, por lo que no
podrá compilar adecuadamente desde los launch profiles. Es necesario cambiar al
JDK para poder realizar esta compilación de forma correcta.

Se describen dos soluciones, la primera para hacer que el proyecto actual apunte a
la librería JDK de Java, y la segunda para que todos los proyectos que se hagan en
adelante apunten a dicha librería.

P02.1 - “Habilitar librería JDK por defecto para el proyecto actual”

Hay que hacer como se muestra a continuación:

En Window->Preferences:

Accedemos a Installed JREs:

4
Cambiamos el JRE por el JDK pulsando Edit:

En JRE home ponemos la localización del JDK instalado (si no ha sido instalado, hay
que descargarlo desde esta URL2:

P02.2 - “Habilitar librería JDK por defecto para todos los proyectos que se creen”

Para no tener que aplicar la solución de la pregunta P02 en cada proyecto Eclipse
que hagamos, podemos hacer que nuestro Eclipse apunte a la librería JDK en todos
los proyectos nuevos que hagamos.

Para ello, hay que modificar el fichero eclipse.ini. El contenido del fichero eclipse.ini
del Eclipse JEE IDE 2018-12 versión Windows 64 bits es:

-startup
plugins/org.eclipse.equinox.launcher_1.5.200.v20180922-1751.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.900.v20180922-17
51
-product
org.eclipse.epp.package.jee.product
-showsplash
org.eclipse.epp.package.common
--launcher.defaultAction
openFile
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.8
[email protected]/eclipse-workspace
-XX:+UseG1GC
-XX:+UseStringDeduplication

2
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

5
--add-modules=ALL-SYSTEM
-Dosgi.requiredJavaVersion=1.8
-Dosgi.dataAreaRequiresExplicitInit=true
-Xms256m
-Xmx1024m
--add-modules=ALL-SYSTEM

Se debe modificar de la siguiente forma (las líneas nuevas aparecen en azul):

-startup
plugins/org.eclipse.equinox.launcher_1.5.200.v20180922-1751.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.900.v20180922-17
51
-product
org.eclipse.epp.package.jee.product
-showsplash
org.eclipse.epp.package.common
--launcher.defaultAction
openFile
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vm
C:/Program Files/Java/jdk1.8.0_131/bin/javaw.exe (la ruta donde se
6
encuentre la librería Java JDK )
-vmargs
-Dosgi.requiredJavaVersion=1.8
[email protected]/eclipse-workspace
-XX:+UseG1GC
-XX:+UseStringDeduplication
--add-modules=ALL-SYSTEM
-Dosgi.requiredJavaVersion=1.8
-Dosgi.dataAreaRequiresExplicitInit=true
-Xms256m
-Xmx1024m
--add-modules=ALL-SYSTEM

P03 - “No puedo arrancar el servidor, el puerto está en uso”.


Para arrancar el servidor siempre estamos usando el lauch profile
“StartDevServer.launch”, pero no debemos olvidar que para parar el servidor
es necesario ejecutar el “StopDevServer.launch”.

Si el error sigue apareciendo tras ejecutar el último launch profile será necesario
parar el proceso Java y Javaw desde el administrador de tareas en Windows o
desde una terminal en otros sistemas.

P04 - “La consola dice algo sobre dependencias que no se


descargan bien”.
A veces las dependencias de bibliotecas externas no se descargan adecuadamente,
(esto puede producirse, por ejemplo, por algún problema o micro-corte en la red).
Esto provoca que el código no pueda ser compilado adecuadamente y, por tanto,
nuestro servidor no se pueda arrancar.

A veces, aparece un mensaje del estilo: “invalid LOC header (bad signature)”.

Una posible solución es intentar a volver a construir nuestro proyecto, haciendo


click derecho sobre él -> Maven -> Update project.

7
Si continúa ocurriendo, una solución (aunque algo drástica) es eliminar todo el
repositorio local de Maven para así forzar la descarga de todas las dependencias de
nuevo.

Para ello, es preciso borrar el directorio “.m2”, que se encuentra en nuestro


directorio de usuario (ten en cuenta que el directorio puede estar oculto).

C:\Users\antonio > rmdir -s .m2

P05 - “Añadir un Header personalizado”.


La solución de abajo solo vale para headers personalizados. Si quieres añadir un
header ‘habitual’ (como ‘Accept’ o ‘Authorization’), la biblioteca restlet dará un
error.

@SuppressWarnings("unchecked")
public void addHeader(ClientResource cr, String headerName, String headerValue) {
Series<Header> headers = (Series<Header>) cr.getRequest().getAttributes()
.get(HeaderConstants.ATTRIBUTE_HEADERS);

if (headers == null) {
headers = new Series<Header>(Header.class);
cr.getRequest().getAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS,
headers);
}
headers.add(headerName, headerValue);
}

//Ejemplo:
addHeader(cr, "Ocp-Apim-Subscription-Key", BING_API_KEY);

//Import ‘Header’ (org.restlet.data)

P06 - “Codificar en base64”.


String str = "77+9x6s=";

8
// encode data using BASE64
String encoded = DatatypeConverter.printBase64Binary(str.getBytes());
System.out.println("encoded value is \t" + encoded);

// Decode data
String decoded = new String(DatatypeConverter.parseBase64Binary(encoded));
System.out.println("decoded value is \t" + decoded);

System.out.println("original value is \t" + str);

P07 - “La página JSP no permite meter/mostrar tildes”.


<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>

P08 - “La API me devuelve text/plain y no puedo procesarlo”.


Hay que crear un ObjectMapper.

Un ejemplo de ObjectMapper sería el siguiente:

ClientResource cr = new ClientResource(url);

ObjectMapper objectMapper = new ObjectMapper();

ClaseJava claseJava = objectMapper.readValue(cr.get(String.class), ClaseJava.class);

También se deberá cambiar manualmente todos los atributos de las clases


afectadas de camelCase a snake_case dado que de esta forma no es capaz de
traducirlo por el método @JsonProperty.

Esta solución también es válida para diferentes tipos de respuestas como


[text/javascript,UTF-8] entre otras.

P09 - “La URL de autorización necesita una sintaxis que es


distinta a la que se envía por defecto”.
//TODO

P10 - “Al lanzar StartDevServer, no se lanza correctamente el


proyecto y me muestra este error”.
FATAL ERROR in native method: JDWP No transports
initialized, jvmtiError=AGENT_ERROR_TRANSPORT_INIT(197)
9
[INFO] ERROR: transport error 202: bind failed: Address
already in use
[INFO] ERROR: JDWP Transport dt_socket failed to
initialize, TRANSPORT_INIT(510)
[INFO] JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No
transports initialized [debugInit.c:750]

→ Aplicar solución indicada en P03 y listo :)

P11 - “Al hacer algo de oAuth me salta un mensaje de session


not enabled”.
Asegúrate de que estás usando la última versión del proyecto plantilla:
https://github.com/aiss-us/aiss-project-template/

P12 - “Al ejecutar StartDevServer, en la consola aparece un


error de Maven”.
Empieza así:

[ERROR] Failed to execute goal


com.google.appengine:appengine-maven-plugin:1.9.46:devserve
r (default-cli) on project lab2-java-server: Execution
default-cli of goal
com.google.appengine:appengine-maven-plugin:1.9.46:devserve
r failed: Unable to load the mojo 'devserver' in the plugin
'com.google.appengine:appengine-maven-plugin:1.9.46'. A
required class is missing:
com.google.appengine.devappserver.DevAppServerRunner

[ERROR]
-----------------------------------------------------

[ERROR] realm =
plugin>com.google.appengine:appengine-maven-plugin:1.9.46

[ERROR] strategy =
org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy

[ERROR] urls[0] =
file:/C:/Users/.m2/repository/com/google/appengine/appengin
e-maven-plugin/1.9.46/appengine-maven-plugin-1.9.46.jar

[ERROR] urls[1] =
file:/C:/Users/TU_USUARIO/.m2/repository/commons-io/commons
-io/1.3.2/commons-io-1.3.2.jar

10
SOLUCIÓN: El error radica de una instalación incompleta o errónea. Basta con
borrar la carpeta “C:\Users\Nombre_Usuario\.m2” y volver a ejecutar el fichero
“StartDevServer.launch”; de esta manera, eclipse vuelve a descargar los recursos
necesarios para ejecutar el fichero con m2.

P13 - “Al intentar hacer una consulta de un recurso, el servidor


entiende la petición pero no las instrucciones que contiene”.
Captura error:

El problema en este caso reside en que el json devuelto es un array de elementos:

Nótese que el contenido empieza por “[“. Por lo tanto a la hora de implementar el
método consulta debemos obtener un array de objetos, en lugar de un sólo objeto:

P14 - “Resumen de la pregunta P13: El objeto JSON que me


devuelve el servicio RESTful empieza y termina con “[ ]” en vez
de con “{ }”, por lo que me da error al convertirlo a objeto Java”.
En este caso, lo más seguro es que el servicio RESTful te esté devolviendo una lista
de objetos JSON en vez de un sólo objetos.

Imaginémonos que el objeto JSON lo queremos convertir en un objeto Playlist. En


el caso normal (cuando el servicio RESTful nos devuelve sólo un objeto JSON)

11
haríamos:

Client Resource cr = null;


Playlist list = null;
try {
cr = new ClientResource(uri);
list = cr.get(Playlist.class);
} catch …

En el caso que el servicio RESTful devuelva una lista de objetos JSON, tenemos que
hacer:

Client Resource cr = null;


Playlist[] list = null;
try {
cr = new ClientResource(uri);
list = cr.get(Playlist[].class);
} catch …

P15 - ”Cambio de ruta archivo JSON”


El archivo JSon OAuthConfig.json se encuentra por defecto en el proyecto plantilla
en DeployedResources/webapp/WEB-INF. Sin embargo, el fichero se debe
encontrar en: src/main/resources/WEB-INF para que los controladores por
puedan encontrarlo.

Otro problema que puede ocurrir es que el JSON no esté bien formado y no se
pueda leer. Para comprobar que es válido, se puede usar la herramienta
https://jsoneditoronline.org/

P16 - ”Cómo saber si la llamada a la API devuelve lo esperado”


Imprime por consola la respuesta del metodo GET.

ClientResource cr = new ClientResource();


String s = cr.get(String.class);
System.out.println(s);

12
P17-”Cabeceras a añadir para hacer un ‘post’ que requiere una
api key de autenticación y el cuerpo a enviar es en formato
json”
Añadir las siguientes líneas de código al final del método en el cual invocamos al
método POST:

ChallengeResponse chr = new


ChallengeResponse(ChallengeScheme.HTTP_OAUTH_BEARER);
chr.setRawValue(access_token);
cr.setChallengeResponse(chr);

cr.post(comentario, MediaType.APPLICATION_ALL_JSON);
//MediaType.APPLICATION_ALL_JSON establece Json como
formato del cuerpo del método post

P18 - “¿Cómo se añaden las cabeceras accept y


authorization c(que contiene: “Bearer {API Key}”) en una
petición HTTP?”.

P19-”Al hacer una llamada a la api en rest client de mozilla me


da el error 503 Service Unavailable”
//TODO

13
P20 - “Mi mashup puede realizar llamadas a un servicio RESTful
desde localhost. Sin embargo, cuando lo despliego en servidor,
las llamadas no devuelven el JSON, sino un mensaje 1001. ¿Por
qué?”
El problema, en general con este tipo de errores, es que el modo de hacer
peticiones con el servidor integrado en el modo de despliegue local es distinto a
cuando se usa la infraestructura de AppEngine.

Hay más información aquí:


https://cloud.google.com/appengine/docs/standard/java/issue-requests#java_8_r
untime_vs_java_7_behavior

La solución es añadir en el app-engine.xml el parámetro “url-stream-handler” con


el valor “urlfetch”, tal y como se muestra abajo:

<xml version="1.0" encoding="utf-8">

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">

<!-- ... -->

<url-stream-handler>urlfetch</url-stream-handler>

<!-- ... -->

</appengine-web-app>

P21 - “Al autenticar con OAuth2, el servicio RESTful no devuelve


el access_token directamente, sino un parámetro ‘code’ en su
dirección URL. Se necesita hacer un POST con ese ‘code’ para
obtener el access_token (mirar también respuesta a P24)”
Al implementar la autenticación OAuth 2.0 de GitHub, nos hemos encontrado con
una excepción de la librería de Google.

GitHub por defecto devuelve una respuesta de tipo texto (Content-Type: text/html),
lo que provoca que la librería Google-oauth2 lance una excepción.

Para solucionar este error, hemos añadido la cabecera Accept: application/json que
pide al servidor que nos devuelva una respuesta JSON

Modificación archivo TokenRequest.java (Línea 269)

14
P22 - “Problema autenticación Oauth2 GitHub”.
Respuesta por el grupo PlaceHolder (Grupo 4):

GitHub por defecto devuelve una respuesta tipo texto (Content-Type: text/html), lo
que provoca que la librería Google-oauth2 lance una excepción.
Para solucionar este error, se ha de añadir la cabecera Accept: application/json que
pide al servidor que nos devuelva una respuesta JSON.
Para ello hay que modificar el archivo TokenRequest.java situado en el paquete
aiss.controller.oauth. En específico la línea 269:

HttpHeaders headers = new HttpHeaders();


headers.setAccept("application/json");

HttpRequest request =// MODIFICACION PARA GITHUB


HttpHeaders headers = new HttpHeaders();

headers.setAccept("application/json");

HttpRequest request = requestFactory.buildPostRequest(

tokenServerUrl, new UrlEncodedContent(this));

request.setHeaders(headers);

requestFactory.buildPostRequest(tokenServerUrl, new
UrlEncodedContent(this);
request.setHeaders(headers);

Esperamos que haya servido de ayuda al grupo que lo necesitaba.

15
P23 - “Hay veces que el servidor devuelve una respuesta cuyo
cuerpo es como un JSON, pero en la cabecera se indica que es
algo diferente (es decir, que no es application/json). Al hacer
ClientResource.get(ClaseJava.class) para obtener el objeto java,
obtengo el error Unable to find a converter for this
representation...”.
Hay servicios que a veces, al realizar la consulta, no devuelven application/json en
su cabecera, si no que devuelven otro formato como podría ser geojson para
mapas, o cualquier otro. En este caso puede que el test y nuestra aplicación nos
aporte un error “Unable to find a converter…”, que se puede solventar de varias
formas, pero aporto dos.

import org.codehaus.*;

import org.restlet.*;

Representation representation = cr.get(); // cr es ClientResource con uri

//Definimos ObjectMapper para extraer el cuerpo de la respuesta:

ObjectMapper mapper = new ObjectMapper();

//Extraemos el cuerpo de la respuesta:

JsonNode jsonNode = mapper.readTree(representation.getStream());

//Y lo convertimos en cadena de texto

String JSONContent = jsonNode.toString();

//Finalmente, usamos otro ObjectMapper para convertir el texto en objecto Java

ObjectMapper mapper2 = new ObjectMapper();

Search search = mapper2.readValue(JSONContent, Search.class)

return search;

16
// Forma 2 //

URL url = new URL(uri);

HttpURLConnection con = (HttpURLConnection) url.openConnection();

con.setRequestProperty(HttpHeaders.ACCEPT, "application/vnd.problem+json;
charset=utf-8"); //problem sería el MediaType que os aporta el error

con.setRequestMethod(HttpMethods.GET);

BufferedReader in = new BufferedReader(new


InputStreamReader(con.getInputStream()));

String inputLine;

StringBuffer content = new StringBuffer();

while ((inputLine = in.readLine()) != null) {

content.append(inputLine);

in.close();

Gson g = new Gson();

Search search = g.fromJson(content.toString(), Search.class);

return search;

La primera forma lo resuelve convirtiendo la respuesta en un String, guardandolo


en un objeto JAVA y luego lee el json de ese objeto, para así tener un json de
resultado. El segundo método es parecido pero hace uso de la librería de Google
Gson, para serializar y deserializar objetos JAVA directamente. Tener en cuenta que
al crear los POJO cambiamos el método snake_case por camelCase, normalmente

17
jsonschema2pojo hace ésto automáticamente, pero al usar estos métodos
necesitamos dejarlo tal cual venía originalmente, cambiandolo manualmente.

P24 - “Cuando autentico con OAuth2, no recibo el access token


directamente, sino que recibo un ‘code’ que luego tendré que
usar como parámetro de una URL. Tras hacer POST a esa URL, el
servicio nos devuelve finalmente el access token”.
Respuesta por el grupo Project DAPP.

En nuestro caso el problema era al intentar obtener el access token de la API de


Unsplash, ya que, como se expone en la pregunta, constaba de dos pasos: el
primero, obtener el authentication code y después usar ese code como parámetro
al hacer POST a una URL de donde sacar el access token.

Explicaremos la situación paso a paso ya que puede que otras APIs presenten la
misma problemática. Para entender mejor el problema lo mejor es entender cómo
autenticarse en la API de Unsplash:

Para obtener el authentication code pondremos en el navegador la URL con los


parámetros que nos indican, devolviéndonos lo siguiente:

18
A nivel de código lo sacaremos con el proporcionado por los laboratorios de la
asignatura:

Aunque se coja como atributo “Unsplash-token”, realmente estamos recibiendo el


authentication code.

Ahora llegamos a la parte que generó una problemática a nuestro grupo: cómo
sacar un parámetro de un POST a una URL.

Bien, desde la API de Unsplash nos indican cómo formar la URL y nos dan el
recurso JSON devuelto por lo que cogemos el recurso y lo pasamos a clase Java con
www.jsonschema2pojo.org, para después poder elegir el parámetro que queremos
obtener del POST, en nuestro caso usaremos getAccessToken().

A continuación, el código para hacer un POST a una URL:

19
Primero, creamos el String con el contenido de la URL y la variable result donde
devolveremos el access token. Creamos un ClientResource con la URL que hemos
creado y dentro de result hacemos POST al ClientResource sacando el access token
de lo que nos ha devuelto la función con getAccessToken().

AccessToken.class representa la clase que hemos creado a partir del JSON que nos
proporciona la API.

P25 - “Aunque en RESTeasy defino todo lo necesario para que


funcione con UTF-8, los ejemplos precargados en el repository
tienen tilde/ñ/nombres de mueble de Ikea… me salen mal
codificados.”

La solución es sencilla. La configuración por defecto para la codificación de los


ficheros Java en Eclipse NO es UTF-8. Hay dos opciones: 1) pelearse con Eclipse
para cambiar el encoding por defecto (Window -> Preferences -> General ->
Workspace : Text file encoding). 2) Abrir el fichero con Notepad++ y clicar en
“Encoding > Convert to UTF-8 (option without BOM)”

P26 - “Las llamadas a la API de Google Books funcionan en local,


pero al tenerlo desplegado sale un error 403 (forbidden) tras la
llamada.”
El problema se explica aquí:
https://stackoverflow.com/questions/36803145/gae-google-books-api.
Básicamente, por cuestiones de derechos de autor, Google necesita saber desde qué
país se está realizando la petición, por lo que hay que añadir el país como
parámetro en la búsqueda (&country=es)

20
P27 - “Al darle a StartDevServer sale un mensaje de An illegal
reflective access operation has occurred”
Esto ocurre porque estamos usando la versión >1.8 del JDK de Java. Debemos
instalar la 1.8 para solucionar este problema
(https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-
2133151.html)

P28 - “Al acceder a la documentación de Swagger desplegada,


salta el error ‘Failed to load API definition’”
Puede que nos aparezca un error como el siguiente:

En este caso, estamos accediendo a la aplicación a través del protocolo “http” (al
lado de la URL aparece “No es seguro”). Sin embargo, al incluir la documentación
de Swagger en el proyecto, pusimos la URL con “https” en el fichero
/docs/index.html, tal que así:

21
Para resolver el error, basta acceder a la aplicación a través del protocolo “https”.

P29 - “Cuando uso alguna API con OAuth2… me sale un error


500”.
Este problema es bastante frecuente, por ejemplo, es conocido que la API de Twitch
también da problemas relacionados con esto.

Si te sale un mensaje que incluye algo como “JsonParser”, el problema es el


siguiente:

El motivo es que OAuth2 define en sun RFC unos formatos concretos de mensajes
en JSON. Por ejemplo, el scope debe ser un string con los valores separados por
comas y no un array. Estas pequeñas sutilezas hacen que algunas APIs lo
implementen de forma ligeramente diferente y, por desgracia, al usar una
herramienta genérica, nos falle.

En la nueva versión de la práctica 7 y proyecto plantilla se han implementado unos


cambios que permiten adaptar el formato del mensaje del token.

La clase CustomTokenResponse (que extiende a TokenResponse, de la biblioteca


que usamos para OAuth) se encarga de deserializar el mensaje (como lo que
hacemos con el json2pojo) y convertirlo al formato oficial RFC.

22
Por ejemplo, para el caso de Twitch:

Problema: expiresIn lo dan como Integer (debería ser un Long) y scope como
List<String> (debería ser un String del tipo “algo,algo,algo,algo”)

● Modificamos el tipo el atributo expiresIn para que sea un Integer


● En el getter hacemos la conversión a Long
○ public Long getExpiresInSeconds() { return
expiresInSeconds.longValue(); }

● Modificamos el tipo del atributo scope a List<String>


● En el getter hacemos la conversión a String:
○ public String getScope() { return
String.join(",", scope); }

Es una solución que puede constar trabajo pillarla al principio, pero que resulta
más sencilla que implementar tu propia petición POST manualmente.

Si tienes dudas, recuerda que tu profesor/a de prácticas estará ahí para ayudarte :)

P30 - “Me da un error 503, ¿qué ocurre?”.


Los errores 5XX son siempre errores del lado del servidor. El mejor consejo ante
este tipo de errores es siempre -mirar el log- en eclipse.

Por ejemplo, un error habitual es "javax.servlet.UnavailableException: Servlet class


aiss.controller.myController is not a javax.servlet.Servlet". Esto se soluciona
haciendo que myController extienda a la clase HttpServlet.

P31 - “Deployments using appcfg are no longer supported”.


En abril de 2020 se produjeron cambios en Google Cloud para realizar el
despliegue. Cualquier proyecto anterior a esa fecha no puede ser directamente
desplegado sin antes realizar un par de cambios. Las instrucciones para esto
estarán disponibles junto al resto del material de la asignatura.

Recuerda que la última versión del proyecto plantilla siempre se encuentra en


https://github.eii.us.es/aiss-us/aiss-project-template

---

En este curso 19/20 hemos publicado en la carpeta de la práctica 4 las


instrucciones, en vídeo y pdf, para la creación de una cuenta en Google Cloud y el
despliegue de la aplicación tras estas nuevas actualizaciones.

23
Hemos publicado un nuevo vídeo para ayudar en los pasos necesarios para realizar
la migración: https://www.youtube.com/watch?v=bGc9tlU1kRo

P32 - “HTTP Request incluyendo cabecera (OTRA FORMA)”.


Para usar este método es necesario incluir en el archivo pom.xml en el apartado de
dependencias la siguiente: (estas incluirán la librería OkHTTP)

<dependency>

<groupId>com.squareup.okhttp</groupId>

<artifactId>okhttp</artifactId>

<version>2.5.0</version>

</dependency>

Ahora haremos la HTTPRequest (en la clase Resource). El código de abajo es muy


similar para cualquiera.

uri = String de la url de nuestra api con los parámetros...

Simplemente cambiar los headers según los que tu api pida.

De esta forma para hacer la llamada a la api no hace falta el ClientResource.

Como vemos devuelve un string y no un objeto JSON. Si queremos parsearlo a JSON


podemos hacerlo como viene en la forma 1 de la P23 del FAQ. En ese código lo
único a cambiar sería la siguiente línea y ponerla así:

JsonNode jsonNode = mapper.readTree(search);

No hace falta usar “Representation representation”. El resto del código es igual.

Si a la hora de mostrarlo en nuestro mashup diera algún error del tipo “not marked
as ignorable” bastaría con seguir lo que pone en las diapositivas de la práctica 5
24
para cada clase java en la que hiciera falta.

P33 - “La API que he elegido solo tiene OAuth 1 y no quiero usar
ninguna otra API”
Todo el código que se ofrece en la asignatura está preparado para OAuth2. La
versión 1 de este protocolo incorpora más complejidad (ej. hay que firmar la
petición con un protocolo HMAC) del lado del cliente y prácticamente está en
desuso hoy en día.

No obstante, si estás muy interesado en seguir usando OAuth1, puedes usar esta
biblioteca externa: https://github.com/scribejava/scribejava

Tendrás que implementar manualmente los servlets para gestionar el callback y la


autorización, pero con esa librería no hay que gestionar nada demasiado complejo.

P34 - “Failed to execute goal com.google.cloud.tools:


appengine-maven-plugin”
La causa raíz del problema no es conocida todavía (si alguien la sabe, que actualice
esta respuesta :P), pero en muchos casos se arregla de la siguiente forma:

1) matar los procesos java.exe y javaw.exe

2) borrar el directorio %USERPROFILE%\AppData\Local\google\ct4j-cloud-sdk

25
3) probar de nuevo

P35 - “Al probar mi API con SwaggerHub me salta algún mensaje


que pone CORS?”
El problema se explica bien aquí:
https://hackernoon.com/how-cors-cross-origin-resource-sharing-works-292z32g0

Para arreglarlo, basta con seguir estas instrucciones:

https://www.codepedia.org/ama/how-to-enable-cors-filter-in-resteasy

P36 - “Copio el ejemplo de la API (lab8) como en Wuolah/otros


y no me funciona con Swagger/OAS 3”

Es totalmente normal. Si usas una versión antigua y ‘no oficial’ siempre habrá
errores y problemas...

El proyecto plantilla y las prácticas se actualizan con frecuencia en el GitHub de la


asignatura. No podemos dar soporte/ayuda sobre proyectos antiguos y
desactualizados con orígenes inciertos.

Para este problema basta con coger la última versión de Swagger-UI aquí:
https://github.com/swagger-api/swagger-ui/releases

PXX - “¿Conoces algún otro problema habitual?”.

26

También podría gustarte