Java 8(Netty) 및 Android에서 WAMP와 Android용 (보안) WebSocket을 제공하는 클라이언트 라이브러리입니다.
Autobahn|Java는 Autobahn 프로젝트의 하위 프로젝트이며 다음을 위한 오픈 소스 클라이언트 구현을 제공합니다.
Android 및 Netty/Java8/JVM에서 실행됩니다.
WebSocket 레이어는 콜백 기반 사용자 API를 사용하며 Android용으로 특별히 작성되었습니다. 예를 들어 메인(UI) 스레드에서는 어떤 네트워크 작업도 실행하지 않습니다.
WAMP 계층은 WAMP 작업(호출, 등록, 게시 및 구독)에 Java 8 CompletableFuture를 사용하고 WAMP 세션, 구독 및 등록 수명 주기 이벤트에 Observer 패턴을 사용합니다.
이 라이브러리는 MIT 라이센스를 받았으며 Crossbar.io 프로젝트에서 유지 관리하고 AutobahnTestsuite를 사용하여 테스트되었으며 Maven에는 JAR로, Dockerhub에는 Docker 도구 체인 이미지로 게시되었습니다.
Maven을 통해 가져오기:
< 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
데모 갤러리의 코드에는 아우토반 라이브러리를 사용하는 방법에 대한 몇 가지 예가 포함되어 있으며 사용하기 편리한 방법도 포함되어 있습니다. 다음은 4가지 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 )));
}
onEvent()의 args
에만 액세스하므로 다음과 같이 단순화할 수 있습니다.
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 ();
}
아우토반은 POJO도 지원합니다.
Person POJO 목록을 반환하는 원격 프로시저를 호출하는 방법은 다음과 같습니다.
// 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 );
Person을 반환하는 프로시저도 등록하세요.
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
에서 프로젝트를 빌드하면 autobahn/build/outputs/aar/
에 aar 아티팩트가 있습니다.
Android가 아닌 시스템용 빌드를 생성하려면 docker가 있고 설치되어 있는지 확인한 다음 프로젝트의 루트 디렉터리에서 아래 명령을 실행하면 됩니다.
make build_autobahn
그러면 autobahn/build/libs/
에 jar 파일이 출력됩니다.
포럼에 가입하여 연락하세요.
이 라이브러리의 버전 1은 여전히 여기 저장소에 있지만 더 이상 유지 관리되지 않습니다.
버전 1은 Android에서 비보안 WebSocket과 WAMP v1만 지원했습니다.
이 두 가지 문제는 모두 Autobahn|Java의 (현재) 버전에서 수정되었습니다.