Menu

Liferay 7.x: Hiểu về Service Tracker

Như chúng ta đã biết, Liferay DXP sử dụng framework OSGi cho môi trường cộng tác giữa các đối tượng (các đối tượng ngày được xem như các services). Khai báo các dịch vụ (Declarative Services (DS) - khái niệm quan trọng của OSGi) là cách để chia sẻ các service giữa các thành phần trong hệ thống. Khi chúng ta khai báo một lớp của Java với annotation @Component thì lớp đó được xem như là một service và sẽ được sử dụng bởi các thành phần khác. Việc sử dụng annotation @Component để biến một lớp của Java thành một service thực sự dễ cài đặt và mở rộng.

Service Tracker

Để sử dụng một service khác thực sự đơn giản, chỉ cần dùng annotation @Reference để gọi đến service mong muốn. Như vậy, service/lớp hiện tại sẽ phụ thuộc vào các service/lớp mà nó tham chiếu. Khi tất cả các service/lớp được deploy thì trạng thái của service/lớp hiện tại là active (sẵn sàng sử dụng). Nhưng đối với các lớp không có khai báo annotation @Component thì chúng ta không thể gọi đến các service/lớp tham chiếu và annotation @Reference sẽ bị bỏ qua.

Một điều quan trọng nữa là việc sử dụng các lớp tĩnh trong môi trường runtime OSGi là không nên và nó có thể gây ra các lỗi không thể phục hồi vì rất khó để dừng hoặc gỡ các service được gọi bởi các lớp tĩnh.

Việc sử dụng annotation như trên là không khả thi. Do đó, service-tracker được sinh ra để theo dõi rất cả các service trong hệ thống. Nó được sử dụng để theo dõi việc thêm, sửa hoặc xoá các service và rất nhiều các thao tác điều khiển khác nữa.

Hãy lấy một ví dụ đơn giản được sử dụng trong Liferay 7.x service builder (các lớp XxxLocalServiceUtil).

public static DealLocalService getService() {
return _serviceTracker.getService();
}

private static ServiceTracker<DealLocalService, DealLocalService> _serviceTracker
= ServiceTrackerFactory.open(DealLocalService.class);

Đối với các lớp khác muốn khai báo service-tracker

Bundle bundle = FrameworkUtil.getBundle(this.getClass());

BundleContext bundleContext = bundle.getBundleContext();

ServiceTracker<DealLocalService, DealLocalService> serviceTracker
= new ServiceTracker(bundleContext, DealLocalService.class, null);

serviceTracker.open();

return serviceTracker.getService();

Sau khi khai báo service-tracker, nó cần được khởi tạo trước khi sử dụng. Và cuối cùng, khi gỡ ứng dụng, service-tracker sẽ gọi phương thức close() để kết thúc.

Khi sử dụng Service Tracker để theo dõi trạng thái của service. Nếu phương thực getService() trả về null nghĩa là service chưa được deploy. Nếu thấy nhiều instance thì có thể sử dụng một trong số chúng.

Tuỳ biến theo dõi service

Chúng ta có thể sử dụng ServiceTrackerCustomizer cho nhiều mục đích. Ví dụ: Xem danh sách các service đang hoạt động chẳng hạn. Nhưng ở đây, chúng ta sẽ làm những cái cụ thể hơn. Các service trong OSGi có thể khác nhau, nhưng chúng có điều giống là đều sử dụng annotation @Component. Bởi vậy, chúng ta có thể dùng ServiceTrackerCustomizer để lấy được những chi tiết của service.

Để sử dụng ServiceTrackerCustomizer, chúng ta cần tạo ra một lớp mới và ghi đè các phương thức đã có: addingService, modifiedService và removedService. Để xoá các tài nguyên khi service được gỡ bỏ, phương thức removedService cần được sử dụng sau khi service được xoá bỏ khỏi bộ nhớ của OSGi.

public class DealServiceTrackerCustomizer
implements ServiceTrackerCustomizer<DealLocalService, DealLocalService>{
private final BundleContext bundleContext;
DealServiceTrackerCustomizer(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}

@Override
public DealLocalService addingService(
ServiceReference<DealLocalService> reference) {

String dealType = (String) reference.getProperty("deal-type");

DealLocalService service = bundleContext.getService(reference);
if(dealType.equals(DEAL_TYPE_ONLINE)){
return service;
}else{
return null;
}
}

@Override
public void modifiedService(
ServiceReference<DealLocalService> reference, DealLocalService service) {
//This method is called
//when a service has had it properties modified

}

@Override
public void removedService(
ServiceReference<DealLocalService> reference, DealLocalService service) {
//This method is called after
//a service is no longer being tracked
//code related to clean up related resources can be added here
}
}

Và cuối cùng, chúng ta chỉ sử dụng lớp ServiceTrackerCustomizer thay vì ServiceTracker như đoạn code dưới đây:

ServiceTracker<DealLocalService, DealLocalService> serviceTracker =
new ServiceTracker(
bundleContext, DealLocalService.class,
new DealServiceTrackerCustomizer(bundleContext));

Bạn có thể xem bài viết gốc tại đây.

Không có nhận xét nào:

Đăng nhận xét