Etiqueta: xml

java – convert between LocalDateTime and XMLGregorianCalendar

There are plenty of examples converting LocalDate to XMLGregorianCalendar but I couldn’t find any to convert from LocalDateTime except this post where I found the answer.

Instead of using the toString() method of the LocalDateTime we should use the format method with an ISO formatter.

LocalDateTime dt = LocalDate.now().atStartOfDay();

XMLGregorianCalendar xmlDateTime = DatatypeFactory.newInstance().newXMLGregorianCalendar(dt.format(DateTimeFormatter.ISO_DATE_TIME));

The reason is the former omits the seconds and nanoseconds if they’re zeros.

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Main {

    public static void main(String[] args) {
        LocalDateTime dt = LocalDate.now().atStartOfDay();
        System.out.println("LocalDateTime toString: " + dt.toString());
        System.out.println("LocalDateTime formatISO: " + dt.format(DateTimeFormatter.ISO_DATE_TIME));
    }
}

LocalDateTime toString: 2019-06-17T00:00
LocalDateTime formatISO: 2019-06-17T00:00:00
Anuncios

angular – Spring GetMapping with JSON parameter throwing HTTP 400 – Bad Request

I had a pretty simple REST service implemented with Spring Web and it was throwing a HTTP 400 – Bad Request Error.

This was the implementation

@GetMapping("titulos/preview")
    public void preview(@RequestParam String titulo, HttpServletResponse response) throws DatatypeConfigurationException, JAXBException, IOException {
        log.debug("REST request to preview Titulo: {}", titulo);
        Titulo tituloParsed = mapper.readValue(titulo, Titulo.class);
        String xml = titulosService.toXML(tituloParsed);
        String url = "http://birtviewer/viewer/run?__report=report/rptTitulo.rptdesign&__format=pdf";
        url += "&payload=" + URLEncoder.encode(xml, "utf-8");
        response.sendRedirect(url);
    }

Nothing wrong with it, it just receives JSON as a parameter and converts it to its XML representation in order to forward it to a BIRT report viewer instance. Still, it was throwing the aforementioned error whenever I was calling it from the client with a JSON payload, opening in a new window or tab.

window.open(`${this.resourceUrl}/preview?titulo=${JSON.stringify(titulo)}`, '_blank');

It turned out that I wasn’t URL encoding the JSON value before sending it to the service. This was causing the error due to the parameter not being recognized and being required by default. I just had to do that to get rid of the error.

window.open(`${this.resourceUrl}/preview?titulo=${encodeURIComponent(JSON.stringify(titulo))}`, '_blank');

sources:
https://stackoverflow.com/questions/29823626/angular-http-post-to-target-blank
https://stackoverflow.com/questions/38372134/how-to-convert-an-object-to-json-correctly-in-angular-2-with-typescript
https://stackoverflow.com/questions/40799609/set-headers-while-submitting-a-form-data
https://developer.mozilla.org/es/docs/Web/HTTP/Status/400

birt – create report from XML data sent as parameter

Not long ago I published an article on how to create a report from JSON sent as parameter. Now is the turn for XML data. The principles are almost the same.

We need to create a new XML data source pointing to a XML file which contains the actual data to be displayed on the report or the XSD definition file.

Screenshot from 2019-06-04 14-32-12

Screenshot from 2019-06-04 14-33-39

then we can define our Data Set using this Data Source

Screenshot from 2019-06-04 14-38-48

Screenshot from 2019-06-04 14-39-09

We need to select which node contains the records we’re going to show and map the fields accordingly.

Screenshot from 2019-06-04 14-39-46

Screenshot from 2019-06-04 14-39-58

Screenshot from 2019-06-04 14-40-44

Screenshot from 2019-06-04 14-40-53

Screenshot from 2019-06-04 14-41-06

Now we can drag and drop our Data Set to create a table in our report.

Screenshot from 2019-06-04 14-42-26

Screenshot from 2019-06-04 14-43-52

PDF
Screenshot from 2019-06-04 14-44-12

Let’s create our parameter named ‘payload’ which will receive the XML sent from the client.

Screenshot from 2019-06-04 14-45-11

now, let’s replace at runtime the XML within the file with the XML we received as parameter. Just add the following code to the script tab of the Data Source we created earlier.

importPackage( Packages.java.io );

xml = new java.lang.String(params['payload']);
bais = new ByteArrayInputStream(xml.getBytes());
ctx = reportContext.getAppContext();

ctx.put('org.eclipse.datatools.enablement.oda.xml.inputStream', bais);

boom! we’re done.

sources:
https://cirovladimir.wordpress.com/2019/05/15/birt-create-report-from-json-data-sent-as-parameter/

Use JSON as a Scripted Data Set


https://www.eclipse.org/forums/index.php/t/162952/

Java – Maven o Gradle

Maven

Maven es una herramienta de software para la gestión y construcción de proyectos Java –Wikipedia

Gradle

Gradle es una herramienta de automatización de proyecto que se basa en los conceptos de Apache Ant y Maven e introduce un lenguaje específico de dominio (DSL) basado en Groovy en lugar de la forma más tradicional de declarar la configuración del proyecto con XML.
Gradle fue diseñado para una solución multi-proyecto que puede llegar a ser bastante grande, y es compatible con compilaciones incrementales que determina inteligentemente qué partes del árbol de construcción han sido actualizadas, por lo que ninguna tarea dependendiente va a ser re-ejecutada. –Wikipedia

Hasta ahora había utilizado Maven como herramienta de gestión de proyectos, pero la siguiente afirmación me ha hecho pensar en utilizar Gradle para los nuevos proyectos

Google adopted Gradle as the default build tool for the Android OS –technologyconversations.com

Fuentes:

Java Build Tools: Ant vs Maven vs Gradle

Apache CXF – Ejemplo de firma de un documento XML

Apache CXF – Ejemplo de firma de un documento XML

Los beneficios de firmar digitalmente un documento XML en nuestros servicios web son que nos provee autenticación, integridad de los datos y el no repudio de la fuente que invoca el servicio.

Para ver un ejemplo de cómo puedes configurar Apache CXF para que utilice y verifique las firmas en un servicio web, sigue el enlace.

via Adding X.509 security headers to Apache CXF SOAP calls | Glen Mazza’s Weblog.

Java – Apache CXF archivos de configuración

Para configurar Apache CXF en una aplicación web, lo puedes hacer de muchas formas. Esto me confunde, ya que hay distintos ejemplos en internet.

Mi forma preferida es configurar un servlet en el archivo web.xml y configurar los servicios en un archivo beans.xml. Un ejemplo básico de estos archivos sería como el siguiente:

web.xml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<init-param>
<param-name>config-location</param-name>
<param-value>/WEB-INF/beans.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>

beans.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">

<import resource="classpath:META-INF/cxf/cxf.xml" />

<jaxws:endpoint id="HelloSOAP" address="/ws/helloService"
implementor="com.acme.ws.soap.HelloServiceImpl" />

<jaxrs:server id="rest-api" address="/rest">
<jaxrs:serviceBeans>
<bean id="HelloREST" class="com.acme.ws.rest.HelloREST" />
</jaxrs:serviceBeans>
</jaxrs:server>

</beans>

Las dependencias necesarias en Maven son las siguientes:


<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>

La dependencia a la librería spring-web es necesaria desde la versión 2.6 de Apache CXF. Las dependencias de SLF4J son opcionales, pero muy recomendables para ver la información del Log. Si quieres saber como configurar SLF4J puedes verlo aquí.

Fuentes:
Apache CXF — Servlet Transport.
http://stackoverflow.com/questions/6349424/apache-cxf-rs-extensions-issue-in-2-4-0

Java – Log4J xml vs properties configuration

Para saber cuáles son las ventajas y desventajas entre un formato y otro, puedes ver la siguiente discusión

http://stackoverflow.com/questions/1256835/why-chose-xml-over-properties-files-for-log4j-configuration

Desde mi punto de vista, deberíamos usar el formato XML.

Aquí dejo un ejemplo de un archivo de configuración properties y su equivalente en xml que encontré en esta página.

log4j.properties

# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<!-- A1 is set to be a ConsoleAppender -->
 <appender name="A1" class="org.apache.log4j.ConsoleAppender">
 <!-- A1 uses PatternLayout -->
 <layout class="org.apache.log4j.PatternLayout">
 <param name="ConversionPattern" value="%-4r [%t] %-5p %c %x - %m%n"/>
 </layout>
 </appender>

<root>
 <!-- Set root logger level to DEBUG and its only appender to A1 -->
 <priority value ="debug" />
 <appender-ref ref="A1" />
 </root>

</log4j:configuration>