- Standalone and Managed Domain
- Centralized Administration
- Command Line Interface (jboss-cli)
- Admin Console
- Configuration files
If we had to pick a winner, it would be JBoss. The only application server in the group whose score never dropped below a 4
zeroturnaround.com
Highhlight: * JBoss is the winner from all the servers studied * Scores range from 1-5 with JBoss never going below 4 * Consistently good or excellent for developer productivity
JBoss consistently performs very well in each category which is why it also shines in the developer profiles exercise
zeroturnaround.com
Lets take a look at WildFly and what it is!
Objective:
Understand the new features of WildFly 8 and revise some of the features carry forward from AS 7.x.
ChatServer.java
@ServerEndpoint("/chat") (1)
public class ChatEndpoint {
@OnMessage (2)
public void message(String message,
Session client) (3)
throws IOException, EncodeException {
for (Session peer : client.getOpenSessions()) {
peer.getBasicRemote().sendText(message);
}
}
}
1 | Creates a WebSocket endpoint, defines the listening URL |
2 | Marks the method that receives incoming WebSocket message |
3 | Payload of the WebSocket message |
@ServerEndpoint
annotation on a POJO converts it into a WebSocket server endpoint. No additional deployment descriptors are required. The URL at which the endpoint is published is included in the annotation.@OnMessage
and the payload of the message is automatically mapped to the method parameter.job.xml
<job id="myJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0">
<step id="myStep" >
<chunk item-count="3"> (1)
<reader ref="myItemReader"/> (2)
<processor ref="myItemProcessor"/> (3)
<writer ref="myItemWriter"/> (4)
</chunk>
</step>
</job>
1 | Item-oriented processing, number of items in chunk |
2 | Item reader for chunk processing |
3 | Item processor for chunk processing |
4 | Item writer for chunk processing |
CreateJson.java
JsonObject jsonObject = Json.createObjectBuilder() (1)
.add("apple", "red") (2)
.add("banana", "yellow")
.build(); (3)
StringWriter w = new StringWriter();
JsonWriter writer = Json.createWriter(w); (4)
writer.write(jsonObject);
1 | Creates a JSON object builder |
2 | Adds a name/value pair to the JSON object |
3 | Returns the JSON object associated with this builder |
4 | Writes the JSON object to the writer |
JSONObject
is created and key/value name pairs are added using convenient add
methods. The API is fluent and you can chain method calls.java.io.Writer
or java.io.OutputStream
.RunMyTask.java
public class MyTask implements Runnable { (1)
@Override
public void run() {
. . .
}
}
@Resource(name = "DefaultManagedExecutorService") (2)
ManagedExecutorService defaultExecutor;
executor.submit(new MyTask()); (3)
1 | Runnable or Callable tasks can be submitted |
2 | ManagedExecutor is injected, default resource provided |
3 | Submit the task |
Runnable
or Callable
.ManagedExecutorService
.ManagedExecutorService
which can be easily injected using @Resource
.RunClient.java
Client client = ClientBuilder.newClient(); (1)
WebTarget target = client.target("..."); (2)
target.register(Person.class);
Person p = target
.path("{id}") (3)
.resolveTemplate("id", "1")
.request(MediaType.APPLICATION_XML) (4)
.get(Person.class); (5)
1 | ClientBuilder is the entry point |
2 | Build a new web resource target, specifies the path |
3 | Sub resource URI |
4 | Define the accepted response media types |
5 | Call HTTP GET, specify the type of resource |
Client
is required to access a Web resource using the Client API. The default instance of Client can be obtained by calling newClient on ClientBuilder
.Client
WebTarget
WebTarget
WebTarget
become apparent when building complex URIs, for example by extending base URIs with additional path segments or templates. Note the use of the URI template parameter {orderId}
. The exact value of this template parameter is resolved using resolveTemplate()
method.get()
method. In this case, the XML response is converted to a Person
POJO using JAX-RS entity providers.More on that later…
mod_cluster
supportedNonBlockingHandler.java
Undertow.builder() (1)
.addListener(8080, "localhost")
.setHandler(new HttpHandler() { (2)
@Override
public void handleRequest(final HttpServerExchange exchange)
throws Exception {
exchange.getResponseHeaders()
.put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender()
.send("Hello World");
}
}).build().start(); (3)
1 | Same API used for WildFly integration, fluent builder API |
2 | Can create multiple handlers |
3 | Build the server and start to listen for connections |
bin/standalone.sh|bat
scripts.bin/domain.sh|bat
scripts.jboss-cli.sh
|bat
jboss-cli.sh|bat
is Command Line Interface management tool for a standalone server or a managed domain. It allows a user to connect to a standalone server or domain controller and execute management operations.Now available!
SendMessage.java
@JMSDestinationDefinition(name="myQueue", interfaceName="javax.jms.Queue") (1)
@Resource(mappedName="myQueue")
Queue queue; (2)
@Inject
private JMSContext context; (3)
context.createProducer().send(queue, "Hello, JMS 2.0!"); (4)
1 | Create destination resource during deployment |
2 | Fetch the queue resource |
3 | Main interface of the simplified API |
4 | Fluent builder API, runtime exceptions |
JMSContext
interface.JMSContext
combines in a single object the functionality of both the Connection
and the Session
in the earlier JMS APIs. A container-managed JMSContext
instance can be obtained by simply injecting it with the @Inject
annotation. Notice, no ConnectionFactory
is specified here. In this case, a default JMS ConnectionFactory is used by and this is defined by the platform.Destination
, a Queue
in this case, is injected using @Resource
. Even this annotation can be created using newly introduced @JMSDestinationDefintion
annotation which would automatically create the destination.* Finally, the message is sent using method chaining. For example, create a producer using createProducer()
and then calling send()
method to send a message to a destination.ReceiveMessage.java
@Resource(mappedName="myQueue")
Queue queue;
@Inject
private JMSContext context;
JMSConsumer consumer = context.createConsumer(queue); (1)
String text = consumer.receiveBody(String.class, 5000); (2)
// => "Hello, JMS 2.0!"
1 | Fluent builder API, runtime exceptions |
2 | No cast required to receive a text message |
JMSDefinitions.java
@JMSDestinationDefinition(name="myQueue", (1)
interfaceName="javax.jms.Queue", (2)
properties = { "durable=false" } (3)
)
@JMSDestinationDefinition(name="myTopic",
interfaceName="javax.jms.Topic" (4)
)
1 | Name of the destination |
2 | JMS Queue |
3 | Provider-specific properties |
4 | JMS Topic |
JMSDefinitions.java
@JMSConnectionFactoryDefinition(name="myFactory", (1)
interfaceName = "javax.jms.QueueConnectionFactory", (2)
minPoolSize = 5, (3)
maxPoolSize = 20,
clientId = "myclientID", (4)
properties = { "initial-connect-attempts=5" } (5)
)
1 | Name of the JMS ConnectionFactory |
2 | Type of the connection factory |
3 | Min/Max size of the connection pool |
4 | JMS properties |
5 | Provider-specific properties |
Connection
and Session
AutoCloseable
JMSClient.java
ConnectionFactory cf = (ConnectionFactory)namingContext.lookup("..."); (1)
Destination destination = (Destination)namingContext.lookup("...");
try (JMSContext context = cf.createContext(userName, password)) { (2)
context.createProducer().send(destination, "hello");
JMSConsumer consumer = context.createConsumer(destination); (3)
String response = consumer.receiveBody(String.class, 5000);
}
1 | Usual JNDI lookup to get the JMS Connection Factory & Destinations |
2 | try-with-resources statement to auto close the context |
3 | Context is automatically started when a consumer is created |
JMSClient.java
@Inject
// @JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory") (1)
@JMSConnectionFactory("myFactory") (2)
@JMSPasswordCredential(userName="guest",password="password") (3)
@JMSSessionMode(JMSContext.AUTO_ACKNOWLEDGE) (4)
private JMSContext context;
1 | Java EE 7 Default JMS Connection Factory… |
2 | … or you use your own |
3 | User credentials |
4 | Acknowledgement mode / Transactional behaviour |
M +------------+ ------------> | consumer 1 | +----------+ M +-------+ / +------------+ | producer | ---> | topic | +----------+ +-------+ \ M +------------+ ------------> | consumer 2 | +------------+
M +------------+ ----------------> | consumer 1 | / +------------+ / +------------+ +----------+ M +-------+ / ---> | consumer 2 | | producer | ---> | topic | / +------------+ +----------+ +-------+ \ / M +------------+ << mysub >> -- ---> | consumer 3 | \ +------------+ \ +------------+ ---> | consumer 4 | +------------+
SharedSubscription.java
@Resource(mappedName="myTopic")
Topic topic;
@Inject
private JMSContext context;
String subscription = "...";
JMSConsumer consumer = context.createSharedConsumer(topic, subscription); (1)
context.setClientID("...");
JMSConsumer durableConsumer = context.createSharedDurableConsumer(topic, subscription); (2)
1 | Non-durable shared consumer (topic + subscription) |
2 | Durable shared consumer (topic + subscription + clientID) |
SendAsynchronously.java
JMSProducer producer = context.createProducer()
.setAsync(new CompletionListener() { (1)
@Override
public void onCompletion(Message message) { } (2)
@Override
public void onException(Message message, Exception exception) { } (3)
});
producer.send(destination, "Hello, Async!"); (4)
1 | Callback for completion |
2 | Called when a message was sent successfully |
3 | Called when a problem occurred and prevent the message to be sent |
4 | Send the message asynchronously |
acknowledgeMode
messageSelector
destinationType
subscriptionDurability
destinationLookup
connectionFactoryLookup
clientId
subscriptionName
MDB.java
@MessageDriven(name = "MyMDB", activationConfig = {
@ActivationConfigProperty(propertyName = "connectionFactoryLookup", (1)
propertyValue = "jms/MyConnectionFactory"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destinationLookup", (2)
propertyValue = "myQueue"),
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge") })
public class MyMDB implements MessageListener {
public void onMessage(Message message) { ... }
}
1 | standard portable property to lookup the connection factory |
2 | standard portable property to lookup the destination |
WildFly - http://wildfly.org, http://github.com/wildfly, @WildFlyAS |
JBoss EAP 6.2 - http://redhat.com/jboss |
Java EE 7 samples - https://github.com/javaee-samples/javaee7-samples |
Slides generated with Asciidoctor and DZSlides backend |
Original slide template - Dan Allen & Sarah White |