Translate

jueves, 27 de noviembre de 2014

Webservice Example with axis2 part 2: Understanding a webservice

This is the second post to show how to create a web service with a simple operation and a complex operation based on Axis2.

In this series of posts we are going to show this points:









Now we are going to learn how a webservice works and the main concepts.

The main part of a webservice is the WSDL file that describes the webservice interface. This interface describes the available operations in the webservice and the input and output parameters of all operations. This file will be the defined using a template java class and the java2wsld java tool that transform a java class in a WSDL file.

Another important concept of the webservice is the endpoint, the endpoint is an URL that you have to know in order to use the webservice. This endpoint is where the server are listening for your requests and where the server code are executed when a webservice operation is called. Finally an output is returned to the client in order to response to the request, this is the server part of the webservice.

The WSDL file is always public and you can access it via URL to see the available operations and mainly to build a client using the wsdl2code java tool that can create a collection of java classes based on a WSDL file in order to use the webservice. With this client you can invoke the available operation of the webservice, this is the client part of the webservice.

This comunication bettwen the client and the server part of the webservice is made by the soap protocol (Simple Object Access Protocol). 




Example:

We have the webservice named Axis2ServiceExample  with the next operation:

Name: simpleOperation
Input Parameters: number1: Integer, number2: Integer
Output Parameters: Integer - Return the add of the input numbers.

WSDL File: http://localhost:9763/services/Axis2ServiceExample?wsdl
endpoint:  http://localhost:9763/services/Axis2ServiceExample/

All of this things are defined in the WSDL file, in the next sections we will see how to the create all parts of the webservice and call to the operation.

References:





sábado, 8 de noviembre de 2014

Webservice Example with axis2 part1: Setting environtment

This is the first post to show how to create a web service with a simple operation and a complex operation based on Axis2.

In this series of posts we are going to show this points:

The first thing to do is set up the necesary environtment to create the web service. Download the next sofware and configure the environment variables:

•    Java SDK version 1.6.0_45 or later.
•    Windows environment variable JAVA_HOME pointing to Java location (C:\Program Files\Java\jdk1.6.0_45)
•    Eclipse IDE version 4.3 Kepler or later.
•    Apache Maven version 3.1.1 (Embedded in IDE or installed in local machine to use it in command line console).
•    Add the apache Maven bin directory path to the Windows environment variable Path
•    Apache Ant version 1.9.4, installed in your local machine.
•    Add the apache Ant bin directory path to the Windows environment variable Path
•    Apache axis2 version 1.6.0  (binary distribution). Libraries XMLBeans version 2.3.0 and axiom version 1.2.11 are included in axis2.
•    Windows environment variable AXIS2_HOME pointing to Axis2 location (C:\axis2-1.6.0)
•    WSO2 application server version 4.0.1 to deploy Web services.  (you have to download the version 5.0.0 in the download page)

The next step is check if all the elements are properly installed.

JAVA
Open a dos command window and execute java -version





ECLIPSE
Execute the eclipse.exe in your eclipse installation



APACHE MAVEN

Open a dos command window and execute mvn -version





ANT
Open a dos command window and execute ant -version



AXIS2
Open a dos command and execute echo %AXIS2_HOME% and check that path y correct.



WSO2 - Application Server
Open a dos windows and run the server using this command.
[WSO2-Installation-folder]/bin/wso2server.bat



Open browser and copy the url that appears in the last line of the output

Enter user admin and password admin





If you are here everything has going ok.



    lunes, 20 de octubre de 2014

    Jenkins: Pool SCM always detect changes

    Jenkins: Consultar repositorio (SCM) siempre detecta cambios.

    Today a quick issue that has happened to me, i was configuring a new Jenkins project as always but the Pool SMC to SVN repository was always detecting changes and triggering a new build.

    This was my normal Jenkins configuration:

    1 - SVN repository URL to my company interal SVN
    2 - Always Check a fresh copy
    3 - Pool SCM each 5 minutes.



    The configuration was ok, but Jenkins was triggering a build each 5 minutes because it was always deteting changes in the SVN repository.

    After "googleling" a while, made some test, and copy the SVN repository URL in a browser i realised that my SVN URL was not the original one. The server was redirecting to another URL i dont know why, maybe due to the https connection.

    The original URL was:

    https://xxxx.yyy.es:443/svn/myproject/trunk

    and the server redirected to

    http://xxxx.yyy.es:8008/svn/myproject/trunk 

    After changing the SVN URL to the final redirect it started to work properly again and it only triggers a build after changes has been uploaded to the reposository.




    Be careful with servers redirects


    references:

    jenkins-scm-triggering-constant-builds-despite-no-change




    martes, 1 de julio de 2014

    Remote Debug in tomcat 6 and 7

    Título: Debug remoto sobre servidor de aplicaciones Tomcat 6 y 7.

    What happends when we can´t install and application in a local tomcat in order to debug some issue o bug?

    The answer is easy, remote debug y the key. It allows you to debug the code in the same way like if your web application was installed in your machine.

    Note: You have to have installed in your local machine the same code that is in the remote machine to do properly remote debug.

    Configuration:

    1 - Remote server´s configuration: The remote server have to be setted with params to determine a port (8000 for example) where the server will listen to a remote debug connection.

    When you run tomcat you have to pass to virtual machine this params:

    -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n

    The easy way to do it is to edit the file [tomcat_installation]\bin\setenv.bat and add this lines

    set DEBUG=-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n
    set JAVA_OPTS=%JAVA_OPTS% %DEBUG%              

    2 - Local configuration (eclipse):

    You have to create a Remote Java Application in Debug Configurations:



    With the next options, setting a socket with the remote server host and port 8000 .



    don´t forget to select the Project where the source code is located.

    Happy Debug!!!


    domingo, 23 de marzo de 2014

    MongoDB Spring Security Code Example

    Titulo: Ejemplo práctico de Spring Security con MongoDB con código fuente.

    I have decided to change the main language of my blog in order to reach and share everything with more people.

    In this post you can see the next topics

    - SpringData With MongoDb Integration
    - Spring MVC to manage navigation
    - Spring Security with Custom user detais service to assign roles and web application authentication.




    Everything is easy and separated in different files to be more understandable and you have all the code in github.

    This example is based on the book Spring Security 3.x Cookbook  that cover a lot of spring security integrations with different technologies:
    1. ORM (Hibernate) and NoSQL Databases (MongoDB) 
    2. JSF
    3. JSP
    4. Struts 2
    5. GWT
    6. Grails
    7. Vaadin
    8. Wicked
    9. Facebook, Twitter
    10. WebServices: RESTFull, SOAP
    11. Captcha Integration
    12. and more all with code samples
    After this recommendation, lets go to show the example, all the code you can find it in my GitHub repository.

    Please download the code as ZIP or fork the repository to follow the example.

    To run the example you have the following requirements:
    1- Eclipse Kepler to import the project from github or zip file.
    2 - Document data base MongoDB installed in the same machine as your application server.
    3 - Application Server Apache Tomcat 7
    4 - Configure your application path context to "/" in ordet to Spring Security secure your URL.



    Import the project into eclipse like a Maven project and deploy it in a Tomcat server sever with the above path configuration.

    Populate you MongoDB database with users data, you can do it easily executing this test file in the application.UserPopulateCollection.java

    Remember to uncomment the //@Test line.



    or insert in the Mongo Database the next data into User Collection




    The application  is a 4 screens application, we have a Login page where you can login like:

    1 - Admin User (Role 1 - ROLE_ADMIN): You can access to User and Campaign pages but not create new campaigns.
    2 - Campaign User (Role 2 - ROLE_CAMPAIGN): You only can access to Campaign page and create new one, but you can not access to users pages.


    You can access the application from the following url using any of these users

    http://localhost:8080/login

    User Admin
    user: user1@antuansoft.es
    pwd: 123

    User Campaign
    user: user2@antuansoft.es
    pwd 123


    Menu page with the different application´s options Users and Campaings.



    Users page where you have all the info about your application users.




    Campaing page where you can access to all information of your campaings and can add and delete it



    I think it's time we have a look at the project configuration files,

    A - pom.xml

    In this file you can see al the dependencies that we need, all of this related with Spring and MongoDB.

    B - web.xml

    Here we have the main project configuration, where the application server starts reading de config files.

    Open the file in github or in your eclipse project and you can see:
    1- The Spring Security filter configuration to secure all the URLs
    2 - Spring MVC servlet dispatcher to manager all the URL requests.
    3 - Log4J configuration
    4 - Spring modules (Spring Data, Spring Security, Spring MVC) configuration files

     <context-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>
          /WEB-INF/mvc-config.xml
          /WEB-INF/security-config.xml       
          /WEB-INF/mongo-config.xml
         </param-value>
     </context-param>
            
    

    C - mvc-config.xml

    In this file there are the basic MVC configuration and packages to scan.

    1 - Set the Spring context to  manage requests with the Spring MVC Controllers with the tag        <mvc:annotation-driven />
    2 - Set the packages to scan Spring beans annotated with @RequestMapping @Component, etc...

      <context:component-scan base-package="com.antuansoft.spring.mvc">  
      <context:component-scan base-package="com.antuansoft.spring.security">  
    

    3 - Define the views configuration location ant type, in this case with jsp, using JSTL.

    D - mongo-config.xml

    Here we have the MongDB configuration

    1 - We define the database parameters, host and port and the database name in the mongoDbFactory. This is the main configuration to connect with database.

    2- Define the MongoRepositories, this is where Spring Data is going to scan to look for Mongo DAOS (Mongo Data Acces Objects). In this DAOS is where all the database operations (save, delete, etc.) and the domain objects (User, and Campaign) are defined.

    <mongo:repositories base-package="com.antuansoft.mongodb.repositories" />
    
    
    E - security-config.xml

    The security configuration of the application is defined here.

    1 - Enable the @PreAuthorize annotation that will be user in MainController class

    2 - Secure the application´s  urls. Due to this config is important to change the application path context to "/" like we said above.
       - /login, /logout and /accessdenied urls are permited to authenticated and not  authenticated users.
       - to access to /menu you have to be authenticated with ROLE_ADMIN or ROLE_CAMPAIGN
       - to access to /listUsers you have to be authenticated with ROLE_ADMIN
       - to access to /listCampaigns you have to be authenticated with ROLE_ADMIN or ROLE_CAMPAIGN
       - Finally the spring security login form is too easy to understand.


    3 - The most important part is the definition of a custom class (mongoUserDetailsService) to authenticate users application access. An the password encoding, here we use plain text but  i recommend  to use MD5.

    <authentication-manager alias="authenticationManager">
     <authentication-provider user-service-ref="mongoUserDetailsService">
       <password-encoder hash="plaintext" />
      </authentication-provider>
     </authentication-manager>
    

    After configuration files we are going to review the specific Java files to understand the Spring Data, Spring Mvc and Spring Security features.

    Spring Security:

    Open the file MongoUserDetailsService.java

    This is the file we have defined in security-config.xml as the authentication provider, this class have to implement the SpringFramework interface UserDetailsService and create the method UserDetailsService.

    This method is used to check if the user data send in login form is valid against your database info, this method have to return a org.springframework.security.core.userdetails.User class with the data of the user found in your database.

    You have to query your user collection and get the user info, we use the method getUserDetail that call to userRepositoryDao.findByUsername(username);

    After getting  user info and based on this, the user role is defined in getAuthorities method.and pass it to UserDetails object.

    getUserDetail  and getAuthorities are two methods that you can customize to set the authentication and the user Rols according yo your requirements.

     private org.springframework.security.core.userdetails.User userdetails;
     public UserDetails loadUserByUsername(String username)
                throws UsernameNotFoundException {
            boolean enabled = true;
            boolean accountNonExpired = true;
            boolean credentialsNonExpired = true;
            boolean accountNonLocked = true;
            com.antuansoft.mongodb.domain.User user = getUserDetail(username);
            
            userdetails = new User(user.getUsername(), 
                        user.getPassword(),
                        enabled,
                        accountNonExpired,
                        credentialsNonExpired,
                        accountNonLocked,
                        getAuthorities(user.getRole()));
                return userdetails;
        }
    
        public List getAuthorities(Integer role) {
            List authList = new ArrayList();
            if (role.intValue() == 1) {
                authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
    
            } else if (role.intValue() == 2) {
                authList.add(new SimpleGrantedAuthority("ROLE_CAMPAIGN"));
            }
            System.out.println(authList);
            return authList;
        }
    
        public com.antuansoft.mongodb.domain.User getUserDetail(String username) {
         com.antuansoft.mongodb.domain.User user = userRepositoryDao.findByUsername(username);
            //System.out.println(user.toString());
            return user;
        }
    


    MongoDB:

    Here we have two things to consider, Domain classes and Dao interfaces.

    1 - Domain classes

    This classes are plain old java objects (pojos) to define the data of your database collections, in other words the objects that your are going to persists in your database.

    Look at the com.antuansoft.mongodb.domain packge and you will find the two documents that we are going to use in this application. User and Campaign.

    The only thing that is special in the classes is that they are annotated with @Document and specify a collection where this pojo will be stored.

    @Document(collection = "campaign" )
    public class Campaign {
    


    You can open this file to see that.

    Campaign.java
    User.java

    2 - DAO interfaces:

    Dao interfacesare in com.antuansoft.mongodb.repositories package and here is where all the database operations (save, delete, etc.) and the domain objects (User, and Campaign) are defined.

    In mongo-config.xml file we have defined this package to be scanned to look for mongo repositories, its means that Spring Context transform this interfaces in a DAO object with all the basic operations like create, read, update,delete where we can use in the application.

    This classes only have to extend from org.springframework.data.repository.CrudRepository to work.

    --
    public interface UserRepositoryDao extends CrudRepository<User, String> {
     
     
     public User findByUsername(String username);
    
    }
    
    --

    This Crud repository has two params <User, String>, here is  where bind the User domain pojo to this Repository Dao. Here we indicate that this Dao process User Object and the ID´s type is String.

    In UserRepositoyDao there is something special, it is a special method user for authentication findByUsername. Another feature of SpringData is that you can define query methods without write any line of code.

    Here we have defined a query to find a user by a username, only with key words. find+By+field to query in user pojo object (findByUsername). And it´s work!!!! is magic!!

    Spring MVC:

    Finally the only thing that we have to review is the controller that allows us to navigate through the application.

    The MainController class is a basic class that use the SpringMVC annotations, @RequestMapping,  to navigate:

    @RequestMapping(value = "/listCampaigns", method = RequestMethod.GET)
     public String listCampaigns(ModelMap map) {
      
      map.addAttribute("new_campaign", new Campaign());
      Iterable campaings= campaignRepositoryDao.findAll();
      map.addAttribute("campaigns",campaings);
      
      return "listCampaigns";
     }
    


    and basically it means that when SpringMVC detects this urls the method will be executed, in this case the method pass to listCampaigns.jsp all the campaings and new campaing object.

    In this class we have a little special thing that add a spring security functionality, it´s the @PreAuthorize annotation that only allow to ROLE_CAMPAIGN users to add a new Campaign.


    @PreAuthorize("hasRole('ROLE_CAMPAIGN')")
     @RequestMapping(value = "/addCampaing", method = RequestMethod.POST)
     public String addCampaign(@ModelAttribute(value = "new_campaign") 
                                      Campaign new_campaign,
                 BindingResult result){
      
      new_campaign.setId(UUID.randomUUID().toString());
      campaignRepositoryDao.save(new_campaign);
      
      return "redirect:/listCampaigns";
     }
    

    And this its all, i thinks that it is a complete example a not too difficult to understand.

    Remember that you have all the code in my GitHub repository.


    References:

    Mainly Spring Security 3.x Cookbook

    Spring Data MongoDB
    Spring Security
    Spring MVC


    domingo, 9 de febrero de 2014

    Ejemplo fácil de Spring REST con código fuente

    Este es una ejemplo que me ha parecido muy útil y sencillo realizado por,  , un miembro la comunidad Spring en Linkedin.



    Lo tiene muy bien explicado en un vídeo que os pongo a continuación y el código en github, que también os pongo. Además su inglés se entiende muy fácilmente.




    Código fuente en github


    sábado, 1 de febrero de 2014

    Weblogic: supervisión de rendimiento del Pool de conexiones

    Una de las características que más me gustan de servidor de aplicaciones Weblogic es toda la gama de menús y opciones de supervisión de que tiene.

    En mi caso he tenido que utilizar varias veces los elementos de supervisión para solucionar varios problemas de rendimiento que se producían en la aplicación.

    Supervisión del Pool de conexiones:

    Para acceder a la supervisión del pool de conexiones del dominios de tu servidor Weblogic 11g tenemos que acceder de la siguiente manera.

    Entramos en la consola de administración de nuestro servidor:

    http://127.0.0.1:7001/console

    Y en la estructura de dominio pulsamos en Entorno>>Servidores

    Y seleccionamos el servidor que queremos supervisar en nuestro caso AdminServer


    Después vamos a la pestaña de supervisión>>JDBC y selecciona el pool de conexiones que queremos supervisar



    Seleccionamos el pool de conexiones y vemos toda la información que Weblogic nos da:


    Hay muchos más pero los más relevantes para mi han sido los que vemos en la imagen.

    El valor más importante es el Recuento Actual de conexiones activas, que son las conexiones que hay activas en el servidor en este momento. Este valor tendrá que ser 0 al final de hacer test de stress a nuestro servidor donde realizamos pruebas a nuestra aplicación cargándola con multiples peticiones concurrentes que accedan a base de datos. Si el valor fuera distinto de 0 es que las conexiones que hemos pedido la pool de conexiones no se han cerrado correctamente y eso es un grave problema.

    Otro valor importante es el Recuento total de esperas de conexión que nos indica que la aplicación ha solicitado una conexión al pool y no tenía conexiones disponibles y ha tenido que esperar para conseguir una conexión libre del pool.

    Por último otro valor interesante el Total de Fallos de esperas de conexión, este valor quiere decir que alguna de las solicitudes de conexión anteriores no obtuvo una conexión en el tiempo requerido y dió un error de timeOut porque no había nunguna conexión disponible. Esto quiere decir que nuestro sistema estaba muy cargado y no fue capaz de responder a tantas peticiones.






    martes, 7 de enero de 2014

    Oracle JDBC: Como usar una secuencia en un INSERT y recuperar el valor generado

    La problemática de hoy surge cuando tengo que hacer un INSERT en mi tabla de notificaciones y necesito que la clave primaria de mi notificación se una valor único.

    Lo primero que se te ocurre y en lo que puedes caer en la tentación es en coger el valor más alto de las que ya hay insertadas y sumarle 1.


    String strSQL="select max(notif_id) from notifications";
    pstmt = conn.prepareStatement(strSQL);
    ResultSet rs = pstmt.executeQuery();            
    int uniqueId = (rs!=null && rs.next())?rs.getInt(1)+1:0;
    


    Pero inmediatamente te das cuenta de que eso puede llevar a conflictos si hay muchas inserciones a la vez y alguno puede duplicar la clave.

    Así que lo mejor es crear una secuencia en Oracle y usarla en nuestro INSERT.

    Con TOAD podemos crear una secuencia fácilmente llamada NOTIF_ID_SEQ con los siguientes parámetros




    Y utilizar la en nuestra INSERT llamando al operador NOTIF_ID_SEQ.nextval


    String strSQL="insert INTO NOTIFICATIONS " +
                  "(USER_ID,PROVIDER_ID,NOTIF_ID) " +                 
                  "VALUES (?,?,NOTIF_ID_SEQ.nextval)";
                                                                                         
    pstmt = conn.prepareStatement(strSQL);
    pstmt.setString(1, userId);               
    pstmt.setInt(2, providerId); 
    pstmt.executeUpdate(); 
    


    Con esto garantizamos que el valor de nuestro identificador es único y es el dado por nuestra secuencia.

    Otra problemática que nos surge inmediatamente en esta casuistica es que podemos querer recuperar el valor generado por la secuencia para usarlo en otro lugar.

    Para ello utilizamos el método getGeneratedKeys() del PrepareStatement pero debemos decirle al PreparedStatement que columnas son las que se autogeneran en un Array de Strings en nuestro caso "NOTIF_ID"

    Veamos un ejemplo:


    String generatedColumns[] = {"NOTIF_ID"};                                               
    pstmt = conn.prepareStatement(strSQL,generatedColumns);
    
    String strSQL="insert INTO NOTIFICATIONS " +
                  "(USER_ID,PROVIDER_ID,NOTIF_ID) " +                 
                  "VALUES (?,?,NOTIF_ID_SEQ.nextval)";
                                                                                         
    pstmt = conn.prepareStatement(strSQL);
    pstmt.setString(1, userId);               
    pstmt.setInt(2, providerId); 
    pstmt.executeUpdate(); 
    
    //Get the generated key
    ResultSet generatedKeys = pstmt.getGeneratedKeys();
    if (null != generatedKeys && generatedKeys.next()) {
      int primaryKey = generatedKeys.getInt(1);
      System.out.println(primaryKey);
    }
    



    Referencias:

    how to get the inserted row primary key with out  using select statement

    getGeneratedKeys()

    How to use Oracle sequence in preparedstatement

    Oracle Java JDBC: Get Primary Key Of Inserted Record




    jueves, 2 de enero de 2014

    Oracle: Query para restar minutos a la fecha del sistema

    La problemática de hoy viene dada por la necesidad de recuperar en una base de datos Oracle los usuarios que han tenido interacción con la aplicación en los últimos 15 minutos.

    En mi caso tengo un campo en mi tabla de usuarios que registra cuando ha sido la última actualización o acceso de este usuario a la aplicación.

    La query a realizar se la siguiente:

    SELECT * FROM users WHERE LAST_UPDATED_DATE > SYSTIMESTAMP - (?/1440)

    Donde ? tenemos que sustituirlo por el número de minutos que queremos restar a la fecha del sistema.

    SYSTIMESTAMP nos devuelve la fecha del sistema incluyendo hora minutos y segundos con el TimeZone de la base de datos.

    El valor de 1440 es porque un día tiene 1440 minutos 24 x 60. Y usamos minutos en este formato ya que lo que se resta normalmente a SYSTIMESTAMP son días.

    Por lo tanto mi query final es la siguiente:

    PreparedStatement pstmt = null;       
    ResultSet rSet = null;
    Connection conn = null;        
    int minutes = 15;
    ........
    ........
    String strSQL="select from users where LAST_UPDATED_DATE > SYSTIMESTAMP-(?/1440)";
    
    pstmt = conn.prepareStatement(strSQL);
    pstmt.setInt(1, minutes);                     
    rSet = pstmt.executeQuery();
    
    
    Referencias:
    
    
    Time Aritmetic with Oracle
    SYSTIMESTAMP