Wednesday, October 18, 2017

Seam 2.x over JEE 7 (Is it Possible)?

Hello all...
I am back!

For  a long time I could not write here because I am working on some particular projects.

A lot of friends are asking me about Seam 2.x into JEE 7 container, like JBoss EAP 7 or Wildfly 8, 9 or 10/11.

I am so confused about this because Seam was created for helping developers to solve issues over JEE 5 / 6 (it is a mistake in my opinion...CDI is a better choice to be used with deltaspike than Seam).

So, is it possible to use Seam 2.x projects on JEE 7?
NO!! It is impossible without a lot and lot of work...It is necessary to change many things into your java code. Libraries are not compatible (seam annotation, mojarra/jsf and so on...).

If you are trying to migrate Seam projects to JBoss EAP 7 directly, it can be a nightmare!

In some situations it is more responsible to write a new application approach using CDI, spring boot or microservices as such WS Rest Services (using TI Bimodal concepts). IMHO it is a good choice to create a new code, removing Seam, and of course reviewing the container dependencies to use microservices into a BiModal approach.

I suggest to create a migration process, planning, measuring, removing Seam libraries step by step. Web Services for instance can be separated into microservices. 

So, migrating Seam projects to EAP 7 could be a hard work, but it must be done with a proof of concepts first, planning, evaluating issues and differences between CDI and Seam approach. The price to convert your Seam project for working into JEE 7 can be high (lot lot and lot necessary time of work).

Tuesday, November 22, 2016

Second Level Cache - Infinispan JBoss EAP 6,7 and Wildfly 8,9

Hello!!
Thanks to be here.

I would like to show a brief configuration inside persistence.xml to enable the second level cache over JBoss EAP 6.x, 7 or Wildfly 8.x, 9.

The second level cache is based on Infinispan framework.

First of all, edit the persistence.xml file.

<!-- Caching is enabled for all entities for Cacheable(true) is specified -->
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<!-- shared-cache-mode>ALL</shared-cache-mode -->

<properties>
            <property name="hibernate.transaction.jta.platform"    value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" />
            <property name="hibernate.temp.use_jdbc_metadata_defaults"    value="false" />
            <property name="hibernate.jdbc.batch_versioned_data" value="true"/>
            <property name="hibernate.generate_statistics" value="false" />

          <property name="hibernate.jdbc.use_streams_for_binary" value="true" />

          <!-- second level cache with infinispan -->            
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="hibernate.cache.use_query_cache"        value="true"/>
            <property name="hibernate.cache.region.factory_class"    value="org.jboss.as.jpa.hibernate4.infinispan.InfinispanRegionFactory"/>
            <property name="hibernate.cache.infinispan.cachemanager" value="java:jboss/infinispan/container/hibernate"/>
            <property name="hibernate.cache.inifinispan.statistics"  value="true"/>
            <property name="hibernate.cache.use_minimal_puts"     value="true"/>
            <property name="hibernate.cache.infinispan.use_synchronization"      value="false"/>
            <property name="hibernate.cache.infinispan.entity.eviction.strategy" value="LIRS"/>
            <property name="hibernate.cache.infinispan.entity.eviction.wake_up_interval" value="3000"/>
            <property name="hibernate.cache.infinispan.entity.eviction.max_entries"      value="12000"/>
            <property name="hibernate.cache.infinispan.entity.expiration.lifespan"       value="60000"/>
            <property name="hibernate.cache.infinispan.entity.expiration.max_idle"       value="40000"/>

</properties>

After that, just enable entity classes (hibernate implementation):

@Cacheable(true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)


That's it.

Thanks a lot and regards.


Monday, August 29, 2016

JBoss EAP with Java Module for Testing - Arquillian, Selenium, Spring Boot and JUnit Together

Hi All,
Thanks again to stay here!

Today, I would like to show you how to create a java module configuration to test your WS service using Arquillian, Selenium, Spring Boot and Junit...

Pre-Requirements

JBoss EAP 6.x
Java 7 or 8
Maven 3.3

So, let's do it!

First of all and the most important point: configure your pom.xml with frameworks and appropriate versions to run tests.

Arquillian

Define your arquillian.xml file into test/resources:

<arquillian xmlns="http://jboss.org/schema/arquillian"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://jboss.org/schema/arquillian
        http://jboss.org/schema/arquillian/arquillian_1_0.xsd">

    <defaultProtocol type="Servlet 3.0"/>  
   
    <container qualifier="jboss" default="true">
        <configuration>
            <property name="jbossHome">/opt/java/jboss/jboss-eap-6.4/</property>
            <property name="serverConfig">standalone-full-ha.xml</property>
            <property name="javaVmArguments">-Xms512m -Xmx1024m -XX:MaxPermSize=256m -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+UseCompressedOops -XX:+AggressiveOpts -XX:+HeapDumpOnOutOfMemoryError -noverify -Xss512k -XX:StackShadowPages=8 -XX:+UseFastAccessorMethods</property>
            <property name="managementAddress">localhost</property>
            <property name="managementPort">9999</property>
            <property name="username">admin</property>
            <property name="password">yadayadaxpto</property>
        </configuration>
    </container>
</arquillian>


Put the versions and packages into pom.xml

        <arquillian.version>1.1.2.Final</arquillian.version>
        <arquillian.warp.version>1.0.0.Alpha6</arquillian.warp.version>
        <arquillian.rest-client.version>1.0.0.Alpha2</arquillian.rest-client.version>


        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-container</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.arquillian.protocol</groupId>
            <artifactId>arquillian-protocol-servlet</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-rest-client-impl-jersey</artifactId>
            <version>1.0.0.Alpha3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.glassfish.jersey.core</groupId>
                    <artifactId>jersey-common</artifactId>
                </exclusion>

                <exclusion>
                    <artifactId>javax.ws.rs</artifactId>
                    <groupId>javax.ws.rs-api</groupId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-warp</artifactId>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.commons</groupId>
                    <artifactId>commons-lang3</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>

        <dependency>
            <!-- http://arquillian.org/modules/contacts-extension/ -->
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-rest-warp-impl-jaxrs-2.0</artifactId>
            <version>${arquillian.rest-client.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mockito</groupId>
                    <artifactId>mockito-all</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-rest-client-impl-3x</artifactId>
            <version>${arquillian.rest-client.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.jboss.arquillian.extension</groupId>
                    <artifactId>arquillian-rest-client-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.jboss.arquillian.extension</groupId>
                    <artifactId>arquillian-rest-client-impl-base</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.arquillian.extension</groupId>
            <artifactId>arquillian-rest-warp-api</artifactId>
        </dependency>



Create your test base class

@RunWith(Arquillian.class)
public class ArquillianDefaultTest {

    @Deployment
    public static WebArchive createTestArchive() {
        return ShrinkWrap.create(WebArchive.class, "test-arquillian.war")
                .addPackages(true, Filters.exclude(".*Test.*"),
                        ArquillianDefaultTest.class.getPackage())
                .addAsLibraries(Maven.resolver().resolve("javax.ws.rs:javax.ws.rs-api:2.0").withTransitivity().asFile())
                .addAsLibraries(Maven.resolver().resolve("org.jboss.arquillian.extension:arquillian-rest-warp-api:1.0.0.Alpha2").withTransitivity().asFile())
                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
    }


    @RunAsClient
    @Test
    public void testWS(@ArquillianResource URL deploymentURL) throws URISyntaxException {
        WebTarget target = buildWebTarget(deploymentURL);
        System.out.println("WebTarget: " + target);
        assertNotNull(target);
    }

}

Spring Boot

   <spring.boot.version>1.3.5.RELEASE</spring.boot.version>
   <spring.boot.maven.plugin.version>1.3.5</spring.boot.maven.plugin.version>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>${spring.boot.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring.boot.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.hamcrest</groupId>
                    <artifactId>hamcrest-core</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring.boot.version}</version>
            <scope>provided</scope>
        </dependency>


Test Sample

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = BaseSpringBootApplicationStartup.class)
@WebAppConfiguration
@IntegrationTest("server.port:7070")
public class ApplicationSpringBootITest extends FluentTest {
 

    @Value("${local.server.port:7070}")
    private int serverPort;

    protected WebDriver webDriver;

    @Before
    public void setUp() {
        webDriver = new FirefoxDriver();
        webDriver.get("http://google.com");
        System.out.println(webDriver.getPageSource());
    }

    @After
    public void teardown() {
        if (webDriver != null) {
            webDriver.quit();
        }
    }

    @Override
    public WebDriver getDefaultDriver() {
        return webDriver;
    }

    protected String getUrl() {
        return "http://localhost:" + serverPort;
    }

    @Test
    public void hasPageTitleMock() {
        when().
            get(getUrl() + "/homeMock").
        then().
            assertThat().
            statusCode(200);
    }
}


Selenium and JUnit

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-firefox-driver</artifactId>
            <version>2.53.1</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-server</artifactId>
            <version>2.53.1</version>
        </dependency>

        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-api</artifactId>
            <version>2.53.1</version>
        </dependency>

       <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-support</artifactId>
            <version>2.53.1</version>
        </dependency>  


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>


It's done! But I just want to show the libraries and versions here, because you can find all details about implementation at my github project.

So, check all artefacts and classes over here:

https://github.com/alvesfred/samples-jboss/tree/master/samples-test

How to Run the tests or the environment...

1 - mvn  clean install or
2 - mvn clean integration-test -P integration-ws-test

Thanks a lot and regards!

Sunday, August 28, 2016

JBoss EAP 6.x with HornetQ Backup Cluster (Broadcast/Loopback) using JGroups

Hi everyone...
I am back!

Thanks a lot to stay here for reading my post. Sorry about my english, but i am studying hard to improve it :-)!

Today, i would like to present a configuration over HornetQ (jboss jms server), settting up a backup server into a HA Cluster.

HornetQ is a good choice to delivery messages using JBoss EAP 6.x, and you can define properties to work with a lot of nodes where the messages will be sent and received in miliseconds.

So, how can i create a HornetQ Live Server, Backup HornetQ Server and setting up a cluster configuration to provide performance for any tasks in Java EE Applications?

It is not a simple question, because a lot of issues and situations must be specified to ensure a good performance solution. But work with JMS as a important part of JEE that solves problems for working in asynchronous process.

So, let's see how we could create a good configuration for working in cluster with HornetQ Messages.

JGroups Properties

For a group server you have to define 3 essencials properties...

<property name="jboss.default.multicast.address"    value="231.0.0.3"/>
<property name="jboss.messaging.group.address"    value="231.3.3.3"/>
<property name="hornetq-discovery-group-name"     value="dg-hornetq-a"/>

These properties will be used for all servers inside the group, and messages will be received by the servers in a cluster environment.

For instance:

<server-group name="grp-b" profile="prf-b">
            <jvm name="default">
                <heap size="3096m" max-size="3096m"/>
                <jvm-options>
                    <option value="-XX:+CMSClassUnloadingEnabled"/>
                    <option value="-XX:+UseConcMarkSweepGC"/>
                    <option value="-XX:+UseCompressedOops"/>
                    <option value="-XX:+AggressiveOpts"/>
                    <option value="-XX:+ScavengeBeforeFullGC"/>
                    <option value="-XX:+HeapDumpOnOutOfMemoryError"/>
                    <option value="-noverify"/>
                    <option value="-Xss1024k"/>
                    <option value="-XX:StackShadowPages=10"/>
                    <option value="-XX:+UseFastAccessorMethods"/>
                </jvm-options>
            </jvm>
            <socket-binding-group ref="full-ha-sockets"/>
            <system-properties>
                <property name="jboss.default.multicast.address"   value="231.0.0.3"/>
                <property name="jboss.messaging.group.address"   value="231.3.3.3"/>
                <property name="hornetq-discovery-group-name"     value="dg-hornetq-a"/>
                <property name="jboss.tx.node.id"                             value="node-a"/>
            </system-properties>
        </server-group>



HornetQ Journal

We have to define the path where HornetQ will save informations for handling messages...

    <system-properties>
        <property name="java.net.preferIPv4Stack" value="true"/>
        <property name="org.apache.tomcat.util.http.Parameters.MAX_COUNT" value="5000"/>
        <property name="user.country" value="BR"/>
        <property name="user.language" value="pt"/>
    </system-properties>

    <paths>
        <path name="hornetq_storage_a" path="/opt/hornetq/a-queue"/>
        <path name="hornetq_storage_b" path="/opt/hornetq/b-queue"/>

        <!-- hornetq backups -->
        <path name="hornetq_storage_a_bkp"  path="/opt/hornetq_bkp/a-queue"/>
        <path name="hornetq_storage_b_bkp"  path="/opt/hornetq_bkp/b-queue"/>

    </paths>


These paths must be used by lived servers and HornetQ backup servers.
But if you prefer, according to your environment, a shared path must be defined for both into the same profile.

 <subsystem xmlns="urn:jboss:domain:messaging:1.4">
                <hornetq-server>
                    <persistence-enabled>true</persistence-enabled>
                    <security-enabled>false</security-enabled>
                    <!--transaction-timeout>180000</transaction-timeout-->
                <backup>false</backup>
 
                   <allow-failback>true</allow-failback>
                    <failover-on-shutdown>true</failover-on-shutdown>
                <shared-store>true</shared-store>
                    <journal-type>ASYNCIO</journal-type>
                    <!--journal-buffer-timeout>2000</journal-buffer-timeout-->
                    <journal-sync-transactional>true</journal-sync-transactional>
                    <journal-sync-non-transactional>true</journal-sync-non-transactional>
                    <log-journal-write-rate>false</log-journal-write-rate>
                    <journal-min-files>20</journal-min-files>
                    <!--journal-max-io>65000</journal-max-io-->
                    <run-sync-speed-test>false</run-sync-speed-test>
                <check-for-live-server>true</check-for-live-server>
                <backup-group-name>${live.group.a:a-live}</backup-group-name>


                <paging-directory     path="paging"     relative-to="hornetq_storage_a"/>
                <bindings-directory   path="bindings"  relative-to="hornetq_storage_a"/>
                <journal-directory path="journal"    relative-to="hornetq_storage_a"/>
                <large-messages-directory path="largemessages" relative-to="hornetq_storage_a"/>



Broadcast and Cluster Configuration

                    <broadcast-groups>
                        <broadcast-group name="bg-a">
                            <socket-binding>messaging-group</socket-binding>
                            <broadcast-period>2000</broadcast-period>
                            <connector-ref>
                                netty
                            </connector-ref>
                        </broadcast-group>
                    </broadcast-groups>

                    <discovery-groups>
                        <discovery-group name="dg-hornetq-a">
                            <socket-binding>messaging-group</socket-binding>
                            <refresh-timeout>2000</refresh-timeout>
                        </discovery-group>
                    </discovery-groups>

                    <cluster-connections>
                        <cluster-connection name="a-cluster">
                            <address>jms</address>
                            <connector-ref>netty</connector-ref>
                      <discovery-group-ref discovery-group-name="dg-hornetq-a"/>                        </cluster-connection>
                    </cluster-connections>

                    <security-settings>
                        <security-setting match="#">
                            <permission type="send" roles="guest"/>
                            <permission type="consume" roles="guest"/>
                            <permission type="createNonDurableQueue" roles="guest"/>
                            <permission type="deleteNonDurableQueue" roles="guest"/>
                        </security-setting>
                    </security-settings>

                    <address-settings>
                        <address-setting match="#">
                            <dead-letter-address>jms.queue.DLQ</dead-letter-address>
                            <expiry-address>jms.queue.ExpiryQueue</expiry-address>
                            <redelivery-delay>0</redelivery-delay>
                            <max-size-bytes>10485760</max-size-bytes>
                            <page-size-bytes>2097152</page-size-bytes>
                      <address-full-policy>BLOCK</address-full-policy>                            <message-counter-history-day-limit>10</message-counter-history-day-limit>
                        </address-setting>
                    </address-settings>

                    <jms-connection-factories>
                        <connection-factory name="InVmConnectionFactory">
                              <connectors>
                                    <connector-ref connector-name="in-vm"/>
                              </connectors>
                              <entries>
                                    <entry name="java:/ConnectionFactory"/>
                              </entries>
   
                              <producer-window-size>-1</producer-window-size>
                              <consumer-window-size>0</consumer-window-size>
                              <consumer-max-rate>-1</consumer-max-rate>
                              <producer-max-rate>-1</producer-max-rate>
                        </connection-factory>
       
                        <connection-factory name="RemoteConnectionFactory">
                            <discovery-group-ref discovery-group-name="dg-hornetq-a"/>                                 
                                  <entries>
                                        <entry name="java:/RemoteJmsXA"/>
                                        <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
                                  </entries>
                                  <ha>true</ha>
                           <block-on-acknowledge>true</block-on-acknowledge>                                  <retry-interval>1000</retry-interval>
                                  <retry-interval-multiplier>1.0</retry-interval-multiplier>
                                  <reconnect-attempts>-1</reconnect-attempts>
                                  <producer-window-size>-1</producer-window-size>
                           <consumer-window-size>0</consumer-window-size>                                  <consumer-max-rate>-1</consumer-max-rate>
                                  <producer-max-rate>-1</producer-max-rate>
                        </connection-factory>
       
                        <pooled-connection-factory name="hornetq-ra">
                                  <transaction mode="xa"/>
                                  <connectors>
                                        <connector-ref connector-name="in-vm"/>
                                  </connectors>
                                  <entries>
                                        <entry name="java:/JmsXA"/>
                                  </entries>
                                  <ha>true</ha>
                           <block-on-acknowledge>true</block-on-acknowledge>                                  <retry-interval>1000</retry-interval>
                                  <retry-interval-multiplier>1.0</retry-interval-multiplier>
                                  <reconnect-attempts>-1</reconnect-attempts>
                                 
                                  <producer-window-size>-1</producer-window-size>
                           <consumer-window-size>0</consumer-window-size>                                  <consumer-max-rate>-1</consumer-max-rate>
                                  <producer-max-rate>-1</producer-max-rate>
                        </pooled-connection-factory>
                    </jms-connection-factories>


HornetQ Backup Server

                <hornetq-server name="a-bkp">
                    <persistence-enabled>true</persistence-enabled>
                    <security-enabled>false</security-enabled>
                    <!--transaction-timeout>180000</transaction-timeout-->
                <backup>true</backup>
                    <allow-failback>true</allow-failback>
                    <failover-on-shutdown>true</failover-on-shutdown>
                    <shared-store>true</shared-store>
                    <journal-type>ASYNCIO</journal-type>
                    <!--journal-buffer-timeout>2000</journal-buffer-timeout-->
                    <journal-sync-transactional>true</journal-sync-transactional>
                    <journal-sync-non-transactional>true</journal-sync-non-transactional>
                    <log-journal-write-rate>false</log-journal-write-rate>
                    <journal-min-files>20</journal-min-files>
                    <!--journal-max-io>65000</journal-max-io-->
                    <run-sync-speed-test>false</run-sync-speed-test>
                    <check-for-live-server>true</check-for-live-server>
                    <backup-group-name>${backup.group.a:a-bkp}</backup-group-name>

               <paging-directory    path="paging"   relative-to="hornetq_storage_a_bkp"/>
               <bindings-directory path="bindings" relative-to="hornetq_storage_a_bkp"/>
               <journal-directory   path="journal"   relative-to="hornetq_storage_a_bkp"/>
               <large-messages-directory path="largemessages" relative-to="hornetq_storage_a_bkp"/>


               ... (the same lines as you put on lived server)


That's it!
Your HornetQ Cluster was created...So, you can have 2 or more hosts using <server-group name="grp-b" profile="prf-b">.

The complete file was saved into my github profile. Please, see it at:

 https://github.com/alvesfred/samples-jboss/blob/master/deploy/domain-block-hornetq-backup.xml

In this file, i created 3 profiles and 3 groups.

If you would like to know if the packages over the network have been sending, just execute the linux command below for each server/host:

 # tcpdump -vv | grep 231.3.3.3
(all udp packages will be showed for each host servers)


If you have any doubt, please let me know.

Thanks a lot and regards



Monday, May 30, 2016

Basic Authentication/Validation for Webservices using REST API and Interceptors

Hi All,
Thanks for reading this post...

Let's talk about how to implement a set of classes using REST concepts, and basic control access to the WebServices. An interceptor will be responsible for reading the request and manage the access control to the resources.

First of all, it will be necessary to define the pom.xml (maven resources) with the following dependencies:

        <dependency>
            <groupId>org.jboss.spec.javax.ws.rs</groupId>
            <artifactId>jboss-jaxrs-api_1.1_spec</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-crypto</artifactId>
            <version>${resteasy.version}</version>
            <scope>provided</scope>
        </dependency>
       
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-jaxb-provider</artifactId>
            <version>${resteasy.version}</version>
            <scope>provided</scope>
        </dependency>

JBoss EAP 6.4 and Resteasy API 2.3.10.Final were used to validate the sample code.

 - Rest Activator

@ApplicationPath("/rest")
public class WsRestActivator extends Application {
}

- Exception Class

public class ServiceAPIException extends Exception {

   public ServiceAPIException(String message) {
        super(message);
    }

    public ServiceAPIException(Exception e) {
        super(e);
    }

    public ServiceAPIException(String msg, Throwable t) {
        super(msg, t);
    }
}

@Provider
public class ExceptionHttpStatusResolver implements ExceptionMapper<ServiceAPIException> {

    @Override
    public Response toResponse(ServiceAPIException exception) {
        Response.Status httpStatus = Response.Status.INTERNAL_SERVER_ERROR;

        if (exception instanceof ServiceAPIException)
            httpStatus = Response.Status.BAD_REQUEST;

        return Response.status(httpStatus).entity(exception.getMessage()).build();
    }
}

- Annotation to allow access to the Webservice methods

@Documented
@Retention (RUNTIME)
@Target({TYPE, METHOD})
public @interface WsAccessMethodPermition {
}

- Service Abstracttion

public abstract class ServiceRest {

    protected void handleException(String msg, Throwable t) throws ServiceAPIException {
        throw new ServiceAPIException(msg, t);
    }
}

- Security Abstraction for Resource Classes

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MediaType;

import org.jboss.resteasy.security.smime.EnvelopedOutput;


public abstract class SecureResource extends ServiceRest {

    public static final String USER_CERTIFICATE = "user-certificate";
   
    private static CertificateFactory factory;

    static {
        try {
            factory = CertificateFactory.getInstance("X.509");
        } catch (Exception e) {

        }
    }

    protected X509Certificate extractCertificate(HttpServletRequest request) {
        try {
            InputStream is = new ByteArrayInputStream((byte[]) request.getAttribute(
                    SecureResource.USER_CERTIFICATE));
            return (X509Certificate) factory.generateCertificate(is);
        } catch (CertificateException e) {
            return null;
        }
    }
   
    protected EnvelopedOutput encryptResponse(HttpServletRequest request, Object result) {
        X509Certificate certificate = extractCertificate(request);
        return encryptResponse(certificate, result);
    }
   
    protected EnvelopedOutput encryptResponse(X509Certificate certificate, Object result) {
        // Object user = UserContext.getUser(result);
        EnvelopedOutput output = new EnvelopedOutput(
                new Object()/* your user object */, MediaType.APPLICATION_JSON);
        output.setCertificate(certificate);

        return output;
    }

}

- Interceptor

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.inject.Inject;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.ext.Provider;

import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.Headers;
import org.jboss.resteasy.core.ResourceMethod;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.interception.AcceptedByMethod;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import org.jboss.resteasy.util.Base64;

@Provider
@ServerInterceptor
public class SecurityInterceptor implements PreProcessInterceptor, AcceptedByMethod {

    private static final String          AUTHORIZATION_PROPERTY = "Authorization";

    private static final String          AUTHENTICATION_SCHEME  = "Basic";

    private static final ServerResponse  ACCESS_DENIED          = new ServerResponse("Access Denied!",     401, new Headers<Object>());

    private static final ServerResponse  ACCESS_FORBIDDEN       = new ServerResponse("Access Forbidden!",  403, new Headers<Object>());

    private static final ServerResponse  SERVER_ERROR           = new ServerResponse("Internal Error!",    500, new Headers<Object>());

    @Override
    public ServerResponse preProcess(HttpRequest request, ResourceMethod methodInvoked) throws Failure, WebApplicationException {
        Method method = methodInvoked.getMethod();

        if (method.isAnnotationPresent(WsAccessMethodPermition.class) ||
                method.isAnnotationPresent(PermitAll.class)) {
            return null;
        }

        // Access denied for all
        if (method.isAnnotationPresent(DenyAll.class)) {
            return ACCESS_FORBIDDEN;
        }

        // Get request headers
        final HttpHeaders headers = request.getHttpHeaders();

        // Fetch authorization header
        final List<String> authorization = headers.getRequestHeader(AUTHORIZATION_PROPERTY);

        // If no authorization information present; block access
        if (authorization == null || authorization.isEmpty()) {
            return ACCESS_DENIED;
        }

        // Get encoded username and password
        final String encodedUserPassword = authorization.get(0).replaceFirst(
                AUTHENTICATION_SCHEME.concat(" "), "");

        // Decode username and password
        String usernameAndPassword;
        try {
            usernameAndPassword = new String(Base64.decode(encodedUserPassword));
        } catch (IOException e) {
            return SERVER_ERROR;
        }

        // Split username and password tokens
        final StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");
        final String username = tokenizer.nextToken();
        final String password = tokenizer.nextToken();

        // Verify user access
        if (!isUserAllowed(request, username, password)) {
            return ACCESS_DENIED;
        }

        return null;
    }

    @SuppressWarnings("serial")
    private boolean isUserAllowed(final HttpRequest request, final String username, final String password) {
        UserWS user = new UserWS(username, password);
        if (user != null) {
            if (!user.getRoles().isEmpty() && !user.hasPermission()) {

                byte[] certificate = user.getCertificate();
                request.setAttribute(SecureResource.USER_CERTIFICATE, certificate);
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean accept(@SuppressWarnings("rawtypes") Class declaring, Method method) {

        // bypass authentication - get methods for instance
        if (method.isAnnotationPresent(WsAccessMethodPermition.class) ||
                method.isAnnotationPresent(PermitAll.class)) {
            return false;
        }

        // Access denied for all
        if (method.isAnnotationPresent(DenyAll.class)) {
            // TODO here for instance log denied access
            return true;
        }

        return true;
    }
}

And now...the resource...

- WebService Implementation

@Path("/test")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class TestResourceWS extends SecureResource {

    @POST
    @Path("/info/")
    @Produces(MediaType.APPLICATION_JSON)
    @WsAccessMethodPermition
    @Override
    public String info() throws ServiceAPIException {
        return "Hello, Access OK!";
    }

    @POST
    @Path("/infodenied/")
    @Produces(MediaType.APPLICATION_JSON)
    @Override
    public void infodenied() throws ServiceAPIException {
        // "denied!";
    }
}

- Sample invocation

http://<host>/<app-name>/rest/test/info
OK!

http://<host>/<app-name>/rest/test/infodenied
Access Denied!

- WS Client Sample...post methods for instance

   MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
   headers.add("Authorization", "Basic " + base64Creds);
   headers.add("Content-Type", "application/json");
   RestTemplate restTemplate = new RestTemplate();
   HttpEntity<ObjectToPass> request = new HttpEntity<ObjectToPass>(ObjectToPass, headers);
     restTemplate.postForObject("http://<host>/<app>/rest/test/info", request, Boolean.class);


Thanks a lot and regards!