مكتبة العملاء التي توفر WAMP على Java 8 (Netty) وAndroid، بالإضافة إلى WebSocket (الآمن) لنظام Android.
Autobahn|Java هو مشروع فرعي لمشروع Autobahn ويوفر تطبيقات عميل مفتوحة المصدر لـ
يعمل على Android وNetty/Java8/JVM.
تستخدم طبقة WebSocket واجهة برمجة تطبيقات المستخدم القائمة على رد الاتصال، وهي مكتوبة خصيصًا لنظام Android. على سبيل المثال، لا يقوم بتشغيل أي عناصر شبكة على مؤشر ترابط (UI) الرئيسي.
تستخدم طبقة WAMP Java 8 CompletableFuture لإجراءات WAMP (الاتصال والتسجيل والنشر والاشتراك) ونمط المراقب لجلسة WAMP وأحداث دورة حياة الاشتراك والتسجيل.
المكتبة مرخصة من معهد ماساتشوستس للتكنولوجيا، ويتم صيانتها بواسطة مشروع Crossbar.io، وتم اختبارها باستخدام AutobahnTestsuite ونشرها كـ JAR إلى Maven وكصورة سلسلة أدوات Docker إلى Dockerhub.
الاستيلاء عبر مافن:
< dependency >
< groupId >io.crossbar.autobahn</ groupId >
< artifactId >autobahn-android</ artifactId >
< version >21.7.1</ version >
</ dependency >
غرادل:
dependencies {
implementation ' io.crossbar.autobahn:autobahn-android:21.7.1 '
}
بالنسبة للأنظمة التي لا تعمل بنظام Android، استخدم artifactID autobahn-java
أو قم فقط بتنزيل أحدث إصدار من JAR
من السهل تشغيل العملاء التجريبيين، ما عليك سوى تثبيت make
وأداة docker
لبدء الأمور.
$ make crossbar # Starts crossbar in a docker container
$ make python # Starts a python based WAMP components that provides calls for the Java demo client
وأخيرا
$ make java # Starts the java (Netty) based demo client that performs WAMP actions
يحتوي الكود الموجود في المعرض التجريبي على بعض الأمثلة حول كيفية استخدام مكتبة Autobahn، ويحتوي أيضًا على طرق ملائمة للاستخدام. فيما يلي مجموعة أساسية من أمثلة التعليمات البرمجية التي تعرض جميع إجراءات WAMP الأربعة.
public void demonstrateSubscribe ( Session session , SessionDetails details ) {
// Subscribe to topic to receive its events.
CompletableFuture < Subscription > subFuture = session . subscribe ( "com.myapp.hello" ,
this :: onEvent );
subFuture . whenComplete (( subscription , throwable ) -> {
if ( throwable == null ) {
// We have successfully subscribed.
System . out . println ( "Subscribed to topic " + subscription . topic );
} else {
// Something went bad.
throwable . printStackTrace ();
}
});
}
private void onEvent ( List < Object > args , Map < String , Object > kwargs , EventDetails details ) {
System . out . println ( String . format ( "Got event: %s" , args . get ( 0 )));
}
نظرًا لأننا لا نصل إلا إلى args
في onEvent()، فيمكننا تبسيطها مثل:
private void onEvent ( List < Object > args ) {
System . out . println ( String . format ( "Got event: %s" , args . get ( 0 )));
}
public void demonstratePublish ( Session session , SessionDetails details ) {
// Publish to a topic that takes a single arguments
List < Object > args = Arrays . asList ( "Hello World!" , 900 , "UNIQUE" );
CompletableFuture < Publication > pubFuture = session . publish ( "com.myapp.hello" , args );
pubFuture . thenAccept ( publication -> System . out . println ( "Published successfully" ));
// Shows we can separate out exception handling
pubFuture . exceptionally ( throwable -> {
throwable . printStackTrace ();
return null ;
});
}
ستبدو المكالمة الأبسط كما يلي:
public void demonstratePublish ( Session session , SessionDetails details ) {
CompletableFuture < Publication > pubFuture = session . publish ( "com.myapp.hello" , "Hi!" );
...
}
public void demonstrateRegister ( Session session , SessionDetails details ) {
// Register a procedure.
CompletableFuture < Registration > regFuture = session . register ( "com.myapp.add2" , this :: add2 );
regFuture . thenAccept ( registration ->
System . out . println ( "Successfully registered procedure: " + registration . procedure ));
}
private CompletableFuture < InvocationResult > add2 (
List < Object > args , Map < String , Object > kwargs , InvocationDetails details ) {
int res = ( int ) args . get ( 0 ) + ( int ) args . get ( 1 );
List < Object > arr = new ArrayList <>();
arr . add ( res );
return CompletableFuture . completedFuture ( new InvocationResult ( arr ));
}
قد يبدو add2
الدقيق للغاية كما يلي:
private List < Object > add2 ( List < Integer > args , InvocationDetails details ) {
int res = args . get ( 0 ) + args . get ( 1 );
return Arrays . asList ( res , details . session . getID (), "Java" );
}
public void demonstrateCall ( Session session , SessionDetails details ) {
// Call a remote procedure.
CompletableFuture < CallResult > callFuture = session . call ( "com.myapp.add2" , 10 , 20 );
callFuture . thenAccept ( callResult ->
System . out . println ( String . format ( "Call result: %s" , callResult . results . get ( 0 ))));
}
إجراء الاتصال مع معلمات نوع البيانات المتغيرة
public void demonstrateCall ( Session session , SessionDetails details ) {
// Call a remote procedure.
byte [] var1 = new byte [ 20 ];
String var2 = "A sample text" ;
int var3 = 99 ;
List < Object > args = new ArrayList <>();
args . add ( var1 );
args . add ( var2 );
args . add ( var3 );
CompletableFuture < CallResult > callFuture = session . call ( "com.myapp.myproc" , args );
callFuture . thenAccept ( callResult ->
System . out . println ( String . format ( "Call result: %s" , callResult . results . get ( 0 ))));
}
public void main () {
// Create a session object
Session session = new Session ();
// Add all onJoin listeners
session . addOnJoinListener ( this :: demonstrateSubscribe );
session . addOnJoinListener ( this :: demonstratePublish );
session . addOnJoinListener ( this :: demonstrateCall );
session . addOnJoinListener ( this :: demonstrateRegister );
// finally, provide everything to a Client and connect
Client client = new Client ( session , url , realm );
CompletableFuture < ExitInfo > exitInfoCompletableFuture = client . connect ();
}
المصادقة بسيطة، نحتاج فقط إلى إنشاء كائن للمصادق المطلوب وتمريره إلى العميل
public void main () {
...
IAuthenticator authenticator = new TicketAuth ( authid , ticket );
Client client = new Client ( session , url , realm , authenticator );
CompletableFuture < ExitInfo > exitInfoCompletableFuture = client . connect ();
}
public void main () {
...
IAuthenticator authenticator = new ChallengeResponseAuth ( authid , secret );
Client client = new Client ( session , url , realm , authenticator );
CompletableFuture < ExitInfo > exitInfoCompletableFuture = client . connect ();
}
public void main () {
...
IAuthenticator authenticator = new CryptosignAuth ( authid , privkey , pubkey );
Client client = new Client ( session , url , realm , authenticator );
CompletableFuture < ExitInfo > exitInfoCompletableFuture = client . connect ();
}
يمكنك أيضًا تقديم قائمة بالمصادقات
public void main () {
...
List < IAuthenticator > authenticators = new ArrayList <>();
authenticators . add ( new TicketAuth ( authid , ticket ));
authenticators . add ( new CryptosignAuth ( authid , privkey , pubkey ));
Client client = new Client ( session , url , realm , authenticators );
CompletableFuture < ExitInfo > exitInfoCompletableFuture = client . connect ();
}
يدعم Autobahn أيضًا POJOs
فيما يلي كيفية استدعاء إجراء بعيد يقوم بإرجاع قائمة الأشخاص POJOs
// Call a remote procedure that returns a Person with id 1
CompletableFuture < Person > callFuture = mSession . call ( "com.example.get_person" , 1 );
callFuture . whenCompleteAsync (( person , throwable ) -> {
if ( throwable != null ) {
// handle error
} else {
// success!
// do something with person
}
}, mExecutor );
// call a remote procedure that returns a List<Person>
CompletableFuture < List < Person >> callFuture = mSession . call (
// remote procedure to call
"com.example.get_persons_by_department" ,
// positional call arguments
new ArrayList < Object >() { List . of ( "department-7" )},
// call return type
new TypeReference < List < Person >>() {}
);
callFuture . whenCompleteAsync (( persons , throwable ) -> {
if ( throwable != null ) {
// handle error
} else {
// success!
for ( Person person : persons ) {
// do something with person
}
}
}, mExecutor );
قم أيضًا بتسجيل الإجراء الذي يُرجع شخصًا
private Person get_person () {
return new Person ( "john" , "doe" , "hr" );
}
private void main () {
CompletableFuture < Registration > regFuture = session . register (
"io.crossbar.example.get_person" , this :: get_person );
regFuture . whenComplete (( registration , throwable ) -> {
System . out . println ( String . format (
"Registered procedure %s" , registration . procedure ));
});
}
مثال الصدى
WebSocketConnection connection = new WebSocketConnection ();
connection . connect ( "wss://echo.websocket.org" , new WebSocketConnectionHandler () {
@ Override
public void onConnect ( ConnectionResponse response ) {
System . out . println ( "Connected to server" );
}
@ Override
public void onOpen () {
connection . sendMessage ( "Echo with Autobahn" );
}
@ Override
public void onClose ( int code , String reason ) {
System . out . println ( "Connection closed" );
}
@ Override
public void onMessage ( String payload ) {
System . out . println ( "Received message: " + payload );
connection . sendMessage ( payload );
}
});
بناء الطريق السريع بسيط جدًا
بالنسبة لنظام التشغيل Android، نوصي باستخدام Android Studio. ما عليك سوى استيراد المشروع في Android Studio، وسيخبرك إذا كان هناك أي تبعيات مفقودة، ثم قم بتثبيتها ثم قم ببناء المشروع من Build > Rebuild Project
وسيكون لديك قطعة أثرية aar في autobahn/build/outputs/aar/
لإنتاج إصدار لأنظمة غير Android، تأكد من أن لديك عامل إرساء وقم بتثبيته ثم استخدم الأمر run below في الدليل الجذر للمشروع
make build_autobahn
سيؤدي ذلك إلى إخراج ملف الجرة في autobahn/build/libs/
.
تواصل معنا من خلال الانضمام إلى منتدانا.
الإصدار 1 من هذه المكتبة لا يزال في الريبو هنا، ولكن لم تعد تتم صيانته.
الإصدار 1 يدعم فقط WebSocket غير الآمن على Android ويدعم WAMP v1 فقط.
تم إصلاح هاتين المشكلتين في الإصدار (الحالي) من Autobahn|Java.