diff --git a/.env.example b/.env.example
index 436b0a3f9a76c8e99d9ca8b0c25135f49393b7cb..ea267e5ee34941861809f983d375cc33fae636c1 100644
--- a/.env.example
+++ b/.env.example
@@ -1,3 +1,5 @@
 DATABASE_URL=jdbc:mysql://{host??}:{port??}/{database_name??}
 DATABASE_USERNAME=
-DATABASE_PASSWORD=
\ No newline at end of file
+DATABASE_PASSWORD=
+API_KEY=
+EXPIRATION_DAYS=
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 91cb86d91114ebcd4947753e66ab52ab011b2d4c..639daede46f78db37c3cafa2f064b6c9d110414d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,7 +41,7 @@
         <dependency>
             <groupId>org.hibernate</groupId>
             <artifactId>hibernate-java8</artifactId>
-            <version>6.0.0.Alpha7</version>
+            <version>5.6.15.Final</version>
         </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/src/main/java/App.java b/src/main/java/App.java
index c736f347fa4ec6b11955499f5f06f47e7d6a49f3..bb905f9271fbbdb0021870785ac5a873439d172a 100644
--- a/src/main/java/App.java
+++ b/src/main/java/App.java
@@ -1,4 +1,4 @@
-import org.tonality.ws.Subscription;
+import org.tonality.service.Subscription;
 
 import javax.xml.ws.Endpoint;
 
diff --git a/src/main/java/org/tonality/middleware/BaseMiddleware.java b/src/main/java/org/tonality/middleware/BaseMiddleware.java
new file mode 100644
index 0000000000000000000000000000000000000000..25ea1adccc76630d0a62844be1077d53d8e89305
--- /dev/null
+++ b/src/main/java/org/tonality/middleware/BaseMiddleware.java
@@ -0,0 +1,5 @@
+package org.tonality.middleware;
+
+public abstract class BaseMiddleware<T> {
+    abstract public T execute(T entity);
+}
diff --git a/src/main/java/org/tonality/middleware/SubscriptionMiddleware.java b/src/main/java/org/tonality/middleware/SubscriptionMiddleware.java
new file mode 100644
index 0000000000000000000000000000000000000000..a153bc91ade249dcca87fb198e03963c4c4f1ef3
--- /dev/null
+++ b/src/main/java/org/tonality/middleware/SubscriptionMiddleware.java
@@ -0,0 +1,29 @@
+package org.tonality.middleware;
+
+import org.tonality.repository.Subscription;
+import org.tonality.type.SubscriptionStatus;
+
+import javax.persistence.EntityManager;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+public class SubscriptionMiddleware extends BaseMiddleware<org.tonality.model.Subscription> {
+    @Override
+    public org.tonality.model.Subscription execute(org.tonality.model.Subscription entity) {
+        if (entity.getStatus() == SubscriptionStatus.ACTIVE
+                && new Date().getTime() - entity.getUpdatedAt().getTime() > (long) Integer.parseInt(System.getenv("EXPIRATION_DAYS")) * 60 * 60 * 1000) {
+            entity.setStatus(SubscriptionStatus.EXPIRED);
+            Subscription.getInstance().update(entity);
+        }
+        return entity;
+    }
+
+    public List<org.tonality.model.Subscription> execute(List<org.tonality.model.Subscription> entities) {
+        List<org.tonality.model.Subscription> result = new ArrayList<>();
+        for (org.tonality.model.Subscription entity : entities) {
+            result.add(this.execute(entity));
+        }
+        return result;
+    }
+}
diff --git a/src/main/java/org/tonality/model/Subscription.java b/src/main/java/org/tonality/model/Subscription.java
index 95ae9c33f8cb13d5306631c9a8ba880828f0f981..3d7775ed2b1d0e1bd856ed035264b5de9f05bdf0 100644
--- a/src/main/java/org/tonality/model/Subscription.java
+++ b/src/main/java/org/tonality/model/Subscription.java
@@ -3,9 +3,6 @@ package org.tonality.model;
 import lombok.Getter;
 import lombok.Setter;
 
-import org.hibernate.Session;
-import org.hibernate.SessionFactory;
-import org.hibernate.Transaction;
 import org.hibernate.annotations.CreationTimestamp;
 import org.hibernate.annotations.UpdateTimestamp;
 import org.tonality.type.SubscriptionStatus;
@@ -26,7 +23,16 @@ public class Subscription implements Serializable {
     private long userId;
 
     @Id
-    private long albumId;
+    private long premiumAlbumId;
+
+    @Column(name = "username", nullable = false)
+    private String username;
+
+    @Column(name = "album_name", nullable = false)
+    private String albumName;
+
+    @Column(name = "artist", nullable = false)
+    private String artist;
 
     @Column(name = "subscription_status", nullable = false)
     @Enumerated(EnumType.STRING)
@@ -59,6 +65,6 @@ public class Subscription implements Serializable {
     }
 
     public String toString() {
-        return "Subscription: \n" + "userId :" + userId + " \nalbumId : " + albumId + " \nstatus: " + status;
+        return "Subscription: \n" + "userId :" + userId + "\n" + "username :" + username + "\n" + "premiumAlbumId :" + premiumAlbumId + "\n" + "albumName :" + albumName + "\n" + "artist :" + artist + "\n" + "status :" + status + "\n" + "createdAt :" + createdAt + "\n" + "updatedAt :" + updatedAt + "\n";
     }
 }
diff --git a/src/main/java/org/tonality/model/SubscriptionId.java b/src/main/java/org/tonality/model/SubscriptionId.java
index 6ad39bf9187689e396683abf5cfca1403565665c..7b834d04b3713d7f50465a14868da4f0d9362cd2 100644
--- a/src/main/java/org/tonality/model/SubscriptionId.java
+++ b/src/main/java/org/tonality/model/SubscriptionId.java
@@ -12,27 +12,27 @@ public class SubscriptionId implements Serializable {
     @Column(name = "user_id", nullable = false)
     private long userId;
 
-    @Column(name = "album_id", nullable = false)
-    private long albumId;
+    @Column(name = "premium_album_id", nullable = false)
+    private long premiumAlbumId;
 
     public SubscriptionId() {}
 
-    public SubscriptionId(long userId, long albumId) {
+    public SubscriptionId(long userId, long premiumAlbumId) {
         this.userId = userId;
-        this.albumId = albumId;
+        this.premiumAlbumId = premiumAlbumId;
     }
 
     @Override
     public boolean equals(Object o) {
         if (o instanceof SubscriptionId) {
             SubscriptionId other = (SubscriptionId) o;
-            return (userId == other.userId) && (albumId == other.albumId);
+            return (userId == other.userId) && (premiumAlbumId == other.premiumAlbumId);
         }
         return false;
     }
 
     @Override
     public int hashCode() {
-        return (int) (userId + albumId);
+        return (int) (userId + premiumAlbumId);
     }
 }
diff --git a/src/main/java/org/tonality/repository/BaseRepository.java b/src/main/java/org/tonality/repository/BaseRepository.java
index 55054d8d3f8652eb94e5f6d203e1bed089a7e06e..7a3db09eaee9166f09ee47ac7a13a5147f5abd54 100644
--- a/src/main/java/org/tonality/repository/BaseRepository.java
+++ b/src/main/java/org/tonality/repository/BaseRepository.java
@@ -60,7 +60,7 @@ public abstract class BaseRepository<T> {
     }
 
     // get by conditions
-    public List<T> search(Map<String, Object>andConditions, Map<String, Object> orConditions) {
+    public List<T> search(Map<String, Object> andConditions, Map<String, Object> orConditions, String searchInput, List<String> searchField, String orderBy, int page, int size) {
         try {
             SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
             EntityManager entityManager = sessionFactory.createEntityManager();
@@ -68,28 +68,50 @@ public abstract class BaseRepository<T> {
             CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
             CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(this.getEntityClass());
             Root<T> root = criteriaQuery.from(this.getEntityClass());
+            List<Predicate> predicates = new java.util.ArrayList<>();
 
             // and conditions
             Predicate andPredicate = criteriaBuilder.conjunction();
             for (Map.Entry<String, Object> entry : andConditions.entrySet()) {
                 andPredicate = criteriaBuilder.and(andPredicate, criteriaBuilder.equal(root.get(entry.getKey()), entry.getValue()));
             }
+            if (andPredicate.getExpressions().size() > 0) {
+                predicates.add(andPredicate);
+            }
 
             // or conditions
             Predicate orPredicate = criteriaBuilder.disjunction();
             for (Map.Entry<String, Object> entry : orConditions.entrySet()) {
                 orPredicate = criteriaBuilder.or(orPredicate, criteriaBuilder.equal(root.get(entry.getKey()), entry.getValue()));
             }
+            if (orPredicate.getExpressions().size() > 0) {
+                predicates.add(orPredicate);
+            }
+
+            // order by
+            criteriaQuery.orderBy(criteriaBuilder.asc(root.get(orderBy)));
+
+            // pagination
+            int offset = (page - 1) * size;
+
+            // like query
+            Predicate likePredicate = criteriaBuilder.disjunction();
+            if (!searchInput.isEmpty()) {
+                for (String field : searchField) {
+                    likePredicate = criteriaBuilder.or(likePredicate, criteriaBuilder.like(root.get(field), "%" + searchInput + "%"));
+                }
+            }
+            if (likePredicate.getExpressions().size() > 0) {
+                predicates.add(likePredicate);
+            }
 
-            if (andPredicate.getExpressions().size() > 0 && orPredicate.getExpressions().size() > 0) {
-                criteriaQuery.where(criteriaBuilder.and(andPredicate, orPredicate));
-            } else if (andPredicate.getExpressions().size() > 0) {
-                criteriaQuery.where(andPredicate);
-            } else if (orPredicate.getExpressions().size() > 0) {
-                criteriaQuery.where(orPredicate);
+            if (predicates.size() > 0) {
+                criteriaQuery.where(predicates.toArray(new Predicate[0]));
+            } else {
+                criteriaQuery.where();
             }
 
-            List<T> entities = entityManager.createQuery(criteriaQuery).getResultList();
+            List<T> entities = entityManager.createQuery(criteriaQuery).setFirstResult(offset).setMaxResults(size).getResultList();
             entityManager.getTransaction().commit();
             entityManager.close();
             return entities;
diff --git a/src/main/java/org/tonality/repository/Subscription.java b/src/main/java/org/tonality/repository/Subscription.java
index 8f1961eef3f0e09666355d015338d4e4b29fcdf9..d419af0812deaa0df2724312f5eedee702baf0f2 100644
--- a/src/main/java/org/tonality/repository/Subscription.java
+++ b/src/main/java/org/tonality/repository/Subscription.java
@@ -1,7 +1,9 @@
 package org.tonality.repository;
 
 import org.tonality.model.SubscriptionId;
+import org.tonality.type.SubscriptionStatus;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -20,6 +22,136 @@ public class Subscription extends BaseRepository<org.tonality.model.Subscription
         return instance;
     }
 
+    public org.tonality.model.Subscription createSubscription(long userId, String username, long premiumAlbumId, String albumName, String artist) {
+        try {
+            org.tonality.model.Subscription subscription = new org.tonality.model.Subscription();
+            subscription.setUserId(userId);
+            subscription.setUsername(username);
+            subscription.setPremiumAlbumId(premiumAlbumId);
+            subscription.setAlbumName(albumName);
+            subscription.setArtist(artist);
+            if (org.tonality.repository.Subscription.getInstance().add(subscription) == null) {
+                throw new Exception("Failed to create subscription");
+            }
+            return subscription;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public org.tonality.model.Subscription updateSubscription(long userId, long premiumAlbumId, SubscriptionStatus status) {
+        try {
+            org.tonality.model.Subscription subscription = org.tonality.repository.Subscription.getInstance().getById(new org.tonality.model.SubscriptionId(userId, premiumAlbumId));
+            subscription.setStatus(status);
+            if (update(subscription) == null) {
+                throw new Exception("Failed to update subscription");
+            }
+            return subscription;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public List<org.tonality.model.Subscription> searchSubscriptions(SubscriptionStatus status, String searchInput, String orderBy, int page, int size) {
+        try {
+            if (searchInput == null || searchInput.isEmpty() || searchInput.equals("[string?]")) {
+                searchInput = "";
+            }
+
+            if (orderBy == null || orderBy.isEmpty() || orderBy.equals("[string?]")) {
+                orderBy = "albumName";
+            } else {
+                orderBy = orderBy.replaceAll(" ", "_");
+            }
+
+            if (page < 1) {
+                page = 1;
+            }
+            if (size < 1) {
+                size = 15;
+            }
+
+            java.util.Map<String, Object> andConditions = new java.util.HashMap<>();
+            andConditions.put("status", status);
+            java.util.Map<String, Object> orConditions = new java.util.HashMap<>();
+            ArrayList<String> searchField = new ArrayList<>();
+            searchField.add("username");
+            searchField.add("artist");
+            searchField.add("albumName");
+            return search(andConditions, orConditions, searchInput, searchField, orderBy, page, size);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public List<org.tonality.model.Subscription> getSubscriptionByStatus(SubscriptionStatus status, String orderBy, int page, int size) {
+        try {
+            if (orderBy == null || orderBy.isEmpty() || orderBy.equals("[string?]")) {
+                orderBy = "albumName";
+            } else {
+                orderBy = orderBy.replaceAll(" ", "_");
+            }
+
+            if (page < 1) {
+                page = 1;
+            }
+            if (size < 1) {
+                size = 15;
+            }
+
+            java.util.Map<String, Object> andConditions = new java.util.HashMap<>();
+            andConditions.put("status", status);
+            java.util.Map<String, Object> orConditions = new java.util.HashMap<>();
+            return search(andConditions, orConditions, "", new ArrayList<>(), orderBy, page, size);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public List<org.tonality.model.Subscription> getSubscriptionsByUserId(long userId, int page, int size) {
+        try {
+            java.util.Map<String, Object> andConditions = new java.util.HashMap<>();
+            andConditions.put("userId", userId);
+            java.util.Map<String, Object> orConditions = new java.util.HashMap<>();
+            return search(andConditions, orConditions, "", new ArrayList<>(), "albumName", page, size);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public boolean deleteSubscriptionsByUserId(long userId) {
+        try {
+            java.util.Map<String, Object> conditions = new java.util.HashMap<>();
+            conditions.put("userId", userId);
+            if (!delete(conditions)) {
+                throw new Exception("Failed to delete subscriptions");
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public boolean deleteSubscriptionsByAlbumId(long premiumAlbumId) {
+        try {
+            java.util.Map<String, Object> conditions = new java.util.HashMap<>();
+            conditions.put("premiumAlbumId", premiumAlbumId);
+            if (!delete(conditions)) {
+                throw new Exception("Failed to delete subscriptions");
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
     // Test
     public static void main(String[] args) {
         Subscription subscription = Subscription.getInstance();
@@ -29,7 +161,10 @@ public class Subscription extends BaseRepository<org.tonality.model.Subscription
         for (int i = 1; i < 4; i++) {
             for (int j = 1; j < 4; j++) {
                 entity.setUserId(i);
-                entity.setAlbumId(j);
+                entity.setPremiumAlbumId(j);
+                entity.setUsername("User " + i);
+                entity.setAlbumName("Album " + j);
+                entity.setArtist("Artist " + 10);
                 System.out.println(subscription.add(entity));
             }
         }
@@ -47,7 +182,7 @@ public class Subscription extends BaseRepository<org.tonality.model.Subscription
         Map<String, Object> andConditions = new java.util.HashMap<>();
         andConditions.put("status", org.tonality.type.SubscriptionStatus.ACTIVE.toString());
         java.util.Map<String, Object> orConditions = new java.util.HashMap<>();
-        java.util.List<org.tonality.model.Subscription> entities = subscription.search(andConditions, orConditions);
+        java.util.List<org.tonality.model.Subscription> entities = subscription.search(andConditions, orConditions, "", new ArrayList<>(), "albumName", 1, 15);
         for (org.tonality.model.Subscription e : entities) {
             System.out.println(e + "\n");
         }
@@ -59,12 +194,12 @@ public class Subscription extends BaseRepository<org.tonality.model.Subscription
         // delete by entity
         entity = new org.tonality.model.Subscription();
         entity.setUserId(1);
-        entity.setAlbumId(3);
+        entity.setPremiumAlbumId(3);
         System.out.println("Successfully deleted : \n" + subscription.delete(entity));
 
         // delete by conditions
         andConditions = new java.util.HashMap<>();
-        andConditions.put("albumId", 1);
+        andConditions.put("premiumAlbumId", 1);
         System.out.println("Successfully deleted : \n" + subscription.delete(andConditions));
     }
 }
diff --git a/src/main/java/org/tonality/service/BaseWebService.java b/src/main/java/org/tonality/service/BaseWebService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0ac46692eb86a94fc352c78a56db906a3acecf08
--- /dev/null
+++ b/src/main/java/org/tonality/service/BaseWebService.java
@@ -0,0 +1,39 @@
+package org.tonality.service;
+
+import javax.annotation.Resource;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpExchange;
+
+// https://stackoverflow.com/questions/12727989/jax-ws-getting-client-ip/13693024#13693024
+public abstract class BaseWebService {
+    @Resource
+    protected javax.xml.ws.WebServiceContext context;
+
+    protected final String httpExchangeKey = "com.sun.xml.internal.ws.http.exchange";
+
+    protected String getClientIp() {
+        MessageContext messageContext = context.getMessageContext();
+        HttpExchange exchange = (HttpExchange) messageContext.get(httpExchangeKey);
+        return exchange.getRemoteAddress().getAddress().getHostAddress();
+    }
+
+    protected String getClientApiKey() {
+        MessageContext messageContext = context.getMessageContext();
+        HttpExchange exchange = (HttpExchange) messageContext.get(httpExchangeKey);
+        return exchange.getRequestHeaders().getFirst("X-API-KEY");
+    }
+
+    protected boolean isRequestValid() {
+        return getClientApiKey() != null && getClientApiKey().equals(System.getenv("API_KEY"));
+    }
+
+    protected void logRequest() throws Exception {
+        if (!isRequestValid()) throw new Exception("Invalid request");
+        // TODO : implement logging to database
+        System.out.println("Client IP: " + getClientIp());
+        System.out.println("Client API Key: " + getClientApiKey());
+    }
+}
diff --git a/src/main/java/org/tonality/service/ISubscription.java b/src/main/java/org/tonality/service/ISubscription.java
new file mode 100644
index 0000000000000000000000000000000000000000..f08e784476367ff5524bee4b7a82a765552e85b7
--- /dev/null
+++ b/src/main/java/org/tonality/service/ISubscription.java
@@ -0,0 +1,107 @@
+package org.tonality.service;
+
+import org.tonality.type.SubscriptionStatus;
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebResult;
+import javax.jws.WebService;
+import javax.xml.bind.annotation.XmlElement;
+import java.util.List;
+
+@WebService
+public interface ISubscription {
+    @WebMethod
+    @WebResult(name = "subscription")
+    org.tonality.model.Subscription createSubscription(
+            @WebParam(name = "userId")
+            long userId,
+            @WebParam(name = "username")
+            String username,
+            @WebParam(name = "premiumAlbumId")
+            long premiumAlbumId,
+            @WebParam(name = "albumName")
+            String albumName,
+            @WebParam(name = "artist")
+            String artist
+    );
+
+    @WebMethod
+    @WebResult(name = "subscription")
+    org.tonality.model.Subscription updateSubscription(
+            @WebParam(name = "userId")
+            long userId,
+            @WebParam(name = "premiumAlbumId")
+            long premiumAlbumId,
+            @WebParam(name = "status")
+            org.tonality.type.SubscriptionStatus status
+    );
+
+    @WebMethod
+    @WebResult(name = "subscription")
+    org.tonality.model.Subscription getSubscription(
+            @WebParam(name = "userId")
+            long userId,
+            @WebParam(name = "premiumAlbumId")
+            long premiumAlbumId
+    );
+
+    @WebMethod
+    @WebResult(name = "subscription")
+    List<org.tonality.model.Subscription> searchSubscription(
+            @WebParam(name = "status")
+            SubscriptionStatus status,
+            @WebParam(name = "searchInput")
+            String searchInput,
+            @WebParam(name = "orderBy")
+            String orderBy,
+            @WebParam(name = "page")
+            int page,
+            @WebParam(name = "size")
+            int size
+    );
+
+    @WebMethod
+    @WebResult(name = "subscription")
+    List<org.tonality.model.Subscription> getSubscriptionsByStatus(
+            @WebParam(name = "status")
+            SubscriptionStatus status,
+            @WebParam(name = "orderBy")
+            String orderBy,
+            @WebParam(name = "page")
+            int page,
+            @WebParam(name = "size")
+            int size
+    );
+
+    @WebMethod
+    @WebResult(name = "subscription")
+    List<org.tonality.model.Subscription> getSubscriptionsByUserId(
+            @WebParam(name = "userId")
+            long userId,
+            @WebParam(name = "page")
+            int page,
+            @WebParam(name = "size")
+            int size
+    );
+
+    @WebMethod
+    boolean deleteSubscription(
+            @WebParam(name = "userId")
+            long userId,
+            @WebParam(name = "premiumAlbumId")
+            long premiumAlbumId
+    );
+
+    @WebMethod
+    boolean deleteSubscriptionsByUserId(
+            @WebParam(name = "userId")
+            long userId
+    );
+
+    @WebMethod
+    boolean deleteSubscriptionsByAlbumId(
+            @WebParam(name = "premiumAlbumId")
+            long premiumAlbumId
+    );
+}
diff --git a/src/main/java/org/tonality/service/Subscription.java b/src/main/java/org/tonality/service/Subscription.java
new file mode 100644
index 0000000000000000000000000000000000000000..7102fe3944a96391761cc62382df5fbf8abb7021
--- /dev/null
+++ b/src/main/java/org/tonality/service/Subscription.java
@@ -0,0 +1,117 @@
+package org.tonality.service;
+
+import org.tonality.middleware.SubscriptionMiddleware;
+import org.tonality.model.SubscriptionId;
+import org.tonality.type.SubscriptionStatus;
+
+import javax.jws.WebService;
+import java.util.List;
+
+@WebService(endpointInterface = "org.tonality.service.ISubscription")
+public class Subscription extends BaseWebService implements ISubscription {
+    @Override
+    public org.tonality.model.Subscription createSubscription(long userId, String username, long premiumAlbumId, String albumName, String artist) {
+        try {
+            logRequest();
+            return org.tonality.repository.Subscription.getInstance().createSubscription(userId, username, premiumAlbumId, albumName, artist);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public org.tonality.model.Subscription updateSubscription(long userId, long premiumAlbumId, SubscriptionStatus status) {
+        try {
+            logRequest();
+            return org.tonality.repository.Subscription.getInstance().updateSubscription(userId, premiumAlbumId, status);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public org.tonality.model.Subscription getSubscription(long userId, long premiumAlbumId) {
+        try {
+            logRequest();
+            SubscriptionMiddleware subscriptionMiddleware = new SubscriptionMiddleware();
+            return subscriptionMiddleware.execute(org.tonality.repository.Subscription.getInstance().getById(new SubscriptionId(userId, premiumAlbumId)));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public List<org.tonality.model.Subscription> searchSubscription(SubscriptionStatus status, String searchInput, String orderBy, int page, int size) {
+        try {
+            logRequest();
+            SubscriptionMiddleware subscriptionMiddleware = new SubscriptionMiddleware();
+            return subscriptionMiddleware.execute(org.tonality.repository.Subscription.getInstance().searchSubscriptions(status, searchInput, orderBy, page, size));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public List<org.tonality.model.Subscription> getSubscriptionsByStatus(SubscriptionStatus status, String orderBy, int page, int size) {
+        try {
+            logRequest();
+            SubscriptionMiddleware subscriptionMiddleware = new SubscriptionMiddleware();
+            return subscriptionMiddleware.execute(org.tonality.repository.Subscription.getInstance().getSubscriptionByStatus(status, orderBy, page, size));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public List<org.tonality.model.Subscription> getSubscriptionsByUserId(long userId, int page, int size) {
+        try {
+            logRequest();
+            SubscriptionMiddleware subscriptionMiddleware = new SubscriptionMiddleware();
+            return subscriptionMiddleware.execute(org.tonality.repository.Subscription.getInstance().getSubscriptionsByUserId(userId, page, size));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public boolean deleteSubscription(long userId, long premiumAlbumId) {
+        try {
+            logRequest();
+            if (!org.tonality.repository.Subscription.getInstance().deleteById(new org.tonality.model.SubscriptionId(userId, premiumAlbumId))) {
+                throw new Exception("Failed to delete subscription");
+            }
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    @Override
+    public boolean deleteSubscriptionsByUserId(long userId) {
+        try {
+            logRequest();
+            return org.tonality.repository.Subscription.getInstance().deleteSubscriptionsByUserId(userId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    @Override
+    public boolean deleteSubscriptionsByAlbumId(long premiumAlbumId) {
+        try {
+            logRequest();
+            return org.tonality.repository.Subscription.getInstance().deleteSubscriptionsByAlbumId(premiumAlbumId);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+}
diff --git a/src/main/java/org/tonality/ws/ISubscription.java b/src/main/java/org/tonality/ws/ISubscription.java
deleted file mode 100644
index e3fc4daf8b3c2725b89afaf65648d23f5bec4505..0000000000000000000000000000000000000000
--- a/src/main/java/org/tonality/ws/ISubscription.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.tonality.ws;
-
-import org.tonality.type.SubscriptionStatus;
-
-import javax.jws.WebMethod;
-import javax.jws.WebParam;
-import javax.jws.WebResult;
-import javax.jws.WebService;
-import java.util.List;
-
-@WebService
-public interface ISubscription {
-    @WebMethod
-    @WebResult(name = "subscription")
-    org.tonality.model.Subscription createSubscription(
-            @WebParam(name = "userId")
-            long userId,
-            @WebParam(name = "albumId")
-            long albumId
-    );
-
-    @WebMethod
-    @WebResult(name = "subscription")
-    org.tonality.model.Subscription updateSubscription(
-            @WebParam(name = "userId")
-            long userId,
-            @WebParam(name = "albumId")
-            long albumId,
-            @WebParam(name = "status")
-            org.tonality.type.SubscriptionStatus status
-    );
-
-    @WebMethod
-    @WebResult(name = "subscription")
-    org.tonality.model.Subscription getSubscription(
-            @WebParam(name = "userId")
-            long userId,
-            @WebParam(name = "albumId")
-            long albumId
-    );
-
-    @WebMethod
-    @WebResult(name = "subscriptions")
-    List<org.tonality.model.Subscription> getSubscriptionsByStatus(
-            @WebParam(name = "status")
-            SubscriptionStatus status
-    );
-
-    @WebMethod
-    @WebResult(name = "subscriptions")
-    List<org.tonality.model.Subscription> getSubscriptionsByUserId(
-            @WebParam(name = "userId")
-            long userId
-    );
-
-    @WebMethod
-    boolean deleteSubscription(
-            @WebParam(name = "userId")
-            long userId,
-            @WebParam(name = "albumId")
-            long albumId
-    );
-
-    @WebMethod
-    boolean deleteSubscriptionsByUserId(
-            @WebParam(name = "userId")
-            long userId
-    );
-
-    @WebMethod
-    boolean deleteSubscriptionsByAlbumId(
-            @WebParam(name = "albumId")
-            long albumId
-    );
-}
diff --git a/src/main/java/org/tonality/ws/Subscription.java b/src/main/java/org/tonality/ws/Subscription.java
deleted file mode 100644
index bd31846ea66c01c71e0322429abbf984602b0dba..0000000000000000000000000000000000000000
--- a/src/main/java/org/tonality/ws/Subscription.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.tonality.ws;
-
-import org.tonality.type.SubscriptionStatus;
-
-import javax.jws.WebService;
-import java.util.List;
-
-@WebService(endpointInterface = "org.tonality.ws.ISubscription")
-public class Subscription implements ISubscription {
-    @Override
-    public org.tonality.model.Subscription createSubscription(long userId, long albumId) {
-        try {
-            org.tonality.model.Subscription subscription = new org.tonality.model.Subscription();
-            subscription.setUserId(userId);
-            subscription.setAlbumId(albumId);
-            if (org.tonality.repository.Subscription.getInstance().add(subscription) == null) {
-                throw new Exception("Failed to create subscription");
-            }
-            return subscription;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    @Override
-    public org.tonality.model.Subscription updateSubscription(long userId, long albumId, SubscriptionStatus status) {
-        try {
-            org.tonality.model.Subscription subscription = new org.tonality.model.Subscription();
-            subscription.setUserId(userId);
-            subscription.setAlbumId(albumId);
-            subscription.setStatus(status);
-            if (org.tonality.repository.Subscription.getInstance().update(subscription) == null) {
-                throw new Exception("Failed to update subscription");
-            }
-            return subscription;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    @Override
-    public org.tonality.model.Subscription getSubscription(long userId, long albumId) {
-        try {
-            org.tonality.model.SubscriptionId id = new org.tonality.model.SubscriptionId(userId, albumId);
-            return org.tonality.repository.Subscription.getInstance().getById(id);
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    @Override
-    public List<org.tonality.model.Subscription> getSubscriptionsByStatus(SubscriptionStatus status) {
-        try {
-            java.util.Map<String, Object> andConditions = new java.util.HashMap<>();
-            andConditions.put("status", status.toString());
-            java.util.Map<String, Object> orConditions = new java.util.HashMap<>();
-            return org.tonality.repository.Subscription.getInstance().search(andConditions, orConditions);
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    @Override
-    public List<org.tonality.model.Subscription> getSubscriptionsByUserId(long userId) {
-        try {
-            java.util.Map<String, Object> andConditions = new java.util.HashMap<>();
-            andConditions.put("userId", userId);
-            java.util.Map<String, Object> orConditions = new java.util.HashMap<>();
-            return org.tonality.repository.Subscription.getInstance().search(andConditions, orConditions);
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    @Override
-    public boolean deleteSubscription(long userId, long albumId) {
-        try {
-            org.tonality.model.SubscriptionId id = new org.tonality.model.SubscriptionId(userId, albumId);
-            if (!org.tonality.repository.Subscription.getInstance().deleteById(id)) {
-                throw new Exception("Failed to delete subscription");
-            }
-            return true;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-    }
-
-    @Override
-    public boolean deleteSubscriptionsByUserId(long userId) {
-        try {
-            java.util.Map<String, Object> conditions = new java.util.HashMap<>();
-            conditions.put("userId", userId);
-            if (!org.tonality.repository.Subscription.getInstance().delete(conditions)) {
-                throw new Exception("Failed to delete subscriptions");
-            }
-            return true;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-    }
-
-    @Override
-    public boolean deleteSubscriptionsByAlbumId(long albumId) {
-        try {
-            java.util.Map<String, Object> conditions = new java.util.HashMap<>();
-            conditions.put("albumId", albumId);
-            if (!org.tonality.repository.Subscription.getInstance().delete(conditions)) {
-                throw new Exception("Failed to delete subscriptions");
-            }
-            return true;
-        } catch (Exception e) {
-            e.printStackTrace();
-            return false;
-        }
-    }
-}
diff --git a/src/main/resources/hibernate.cfg.xml b/src/main/resources/hibernate.cfg.xml
index 33e84f12feb368c1b87a0fb6f49165def29fd9aa..1af8bee269c849e7002cd39f2ec3e8dd7ef245f9 100644
--- a/src/main/resources/hibernate.cfg.xml
+++ b/src/main/resources/hibernate.cfg.xml
@@ -6,7 +6,7 @@
     <session-factory>
 
         <property name="hibernate.hbm2ddl.auto">update</property>
-        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
+        <property name="dialect">org.hibernate.dialect.MySQL8Dialect</property>
         <property name="hibernate.connection.autocommit">false</property>
         <property name="hibernate.show_sql">true</property>
         <property name="hibernate.format_sql">true</property>