Getting multiple instances of a CDI bean

This is a simple and quick post to show you how to get multiple implementations of a single interface when you are using the CDI context or even EJB.

Let’s develop a sample interface with two basic implementations:

public interface SimpleService {

    String doSomething();

}
import javax.inject.Named;

@Named
public class SomeSimpleService implements SimpleService {

    @Override
    public String doSomething() {
        return "Some single service";
    }

}
import javax.inject.Named;

@Named
public class OtherSimpleService implements SimpleService {

    @Override
    public String doSomething() {
        return "Other single service";
    }

}

We must consider that you could have a lot more implementations of this interface. For some reason, in this case you have to use all the implementations and call a method of each one of them.

The keypoint to do this is to use the @Any annotation and the Instance interface.

An example of its use in a stateless EJB can be done this way:

import java.util.Iterator;

import javax.ejb.Stateless;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;

@Stateless
public class StatelessBean {

    @Inject @Any
    private Instance<SimpleService> simpleService;

    public void doSomethingWithAllSimpleServices() {
        Iterator<SimpleService> services = simpleService.iterator();
        while (services.hasNext()) {
            System.out.println(services.next().doSomething());
        }
    }

}

Very simple, right? ūüôā

With this approach, you could also think in getting “any bean” of that type. For this, create another method in StatelessBean class:

[...]

    public void doSomethingWithAnySimpleService() {
        System.out.println(simpleService.get().doSomething());
    }

[...]

It’s just this for today. Hope it can help you.
See you soon.

Advertisements

java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

Today I faced an error that I’ve never seen before:

java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty

This situation was happening when I was executing any Maven command in a new virtual machine with Ubuntu 15.10 and JDK 1.8. The solution for me was very simple, I just had to reconfigure Java certificates installed on that machine.

I used this command:

sudo /var/lib/dpkg/info/ca-certificates-java.postinst configure

I’m not sure why exactly this error was happening, but seems that is a kind of bug in installing the JDK 1.8 via apt-get command.

That’s all for today. See you.

Getting Spring beans programmatically

Something very common in projects with Spring is the need to get Spring beans in objects not managed by Spring. One example is when you are developing a custom manner to audit Hibernate entities using event listeners (this is subject to another post, actually).

The better option we have to allow this is to create a bean that implements the org.springframework.context.ApplicationContextAware interface. According to the documentation:

Implementing this interface makes sense for example when an object requires access to a set of collaborating beans. Note that configuration via bean references is preferable to implementing this interface just for bean lookup purposes.

A possible and simple implementation of this interface is:

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class ContextProvider implements ApplicationContextAware {

    private static ApplicationContext CONTEXT;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        CONTEXT = applicationContext;
    }

    /**
     * Get a Spring bean by type.
     **/
    public static <T> T getBean(Class<T> beanClass) {
        return CONTEXT.getBean(beanClass);
    }

    /**
     * Get a Spring bean by name.
     **/
    public static Object getBean(String beanName) {
        return CONTEXT.getBean(beanName);
    }

}

Take a look at the class above. It’s a simple bean (annotated with @Component) that implements the referenced Spring interface and, because of this, is notified about the creation of the Spring context.

When this happens, the Spring application context is put in an unique (static) object. This way, the static methods #getBean can find any managed bean making use of Spring context.

If you want to see an example of this working, take a look at this example project in my GitHub account.

See you.

Removing XML declaration in WS request

So, I was there: two days after the web services owner tell me that I had to consume their services without¬†the XML declaration in the SOAP request, I didn’t know how to do this yet.

I’ve no idea how many¬†articles and documentations I read, neither about how many attempts I made. Nothing seemed to change that damned that was sent automatically in the top of my SOAP request.

At that time, I was working in a project using the default implementation for web services in Java, JAX-WS. I figured out a solution for my case using some parts of Apache CXF and in this post I intend to show you detailed examples about how to do this.

Publishing sample web service

Firstly, we must to¬†develop a simple web service and publish it so we can test the WSDL. To do this, let’s begin creating a default Maven project called ws-soap-publisher¬†(you can delete all¬†the¬†dependencies and classes automatically generated by Maven).

mvn archetype:generate
  -DarchetypeArtifactId=maven-archetype-quickstart
  -DinteractiveMode=false
  -DgroupId=com.brunozambiazi
  -DartifactId=ws-soap-publisher
  -Dversion=1.0.0
  -Dpackage=com.brunozambiazi.ws.publisher

Open pom.xml and add the JAX-WS dependency:

<dependencies>
  <dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.2.10</version>
  </dependency>
</dependencies>

Now, let’s create a simple web service class with just one service method to print a message:

package com.brunozambiazi.ws.publisher;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService
public class HelloWebService {

    @WebMethod
    public void print(@WebParam String something) {
        System.out.format("Printing '%s'", something);
    }

}

We also have to create a simple class to publish the web service on port 8080. After creating the class, just run it.

package com.brunozambiazi.ws.publisher;

import javax.xml.ws.Endpoint;

public class Publisher {

    public static void main(String[] args) {
        System.setProperty("com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true");
        System.setProperty("com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true");
        System.setProperty("com.sun.xml.ws.transport.http.HttpAdapter.dump", "true");
        System.setProperty("com.sun.xml.internal.ws.transport.http.HttpAdapter.dump", "true");

        System.out.println("Publishing service...");
        Endpoint.publish("http://localhost:8080/helloWebService", new HelloWebService());
    }

}

Notice that the first four lines of code in the main method, are just some properties being enabled. This properties are necessary to log the HTTP transport layer, so we can see all the data received as request and sent as response of the web service.

By now, open the browser and try to access the address http://localhost:8080/helloWebService?wsdl. If everything is ok, you will see the contract generated for who wants to consume your web service.

If you want, you can test this web service using a client like SoapUI.

Consuming the web service

Let’s proceed creating a project called ws-soap-consumer to consume and test the web service (again, you can delete all the dependencies and Maven auto generated classes).

mvn archetype:generate
  -DarchetypeArtifactId=maven-archetype-quickstart
  -DinteractiveMode=false
  -DgroupId=com.brunozambiazi
  -DartifactId=ws-soap-consumer
  -Dversion=1.0.0
  -Dpackage=com.brunozambiazi.ws.consumer

Now, edit pom.xml to configure the JAX-WS Maven Plugin. This plugin will generate automatically all the necessary stubs to consume the web service.

<build>
  <plugins>
    <plugin>
      <groupId>org.jvnet.jax-ws-commons</groupId>
      <artifactId>jaxws-maven-plugin</artifactId>
      <version>2.3</version>
      <executions>
        <execution>
          <goals>
            <goal>wsimport</goal>
          </goals>
          <configuration>
            <vmArgs>
              <vmArg>-Djavax.xml.accessExternalSchema=all</vmArg>
            </vmArgs>
            <wsdlUrls>
              <wsdlUrl>http://localhost:8080/helloWebService?wsdl</wsdlUrl>
            </wsdlUrls>
            <sourceDestDir>src/main/java</sourceDestDir>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Execute the project with Maven, running with the package phase. You’ll notice that some classes were generated inside a new package with the same name as the main package of the other project. At that time, your project must seem like this:

ws-soap-consumer-project

To finish this part, let’s create the class to consume the web service:

package com.brunozambiazi.ws.consumer;

import com.brunozambiazi.ws.publisher.HelloWebService;
import com.brunozambiazi.ws.publisher.HelloWebServiceService;

public class Consumer {

    public static void main(String[] args) {
        HelloWebServiceService service = new HelloWebServiceService();
        HelloWebService port = service.getHelloWebServicePort();
        port.print("First consumer!");
    }

}

The problem

Ok, we have all the necessary stuffs to see the “problem” happenning. (At least for me this was a problem…)

First of all, run the publisher class. You must see the output message “Publishing service…”.

Now, run the consumer class. The complete output must be something like this:

---[HTTP request]---
Accept: text/xml, multipart/related
Connection: keep-alive
Host: localhost:8080
User-agent: JAX-WS RI 2.2.10 svn-revision#919b322c92f13ad085a933e8dd6dd35d4947364b
Content-type: text/xml; charset=utf-8
Soapaction: "http://publisher.ws.brunozambiazi.com/HelloWebService/printRequest"
Content-length: 234
<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:print xmlns:ns2="http://publisher.ws.brunozambiazi.com/"><arg0>First consumer!</arg0></ns2:print></S:Body></S:Envelope>--------------------

Printing 'First consumer!'---[HTTP response 200]---
Date: Sat, 19 Dec 2015 01:03:29 GMT
Transfer-encoding: chunked
Content-type: text/xml; charset=utf-8
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:printResponse xmlns:ns2="http://publisher.ws.brunozambiazi.com/"></ns2:printResponse></S:Body></S:Envelope>--------------------

Do you see the  in line 9? This is the damned!

The solution

After numerous attemps and research, I solved my problem just replacing the JAX-WS dependency by two modules of Apache CXF.

So, open the consumer’s project¬†pom.xml and let the dependencies tag this way:

<dependencies>
  <dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.1.4</version>
  </dependency>
  <dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.1.4</version>
  </dependency>
</dependencies>

Now, try again. Run the consumer class and take a look at the output:

---[HTTP request]---
Accept: */*
Connection: keep-alive
Host: localhost:8080
Pragma: no-cache
User-agent: Apache CXF 3.1.4
Content-type: text/xml; charset=UTF-8
Soapaction: ''
Content-length: 211
Cache-control: no-cache
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:print xmlns:ns2="http://publisher.ws.brunozambiazi.com/"><arg0>First consumer!</arg0></ns2:print></soap:Body></soap:Envelope>--------------------

Printing 'First consumer!'---[HTTP response 200]---
Date: Sat, 19 Dec 2015 01:18:57 GMT
Transfer-encoding: chunked
Content-type: text/xml; charset=utf-8
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:printResponse xmlns:ns2="http://publisher.ws.brunozambiazi.com/"></ns2:printResponse></S:Body></S:Envelope>--------------------

Pay attention in line 11, where the request SOAP envelope is shown. Can you see the XML declaration? Of course not, because it isn’t there anymore! By default, Apache CXF doesn’t specify this – and this is exactly what I was looking for.


I know this is a specific and maybe unlikely situation, but it was very hard to find out a solution and so I decided to share my (maybe unpleasant) experience with that.

You can get the source code from this post on my GitHub account, here and here.

See you soon.

Working with JSON in Java

In this post I’m gonna show a simple way to work with JSON in Java, converting POJOs to JSON strings and vice-versa. All source code presented here can be downloaded in my GitHub account.

JSON libs

There are many frameworks in Java to facilitate our lives when we want to convert Java objects in JSON strings. You can see many of them here.

One of the most used (and my favorite, btw) is called Jackson. To import it to your project (assuming you have a Maven project), just add the dependency below:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.6.1</version>
</dependency>

All the examples we gonna do are based on this simple Java object (POJO) called User (I will omit the getters and setters, but you must create them):

import java.util.Calendar;
import java.util.Set;

public class User {
	
    private Long id;
    private String name;
    private Calendar birthDate;
    private Set<String> emails;

    // getters and setters for the 4 properties above

}

Converting Java objects to JSON strings

The process to convert a Java object in a JSON string is called serialization and Jackson turns this very easy. All we need to do is to create an ObjectMapper, the core of Jackson framework convert process, and pass to it an instance of the object we want to serialize.

import com.brunozambiazi.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Calendar;
import java.util.HashSet;

public class SerializationTest {

    public static void main(String[] args) throws Exception {
        User user = new User();
        user.setId(1L);
        user.setName("User");
        user.setBirthDate(Calendar.getInstance());
        user.setEmails(new HashSet<String>());
        user.getEmails().add("user@gmail.com");
        user.getEmails().add("user@yahoo.com");
        
        ObjectMapper mapper = new ObjectMapper();
        
        String json = mapper.writeValueAsString(user);
        System.out.println(json);
    }
    
}

Running the code above, you must see this output:

{"id":1,"name":"User","birthDate":1439662844272,"emails":["user@yahoo.com","user@gmail.com"]}

I told you: it’s very easy! If you want to¬†beautify the output, just add this line after instantiate the ObjectMapper:

mapper.enable(SerializationFeature.INDENT_OUTPUT);

And voilà! Our output now will look like this:

{
  "id" : 1,
  "name" : "User",
  "birthDate" : 1439664151489,
  "emails" : [ "user@yahoo.com", "user@gmail.com" ]
}

But, wait a minute. What is that number in the birthDate value? Jackson has his own default serializers for all kind of objects. For Calendar, the default serializer just print the result of #getTimeInMillis() method. If we want to change default behavior, we need to create a custom converter and tell Jackson to use it.

So, let’s create a custom serializer for Calendar class that receives a Calendar object as input parameter and performs a conversion of this to a String with “MM/dd/yyyy” format. It’s important to note the class we need to¬†extending from (JsonSerializer).

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class CalendarToDateStringSerializer extends JsonSerializer<Calendar> {

    @Override
    public void serialize(Calendar value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        if (value != null) {        
            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
            String formatted = sdf.format(value.getTime());
            gen.writeString(formatted);
        }
    }

}

There are at least two approach to use custom converters with Jackson. The first of is to use the annotation @JsonSerialize, passing the custom serializer class as using parameter, in all POJO fields you want to consider your serializer. In our example, we would change the birthDate attribute in User class:

@JsonSerialize(using = CalendarToDateStringSerializer.class)
private Calendar birthDate;

This approach is useful when you want to use custom serializer in a few fields. If your serializer is general and must to be used in all fields of a certain class, the second approach is more appropriate: register a module into the ObjectMapper and so you will not need the annotation approach.

In our example, just change creating ObjectMapper instance snippet for the code below:

SimpleModule module = new SimpleModule();
module.addSerializer(Calendar.class, new CalendarToDateStringSerializer());

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);

Running again the SerializationTest class, you must see something like this:

{
  "id" : 1,
  "name" : "User",
  "birthDate" : "08/15/2015",
  "emails" : [ "user@yahoo.com", "user@gmail.com" ]
}

Converting JSON strings to Java objects

The process to convert a Java object to a string in JSON format is very simple, right? But believe: the opposite process, known as deserialize, is still easier than that. All we need to do is create again an ObjectMapper instance and pass to it the string in JSON format and the class we want the target object.

import com.brunozambiazi.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;

public class DeserializationTest {

    public static void main(String[] args) throws Exception {
        String json = "{\"id\":1,\"name\":\"User\",\"birthDate\":\"08/15/2015\",\"emails\":[\"user@yahoo.com\",\"user@gmail.com\"]}";

        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.readValue(json, User.class);
        System.out.println(user.getName()+" - "+user.getId());
    }
    
}

Running this code you will get… oops!

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: 
Can not construct instance of java.util.Calendar from String value '08/15/2015': not a valid representation
 (error: Failed to parse Date value '08/15/2015': Can not parse date "08/15/2015": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"))
 at [Source: {"id":1,"name":"User","birthDate":"08/15/2015","emails":["user@yahoo.com","user@gmail.com"]}; line: 1, column: 22] (through reference chain: com.brunozambiazi.model.User["birthDate"])
    at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:55)
    at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:904)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseDate(StdDeserializer.java:787)
    at com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateBasedDeserializer._parseDate(DateDeserializers.java:175)
    [...]

Do you remember we use a custom serializer to change the way Jackson output a Calendar value? To deserialize correctly, now we need to create a custom deserializer for Calendar, it means to realize the opposite work we did in the serializer.

The Calendar deserializer will¬†get the date string representation, perform a conversion using the format we know (“MM/dd/yyyy”)¬†and return the Calendar instance created with this date. It’s important to note the class we need to extend from (JsonDeserializer).

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class DateStringToCalendarDeserializer extends JsonDeserializer<Calendar> {

    @Override
    public Calendar deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        try {
            String formatted = p.getValueAsString();
            SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
            
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(sdf.parse(formatted));
            return calendar;
        } catch (ParseException e) {
            throw new IOException(e);
        }
    }

}

We can use this converter by two ways, like we use de serializer converter presented before. The first way is to use an annotation directly in the field we want to convert, like this:

@JsonDeserialize(using = DateStringToCalendarDeserializer.class)
 private Calendar birthDate;

Considering this converter as a general converter for Calendar fields, we can use a simpler solution: register the deserializer as a module of the ObjectMapper. So, change the creating ObjectMapper instance by code snippet below:

SimpleModule module = new SimpleModule();
module.addDeserializer(Calendar.class, new DateStringToCalendarDeserializer());
 
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);

And it’s done! Run again the¬†DeserializationTest class and you will get a complete representation of the User instance based on the original JSON string.


Like I said in the begin of this post, there are many frameworks to work with JSON in Java. Jackson is my favourite not just by simplicity but also by the possibility to add more capabilities to it (like work with XML).

Feel free to disagree with me in comments. =)

See you soon.


References:

Enum comparisons in Java

I could bet that when you were starting with Java programming, in some moment you learned something like this:

Always use the equals method for comparisons. Never use the == operator.

Firstly, it’s important to say this is totally true for objects. The equals method must to be used always you are comparing object equality value, unless you want to¬†test if two instances¬†refers¬†both to the same reference.

But I think very awkward to¬†see Java code comparing¬†two enum options using the equals method. Besides, the code seems much¬†more clear and readable using the == comparator.¬†Let’s see a very simple example with this¬†two comparison ways:

class EnumComparison {

    enum Fruit {
        APPLE, LEMON, ORANGE;
    }

    public void test(Fruit chosenFruit) {
        if (Fruit.APPLE.equals(chosenFruit)) {
            System.out.println("Apple with equals method!");
        }

        if (chosenFruit == Fruit.APPLE) {
            System.out.println("Apple with == comparator!");
        }
    }

}

Fortunately, the second option is possible with Java, according to the official documentation:

Because there is only one instance of each enum constant, it is permissible to use the == operator in place of the equals method when comparing two object references if it is known that at least one of them refers to an enum constant.

In my opinion,¬†the enum comparison using == operator is much more clear and easy to understand. But, in summary, it’s important to say: with enums, compare like you want.

See you soon.