What’s new in WildFly 8 ?

Eduardo Martins

  • WildFly EE Core Dev Team, Red Hat Inc.
  • Naming/JNDI, EE Concurrency Utilities
  • Working remotely from Sesimbra, Portugal
Notes
  • My name is Eduardo Martins, and currently I’m a WildFly core developer at Red Hat
  • Currently I lead Naming module development, i.e. everything wrt JNDI & @Resource Injection, and I’m also a major contributor to the EE module development, for instance responsible for the EE Concurrency Utilities that we will talk about later.
  • I live by the sea since I can remember, so naturally I’m bound to it, and went through every imaginable sea activity, but in the last 15 years it’s mostly about surfing.

zeroturnaround.com

zeroturnaround trophy

Notes
  • What we’re looking at in this part of the report are the real developer concerns and metrics including:
    • Ease of download and installation
    • Real performance metrics
    • Tooling support
    • Server Configuration
  • WebLogic and WebSphere were not included as these servers are really targeted for large-enterprises and apps in production rather than lightweight development
  • Each server was ranked from 1 to 5

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
Notes

Highhlight: * JBoss is the winner from all the servers studied * Scores range from 1-5 with JBoss never going below 4 * JBoss AS version ??

JBoss consistently performs very well in each category which is why it also shines in the developer profiles exercise


zeroturnaround.com
wildfly
Notes

Lets take a look at WildFly and what is it!

Objective:
Understand the new features of WildFly 8 and revise some of the features carry forward from AS 7.x.

Notes
  • The aim of today’s presentation is …
  • … to learn the new features of WildFly 8
  • … learn some of the main features that already existed in AS 7.x and carried forward.

What is WildFly 8 ?

Notes
  • The new name is relevant because it differentiates our community project from the commercial offering. After JBoss AS 7.1.2,the community offering is renamed to WildFly. This is the upstream project for JBoss Enterprise Application Platform. Main focus of WildFly is to meet community demands by rapid releases and latest in innovation. EAP is focused towards a more conservative branch, which is battle-tested for mission critical deployments.
  • WildFly provides a lightweight managed application runtime. WildFly provides a unified management layer fully integrated with all aspects of server and is exposed using a variety of APIs and protocols. These could be used to automate operational needs of any environment – small JVM on a tiny server or thousands of JVM spread across the world.
  • For JBoss, developer is the key. So from the very beginning WildFly is designed to be easy and quick to get going. It offers rapid boot time, excellent developer tooling through not just JBoss Tools project and NetBeans plugin but also community–contributed IntelliJ, and a wide variety of quick start examples.
  • WildFly implements the latest Java EE standards as well as additional open source innovative APIs. While Java EE is the most common usage of WildFly but it is not tied to any particular language or SDK. For example, TorqueBox provides full Ruby-on-Rails experience and is based on WildFly architecture and use many of its core features.
  • The source code is completely open source and available to you for free. If you have an issue with your application, you can attach a debugger and find out what might be causing the issue. You can file a bug, and then send a pull request for the patch to be applied.

WildFly 8 main features

Notes
  • WildFly 8 is Java EE 7 compliant and brings all the great technologies added to the platform.
  • It also adds a new high performance and flexible Web server.
  • Another important feature in WildFly is the ability to segment administrative responsibilities based upon different user roles. This allows users to be restricted to specific areas of console such as to deploy an application or access privileged resources. This is commonly called as Role Based Administration Control (RBAC).
  • Also a special audit log with actions of the user is enabled and this log can then be uploaded to a secure location.
  • Automated patching ?

WildFly: Java EE 7

javaee7
Notes
  • Java EE 7 is the latest release of the platform and focuses around increasing productivity and embracing HTML5. WildFly 8 is Java EE 7 compliant and so you get all the technologies from the platform here.
  • WebSocket (JSR 356), Batch (JSR 352), JSON (JSR 353), Concurrency Utilities for Java EE (JSR 236) are four new techonlogies in the platform. JAX-RS 2 (JSR 339) and JMS 2 (JSR 343) went through significant updates. CDI 1.1 (JSR 346), Bean Validation 1.1 (JSR 349), JPA 2.1 (JSR 338), JTA 1.2 (JSR 907) also made updates.
  • Lets take a look at some Java EE 7 sample code.

WildFly: Java EE 7 WebSocket (JSR 356)

ChatServer.java
@ServerEndpoint("/chat") (1)
public class ChatEndpoint {
    @OnMessage (2)
    public void message(String message,
                        Session session) (3)
                   throws IOException, EncodeException {
        for (Session peer : session.getOpenSessions()) {
            peer.getBasicRemote().sendText(message);
        }
    }
}
1Creates a WebSocket endpoint, defines the listening URL
2Marks the method that receives incoming WebSocket message
3Payload of the WebSocket message
Notes
  • The Java API for WebSocket, WebSocket 1.0, is a key technology for HTML5 support. WebSocket provides a bi-directional and full-duplex communication channel over a sigle TCP connection.
  • Adding @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.
  • The POJO method that needs to be invoked is marked with @OnMessage and the payload of the message is automatically mapped to the method parameter.
  • First parameter receives the payload, second parameter marks the conversation from the client.
  • Method implementation iterate over all the connected clients and broadcast the received payload.

WildFly: Java EE 7 Batch (JSR 352)

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>
1Item-oriented processing, number of items in chunk
2Item reader for chunk processing
3Item processor for chunk processing
4Item writer for chunk processing
Notes
  • Batch Processing provides item-oriented (aka chunk, and preferred style) and task-oriented (aka batchlet) processing. This is a job description of chunk processing, aka Job XML.
  • Job XML typically consists of many steps, this canonical sample contains one chunk step.
  • This chunk has a reader, processor, and writer. The ref attribute refers to CDI resolvable bean name bundled with the archive.
  • The item-count attribute defines the chunk size, i.e. the number of items processed at one time.
  • The reader, processor, and writer work together for a chunk number of items at a time.
  • All of this is done within a transaction, with automatic checkpointing.

WildFly: Java EE 7 JSON (JSR 353)

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);
1Creates a JSON object builder
2Adds a name/value pair to the JSON object
3Returns the JSON object associated with this builder
4Writes the JSON object to the writer
Notes
  • JSON is a key technology for data transfer within HTML5 applications. With JSON 1.0, Java EE 7 adds new APIs to enable the parsing and generation of JSON text and objects.
  • JSON API provides streaming and object model API to parse and generate JSON. This is an object-model API sample.
  • JSONObject is created and key/value name pairs are added using convenient add methods.
  • Created object can be written to java.io.Writer or java.io.OutputStream.

WildFly: Java EE 7 Concurrency (JSR 236)

RunMyTask.java
public class MyTask implements Runnable { (1)

    @Override
    public void run() {
        . . .
    }
}

@Resource(name = "DefaultManagedExecutorService") (2)
ManagedExecutorService defaultExecutor;

executor.submit(new MyTask()); (3)
1Runnable or Callable tasks can be submitted
2ManagedExecutor is injected, default resource provided
3Submit the task
Notes
  • Concurrency Utilities is a new addition to the Java EE 7 platform and is an extension of the Java SE Concurrency Utilities API. This API provides asynchronous capabilities to Java EE application components, at a lower level than the existing asynch APIs (offered by EJB, Servlet, JAX-RS), and thus gives you a finer-grain level of control and configuration.
  • API provides 4 types of managed objects, one of them is ManagedExecutorService.
  • Task can be defined as Runnable or Callable.
  • Platform provides a default instance of ManagedExecutorService which can be easily injected using @Resource.
  • Usual calls from JSR 166y are now available. All standard Java SE Concurrency APIs and design patterns are available for us. The big difference is that the threads created here are managed by the application server now. The JNDI, class loading, security context information is available to these tasks. This was not available earlier.

WildFly: Java EE 7 JAX-RS (JSr 339)

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)
1ClientBuilder is the entry point
2Build a new web resource target, specifies the path
3Sub resource URI
4Define the accepted response media types
5Call HTTP GET, specify the type of resource
Notes
  • JAX-RS 2.0 now adds a client-side API to access a REST endpoint in a standard way.
  • An instance of 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.
  • A Web resource can be accessed using a fluent API in which method invocations are chained to build and ultimately submit an HTTP request.
  • Conceptually, the steps required to submit a request are the following:
    • obtain an instance of Client
    • create a WebTarget
    • create a request from the WebTarget
    • submit a request or get a prepared Invocation for later submission
  • The benefits of using a WebTarget become apparent when building complex URIs, for example by ex- tending 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.
  • The response to a request typed in the invocation of get() method. In this case, a String representation is returned back. This can also be a POJO where on-the-wire format is converted to POJO using JAX-RS entity providers.

WildFly: Java EE 7 JMS (JSR 343)

SendMessage.java
@JMSDestinationDefinition(name="myQueue", interfaceName="javax.jms.Queue") (1)

@Resource(mappedName="myQueue")
Queue syncQueue;

@Inject
// @JMSConnectionFactory("java:comp/DefaultJMSConnectionFactory") (2)
private JMSContext context; (3)

context.createProducer().send(syncQueue, "..."); (4)
1Create destination resource during deployment
2Default JMS connection factory
3Main interface of the simplified API
4Fluent builder API, runtime exceptions
Notes
  • JMS has undergone a major simplification with the JMS 2.0 by offering the simple and easier-to-use API and offloading developer tasks onto container services.
  • Sending and receiving a message using JMS 1.1 required a lot of boilerplate code. JMS 2.0 has really fixed this with the addition of the new JMS simplified API and, in particular, the 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.
  • A 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.
  • Really simple and clean. This also improves semantic readability of your code.

Java Transaction API 1.2 (JSR 907)

Notes
  • A significant change in JTA allows to convert any POJO into a transactional object.
  • The javax.transaction.Transactional annotation provides the application the ability to declaratively control transaction boundaries on CDI managed beans, as well as classes defined as managed beans by the Java EE specification, at both the class and method level where method level annotations override those at the class level.·
  • The javax.transaction.TransactionScoped annotation provides the ability to specify a standard CDI scope to define bean instances whose lifecycle is scoped to the currently active JTA transaction. This annotation has no effect on classes which have non-contextual references such those defined as managed beans by the Java EE specification .

Contexts and Dependency Injection 1.1 (JSR 346)

Notes
  • CDI is making the platform lot more cohesive and is becoming a core component model.
  • Also, CDI is now enabled by default in Java EE 7, without the requirement to specify a beans.xml descriptor.·
  • If beans.xml exists with version 1.1, then a new attribute bean-discovery-mode can be specified on the top level <beans>. “all” value can be specified to enable injection all beans in the archive. “annotated” value is used to inject beans with a bean defining annotation – such as one with a CDI scope. And “none” can be used to completely disable CDI.
  • A new annotation @Vetoed is added to enable programmatic disablement of classes. This functionality was available in other frameworks and now in the standards.

WildFly: Java EE 7 IDEs

netbeans-wildfly eclipse-wildfly intellij-wildfly netbeans-logo jbosstools-logo intellij-logo

WildFly: New web server (Undertow)

Notes
  • Undertow is a flexible performant web server written in java, providing both true blocking and non-blocking API’s based on NIO. It has the ability to scale to a million connections and has impressive numbers on throughput. It also allows us to add support for modern security standards. And since web server is one of the most critical pieces of an application server, writing it a fresh allows us to provide the best possible performance and memory efficiency.
  • Undertow has a composition based architecture that allows you to build a web server by combining small single purpose handlers. The gives you the flexibility to choose between a full Java EE servlet 3.1 container, or a low level non-blocking handler, to anything in between.
  • Undertow is designed to be fully embeddable, with easy to use fluent builder APIs. Undertow’s lifecycle is completely controlled by the embedding application.
  • Undertow provides support for Servlet 3.1, including support for embedded servlet. It is also possible to mix both Servlets and native undertow non-blocking handlers in the same deployment. It allows to upgrade from HTTP to our native protocols.

WildFly new web server: Undertow

NonBlockingHandler.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)
1Same API used for WildFly integration, fluent builder API
2Can create multiple handlers
3Start the handler in JVM
Notes

Read through the code ;-)

Undertow benchmarks

1000
http://www.techempower.com/blog/2014/03/04/one-million-http-rps-without-load-balancing-is-easy/

WildFly: Port reduction

Notes
  • By utilizing HTTP upgrade, WildFly 8 has moved nearly all of its protocols to be multiplexed over two HTTP ports: a management port, and an application port. This is a big benefit to cloud providers (such as OpenShift) who run hundreds to thousands of instances on a single server. This is another example of why JBoss is designed for the cloud / PaaS. The better examples are small memory footprint and fast startup (delivered in AS 7).
  • Note that since CR1 we have finally dropped the native management port 9999, which instead uses the HTTP management port (9990). Our full profile configuration also dropped the native JMS ports 5445 and 5455, which instead are multiplexed over port 8080. However, all of these original ports can still be enabled if desired.
  • At some point, we may offer a single port mode, to allow all server traffic to go through a single port.

WildFly: Role based access control

Notes
  • Role Based Access Control (RBAC) is the ability to restrict access to system or certain portions of it to authorized users. For JBoss AS 7.x or JBoss EAP 6.0 and 6.1, the web-based administrative console had an all-or-nothing approach. So if a user can authenticate with management security realm, then he’ll have all the privileges. This might be OK for smaller deployments but the roles are typically divided for mission critical deployments and a finer-grained control is required.
  • JBoss EAP 6.2 and WildFly 8 introduces RBAC using different roles. There are essential 7 different roles in 2 different categories – administrative and privileged.
  • Each Role is defined as a set of Permissions and Permissions specify what Actions are permitted by the logged in user, which is basically lookup, write, or delete.

WildFly: Administrative audit logging

Notes
  • WildFly comes with audit logging built in for management operations affecting the management model. By default it is turned off. The information is output as JSON records.
  • RBAC and Audit Logging certainly makes the server enterprise grade. But EAP (not WildFly) is certify to very military-grade security standards - namely Common Criteria (EAL 4+) so it can be deployed in highly sensitive, restrictive environments; or even banks ;). Features like Audit Logging and RBAC make it possible.

WildFly: Automated patching

Notes
  • The infrastructure to support the application of patches to an existing install has been implemented. This capability allows for a remote client to install and rollback new static modules and binary files using the WildFly management protocol.
  • This feature will be used in future for EAP.

WildFly: Minimalistic "core" distribution

Notes
  • A new download option is now available in WildFly 8, called the "core" distribution. This distribution is ideal for framework authors that want to build their own application runtime using the powerful WildFly 8 architecture.
  • This allows to add new subsystems, add new deployment types, your application needs to take advantage of the powerful CLI for managementaspect, etc. This is nothing to do with an existing standard like Java EE or anything else, its purely related to how WildFly internals work.
  • Management, classloading (JBoss Modules), logging etc is bare bones, everything else like EJB, JPA, Clustering are extensions to that. Core has a deployment manager but it does not know what to do with the uploaded archive, such as WAR, unless an extension is uploaded.
  • Rich management layer supporting configuration persistence, hot runtime updates, and unified set of tools and protocols.
  • Built-in lightweight web server (supports the HTTP/JSON management protocol)

WildFly: Miscellaneous

Notes
  • This release has improved compatibility with JDK8, and we now encourage everyone interested in Java 8 to run WildFly 8 on it as well. Expect future releases of WildFly to include APIs that take advantage of the new language features.
  • WildFly 8 includes RESTEasy 3 which supports the standard Java EE REST APIs (JAX-RS 2.0) and also provides a number of useful extensions including JSON Web Encryption, Jackson, Yaml, JSON-P, and Jettison.
  • Hibernate Search is now offered out of the box in WildFly. Hibernate Search indexes objects for fast full-text searching. Multiple data sources are supported including Infinispan and standard database entities.
  • WildFly now provides a specialized Java security manager that allows you to define per-deployment security permissions, and also greatly improves upon the performance of using the standard Java security manager. In addition to the standard Java EE permissions.xml, a more flexible jboss-permissions.xml descriptor is also supported.
  • Allows applications to view cluster topology and listen for topology changes. Allows applications to broadcast/submit commands to nodes in the cluster for remote execution. Requisite modules are automatically made available to deployments, if supported by the server profile.
  • CMP - JPA offers much more performant and flexible API. JAX-RPC - JAX-WS offers a much more accurate and complete solution. JSR-88 - Very little adoptionr. Most preferred the more complete deployment APIs provided by venders. We decided to completely remove support for these technologies due to the high maintenance cost, low community interest, and much better alternative solutions. If you are not able to port at this time, we recommend looking at JBoss EAP6, which provides long term maintenance and support of these technologies.

WildFly: In the cloud

openshift-logo cloudbees-logo

Carry forward from AS 7.x

  • Standalone and Managed Domain
  • Centralized Administration
    • Command Line Interface (jboss-cli)
    • Admin Console
    • Configuration files
Notes
  • AS 4, 5, and 6 had the concept of a single independent instance server only. AS 7 introduced the concept of multi-server topology using managed domain.
  • It provides multiple ways for centralized administration serving different use cases.

Standalone and Managed Domain

Notes
  • Standalone instance is a single independent instance of server, just like AS 4, 5, and 6. can be started using bin/standalone.sh|bat scripts.
    • This mode is recommended for development.
    • If more than one standalone instance is launched and multi-server management is desired, it is the user’s responsibility to coordinate management across the servers. For example, to deploy an application across all of the standalone servers, the user would need to individually deploy the application on each server.
  • A managed domain that allows you to run and manage a multi-server topology and manage multiple WildFly instances from a single control point. It can be started using bin/domain.sh|bat scripts.
    • This mode is recommended for production.
  • Deploying critical applications on a single node suffers from two potential problems:
    • loss of application availability when the node hosting the application crashes (single point of failure)
    • loss of application availability in the form of extreme delays in response time during high volumes of requests (overwhelmed server) WildFly supports two features which ensure high availability of critical Java EE applications:
    • fail-over: allows a client interacting with a Java EE application to have uninterrupted access to that application, even in the presence of node failures
    • load balancing: allows a client to have timely responses from the application, even in the presence of high-volumes of requests
  • Fail-over allows a client interacting with a Java EE application to have uninterrupted access to that application, even in the presence of node failures. If the application makes use of WildFly’s fail-over services, a client interacting with an instance of that application will not be interrupted even when the node on which that instance executes crashes. Behind the scenes, WildFly makes sure that all of the user data that the application make use of (HTTP session data, EJB SFSB sessions, EJB entities and SSO credentials) are available at other nodes in the cluster, so that when a failure occurs and the client is redirected to that new node for continuation of processing (i.e. the client "fails over" to the new node), the users data is available and processing can continue.
  • Load balancing allow a client to have timely responses from the application, even in the presence of high-volumes of requests. Using a load balancer as a front-end, each incoming HTTP request can be directed to one node in the cluster for processing. in this way, the cluster acts as a pool of processing nodes and the load is "balanced" over the pool of nodes, achieving scalability and, as a consequence, availability.

Managed Domain

managed domain
Notes
  • Domains can span multiple physical (or virtual) machines, with all WildFly 8 instances on a given host under the control of a special Host Controller process. One Host Controller instance is configured to act as the central Domain Controller. The Host Controller on each host interacts with the Domain Controller to control the lifecycle of the application server instances running on its host and to assist the Domain Controller in managing them.
  • Host controller (HC) is started with domain.sh|bat script and is only concerned with server management on that host. Domain Controller (DC) is a special HC that is configured to be the central management control point for the collection of servers in the ‘domain’.
  • All of the WildFly 8 instances in the domain share a common management policy, with the Domain Controller acting to ensure that each server is configured according to that policy.
  • A server group is set of server instances that will be managed and configured as one. In a managed domain each application server instance is a member of a server group. DC and HC ensures that all servers in a server group have a consistent configuration.
  • Server is an actual server instance. It runs in a separate JVM process from HC and is started by HC. User cannot launch this process from command line.
  • It’s important to understand that the choice between a managed domain and standalone servers is all about how your servers are managed, not what capabilities they have to service end user requests. This distinction is particularly important when it comes to high availability clusters. It’s important to understand that HA functionality is orthogonal to running standalone servers or a managed domain. That is, a group of standalone servers can be configured to form an HA cluster.

Clustering Strategies

Notes
  • By default, cluster nodes monitor each other’s status using the UDP protocol. Some networks only allow TCP to be used. In this situation, you can add the TCPPING protocol stack to your configuration and use it as the default mechanism. These configuration options are available in the command-line based Management CLI. The mod_cluster subsystem also uses UDP communication by default, and you can choose to use TCP here as well.
  • Advantages of mod_cluster
    • mod_cluster Management Protocol (MCMP) is an additional connection between the application server nodes and httpd, used by application server nodes to transmit server-side load balance factors and lifecycle events back to the web container via a custom set of HTTP methods.
    • Dynamic configuration of HTTPD proxies allows JBoss EAP 6 to adapt on the fly, with no additional configuration.
    • The application servers perform the load-balancing factor calculations. This makes load balancing metrics more accurate than other connectors.
  • mod_cluster gives fine-grained application lifecycle control. Each server forwards any web application context lifecycle events to the proxy, informing it to start or stop routing requests for a given context in the server. This prevents end users from seeing 404 errors due to unavailable resources.
    • AJP, HTTP or HTTPS with mod_cluster and Apache HTTP can be used.

Command Line Interface

Notes
  • 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.
  • All configuration data is persisted in the backing XML configuration files. These files can be directly manipulated as well but require knowledge about them.

Admin Console

Notes
  • The Admin Console is a responsive web-based administration console and provides a GUI for all administration tasks.

Migrate to WildFly

700
http://wildfly.org/news/2014/02/06/GlassFish-to-WildFly-migration/
http://zeroturnaround.com/rebellabs/abandon-fish-migrating-from-glassfish-to-jboss-or-tomee/

the most logical decision when migrating from GlassFish is opting for an equivalent open source alternative


zeroturnaround.com

JBoss/WildFly or TomEE chosen because …

WildFly is:

  • Java EE 7 compliant
  • lightweight
  • managable
  • highly scalable
  • open source
  • application server

Now available!

Open source polyglot conference

devnation summitpromo

References

WildFly - http://wildfly.org, http://github.com/wildfly, @WildFlyAS
JBoss EAP 6.2 - http://www.jboss.org/products/eap
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

Eduardo Martins