{"id":1833,"date":"2014-12-16T17:38:22","date_gmt":"2014-12-16T17:38:21","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1833"},"modified":"2014-12-16T17:38:22","modified_gmt":"2014-12-16T17:38:21","slug":"why-couchbase-chose-rxjava-new-java-sdk","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/es\/why-couchbase-chose-rxjava-new-java-sdk\/","title":{"rendered":"Por qu\u00e9 Couchbase eligi\u00f3 RxJava para el nuevo SDK de Java"},"content":{"rendered":"<p>Esta entrada de blog explica nuestro razonamiento y motivaci\u00f3n para elegir RxJava como uno de los componentes integrales de nuestro nuevo Java SDK.<\/p>\n<h2>Motivaci\u00f3n<\/h2>\n<p>Hay muchas formas de dise\u00f1ar una API y cada una tiene sus ventajas (y sus inconvenientes). En el proceso de dise\u00f1o de nuestras flamantes API, una de las principales cuestiones era c\u00f3mo exponerlas al usuario.\u00a0<\/p>\n<p>Una pregunta que no tuvimos que hacernos fue: \u00bfdeber\u00eda ser s\u00edncrona o as\u00edncrona? Creemos firmemente que las API as\u00edncronas son la \u00fanica forma sensata de obtener el rendimiento y la escalabilidad que a menudo se necesitan, y adem\u00e1s es mucho m\u00e1s f\u00e1cil pasar de as\u00edncrono a s\u00edncrono que al rev\u00e9s. El SDK estable actual (1.4.3 en el momento de escribir esto) ya hace un uso intensivo de Futures de varias formas para proporcionar respuestas as\u00edncronas, y esto se remonta a 2006\/7, cuando spymemcached introdujo originalmente el concepto en su API.<\/p>\n<p>Es bien sabido que la interfaz Java Future es muy limitada en comparaci\u00f3n con otras soluciones (como los futuros de Scala). Adem\u00e1s, tambi\u00e9n es un poco m\u00e1s complicado de programar si necesitas construir flujos de datos as\u00edncronos en los que un c\u00e1lculo depende del otro y quieres que todo sea as\u00edncrono. En versiones recientes hemos a\u00f1adido soporte para listeners, que mejoran bastante la situaci\u00f3n pero siguen sin ser una soluci\u00f3n ideal.<\/p>\n<p>En los \u00faltimos a\u00f1os han surgido otras bibliotecas y patrones que hemos seguido de cerca. Uno de los conceptos maduros es el conocido como Extensiones Reactivas, originado en Microsoft y .NET. Se basa en la idea de que las aplicaciones deben estar orientadas a eventos y reaccionar a ellos de forma as\u00edncrona. Define un conjunto muy rico de operadores sobre lo que se puede hacer con los datos (modificarlos, combinarlos, filtrarlos, etc.). Recientemente, Netflix lo ha portado a Java y lo ha bautizado como RxJava (hay que tener en cuenta que, aunque el proyecto se encuentra actualmente en el espacio de nombres de Netflix, se trasladar\u00e1 a \"io.reactivex\" m\u00e1s pronto que tarde). Es muy estable y tambi\u00e9n proporciona adaptadores para otros lenguajes JVM como Scala, Groovy y JRuby que juega bien con nuestros planes para ampliar el apoyo tambi\u00e9n.<\/p>\n<h2>El concepto<\/h2>\n<p>La idea principal de Rx gira en torno a los Observables y sus observadores. Si no te has topado con este concepto, puedes pensar en el Observable como el primo as\u00edncrono y basado en push (o m\u00e1s formalmente llamado dual) de un Iterable. M\u00e1s espec\u00edficamente, esta es su relaci\u00f3n:<\/p>\n<table border=\"1\" cellpadding=\"1\" cellspacing=\"1\" style=\"width:500px\">\n<thead>\n<tr>\n<th scope=\"col\">Evento<\/th>\n<th scope=\"col\">Iterable (tirar)<\/th>\n<th scope=\"col\">Observable (push)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>recuperar datos<\/td>\n<td>T siguiente()<\/td>\n<td>onNext(T)<\/td>\n<\/tr>\n<tr>\n<td>descubrir error<\/td>\n<td>lanza una excepci\u00f3n<\/td>\n<td>onError(Excepci\u00f3n)<\/td>\n<\/tr>\n<tr>\n<td>completa<\/td>\n<td>devuelve<\/td>\n<td>onCompleted()<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Cada vez que se introducen datos en un observable, todos los observables suscritos a \u00e9l reciben los datos en su m\u00e9todo onNext(). Si el observable se completa eventualmente (que no tiene por qu\u00e9 ser siempre el caso). se llama al m\u00e9todo onCompleted. Ahora bien, en cualquier punto del proceso, si se produce un error se llama al m\u00e9todo onError y el observable tambi\u00e9n se considera completado.<\/p>\n<p>Si te gusta la gram\u00e1tica, el contrato tiene este aspecto:\u00a0<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">OnNext* (OnCompleted | OnError)?<\/div>\n<\/div>\n<p>Espec\u00edficamente note que no hay distinci\u00f3n si solo 1 o N datos son retornados, esto puede ser normalmente inferido de los m\u00e9todos que usted llama y como est\u00e1 documentado. De todas formas no cambia tu flujo de programaci\u00f3n. Como esto es un poco abstracto, veamos un ejemplo concreto. En la clase CouchbaseCluster, hay un m\u00e9todo llamado openBucket que inicializa todos los recursos necesarios y luego devuelve una instancia de Bucket para que trabajes con ella. Ahora puedes imaginar que abrir sockets, coger una configuraci\u00f3n y dem\u00e1s lleva algo de tiempo, as\u00ed que este es un candidato perfecto. La API de bloqueo se ver\u00eda as\u00ed:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">interfaz Cluster {<br \/>\u00a0 \u00a0 \u00a0 \u00a0 Bucket openBucket(String name, String password);<br \/>}<\/div>\n<\/div>\n<p>\u00bfC\u00f3mo podemos hacerlo as\u00edncrono? Tenemos que envolverlo en un Observable:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">interfaz Cluster {<br \/>\u00a0 \u00a0 \u00a0 \u00a0 Observable<bucket> openBucket(String nombre, String contrase\u00f1a);<br \/>}<\/div>\n<\/div>\n<p>As\u00ed que ahora devolvemos un observable que eventualmente retornar\u00e1 con una instancia de cubo que podemos usar. Vamos a a\u00f1adir un observador:<\/p>\n<div class=\"geshifilter\">\n<div class=\"java geshifilter-java\" style=\"font-family:monospace;\">racimo.<span style=\"color: #006633;\">openBucket<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">suscr\u00edbase a<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Observador<span style=\"color: #339933;\"><<\/span>Cubo<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> onCompleted<span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Asystem+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Sistema<\/span><\/a>.<span style=\"color: #006633;\">fuera<\/span>.<span style=\"color: #006633;\">println<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"\u00a1Observable hecho!\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><\/p>\n<p>\u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> onError<span style=\"color: #009900;\">(<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Athrowable+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Throwable<\/span><\/a> e<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Asystem+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Sistema<\/span><\/a>.<span style=\"color: #006633;\">err<\/span>.<span style=\"color: #006633;\">println<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"Algo pas\u00f3\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 e.<span style=\"color: #006633;\">printStackTrace<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><\/p>\n<p>\u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> onNext<span style=\"color: #009900;\">(<\/span>Cubo cubo<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Asystem+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Sistema<\/span><\/a>.<span style=\"color: #006633;\">fuera<\/span>.<span style=\"color: #006633;\">println<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"Cubo recibido: \"<\/span> <span style=\"color: #339933;\">+<\/span> cubo<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/><span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><\/div>\n<\/div>\n<p>Ten en cuenta que estos m\u00e9todos son llamados en un hilo diferente, as\u00ed que si dejas el c\u00f3digo as\u00ed y sales de tu hilo principal despu\u00e9s, probablemente no ver\u00e1s nada. Aunque ahora podr\u00edas escribir todo el resto de tu c\u00f3digo en el m\u00e9todo onNext, probablemente no sea la mejor forma de hacerlo. Dado que el cubo es algo\u00a0<br \/>que quieras abrir por adelantado, podr\u00edas bloquearlo y luego proceder con el resto de tu c\u00f3digo. Cada Observable se puede convertir en un observable de bloqueo, que se siente como un Iterable:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">BlockingObservable<bucket> blockingObservable = cluster.openBucket().toBlocking();<\/div>\n<\/div>\n<p>Encontrar\u00e1s muchos m\u00e9todos para iterar sobre los thata recibidos de forma bloqueante, pero tambi\u00e9n hay m\u00e9todos abreviados si s\u00f3lo esperas un \u00fanico valor (que sabemos que es nuestro caso):<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">Bucket bucket = cluster.openBucket().toBlocking().single();<\/div>\n<\/div>\n<p>Lo que ocurre aqu\u00ed internamente es que el valor llamado en onNext se almacena para nosotros y se devuelve una vez que se llama a onComplete. si se llama a onError, el throwable se lanza directamente y se puede atrapar.<\/p>\n<h2>API unificadoras<\/h2>\n<p>Lo que has visto apenas roza la superficie. La apertura del cubo tambi\u00e9n podr\u00eda realizarse con un Future<bucket> solo. Donde los Observables brillan es cuando se necesita trabajar con m\u00e1s de un resultado devuelto. En este caso, un Future<t> ya no encaja y Future&lt;Colecci\u00f3n&lt;T&gt;&gt; o algo similar no tiene el mismo contrato. Dado que los Observables implican que se puede devolver m\u00e1s de un T, las APIs pueden tener el mismo aspecto aunque a veces se devuelva uno y a veces m\u00e1s de un Ts.<\/p>\n<p>De nuevo, veamos un ejemplo concreto. El SDK expone un m\u00e9todo get que devuelve un documento. Su aspecto es el siguiente:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">interfaz Cubo {<br \/>\u00a0 \u00a0 \u00a0 \u00a0 Observable<jsondocument> get(String id);<br \/>}<\/div>\n<\/div>\n<p>Pero tambi\u00e9n soportamos consultas (Views, N1QL) que potencialmente devuelven m\u00e1s de un resultado (o incluso ninguno). Gracias al contrato Observable, podemos construir una API como esta:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">interfaz Cubo {<br \/>\u00a0 \u00a0 \u00a0 \u00a0 Observable<viewresult> query(ViewQuery query);<br \/>}<\/div>\n<\/div>\n<p>\u00bfLo ves? El contrato dice impl\u00edcitamente \"si pasas una consulta, obtendr\u00e1s N ViewResults de vuelta\", ya que sabes c\u00f3mo tiene que comportarse un Observable. Y para tener una visi\u00f3n m\u00e1s amplia, aqu\u00ed hay a\u00fan m\u00e1s m\u00e9todos que intuitivamente se comportan de la manera que esperas que lo hagan.<\/p>\n<div class=\"geshifilter\">\n<div class=\"java geshifilter-java\" style=\"font-family:monospace;\"><span style=\"color: #000000; font-weight: bold;\">interfaz<\/span> Cubo <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #339933;\"><<\/span>D <span style=\"color: #000000; font-weight: bold;\">extiende<\/span> Documento<span style=\"color: #339933;\">&gt;<\/span> Observable<span style=\"color: #339933\">&lt;<\/span>D<span style=\"color: #339933\">&gt;<\/span> insert<span style=\"color: #009900\">(<\/span>D document<span style=\"color: #009900\">)<\/span><span style=\"color: #339933\">;<\/span><br \/> <span style=\"color: #339933\">&lt;<\/span>D <span style=\"color: #000000;font-weight: bold\">extends<\/span> Document<span style=\"color: #339933\">&gt;<\/span> Observable<span style=\"color: #339933;\"><<\/span>D<span style=\"color: #339933;\">><\/span> upsert<span style=\"color: #009900;\">(<\/span>Documento D<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #339933;\"><<\/span>D <span style=\"color: #000000; font-weight: bold;\">extiende<\/span> Documento<span style=\"color: #339933;\"><?>><\/span> Observable<span style=\"color: #339933;\"><<\/span>D<span style=\"color: #339933;\">><\/span> sustituir<span style=\"color: #009900;\">(<\/span>Documento D<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><\/p>\n<p>\u00a0 \u00a0 Observable<span style=\"color: #339933;\"><<\/span>VerResultado<span style=\"color: #339933;\">><\/span> consulta<span style=\"color: #009900;\">(<\/span>Consulta ViewQuery<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 Observable<span style=\"color: #339933;\"><<\/span>Resultado de la consulta<span style=\"color: #339933;\">><\/span> consulta<span style=\"color: #009900;\">(<\/span>Consulta<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 Observable<span style=\"color: #339933;\"><<\/span>Resultado de la consulta<span style=\"color: #339933;\">><\/span> consulta<span style=\"color: #009900;\">(<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Astring+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Cadena<\/span><\/a> consulta<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><\/p>\n<p>\u00a0 \u00a0 Observable<span style=\"color: #339933;\"><<\/span>Booleano<span style=\"color: #339933;\">><\/span> descarga<span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/><span style=\"color: #009900;\">}<\/span><\/div>\n<\/div>\n<h2>\u00a1Async mi flujo de datos!<\/h2>\n<p>Hasta ahora hemos visto lo que los Observables pueden hacer por nosotros y c\u00f3mo nos ayudan a proporcionar APIs cohesivas, simples y a la vez as\u00edncronas. Pero los Observables realmente brillan por sus aspectos de componibilidad. Se pueden hacer muchas cosas con Observables, y no podemos cubrirlas todas en este post. RxJava tiene una muy buena documentaci\u00f3n de referencia que se puede encontrar aqu\u00ed, as\u00ed que \u00e9chale un vistazo. Utiliza diagramas de m\u00e1rmol para mostrar c\u00f3mo funcionan los flujos de datos as\u00edncronos, algo que tambi\u00e9n queremos incluir en nuestra documentaci\u00f3n en el futuro.<\/p>\n<p>Consideremos un ejemplo pr\u00e1ctico: Quieres cargar un documento desde couchbase (que es un objeto JSON completo con detalles del usuario), pero s\u00f3lo quieres hacer algo con el firstname m\u00e1s abajo en tu c\u00f3digo. Podemos utilizar la funci\u00f3n map para mapear desde el JsonDocument a la cadena firstname:<\/p>\n<div class=\"geshifilter\">\n<div class=\"java geshifilter-java\" style=\"font-family:monospace;\">cubo<br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">consiga<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"usuario::1\"<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">mapa<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Func1<span style=\"color: #339933;\"><<\/span>JsonDocument, Cadena<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Astring+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Cadena<\/span><\/a> llame a<span style=\"color: #009900;\">(<\/span>JsonDocument jsonDocument<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">devolver<\/span> jsonDocument.<span style=\"color: #006633;\">contenido<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">getString<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"nombre\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">suscr\u00edbase a<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Acci\u00f3n1<span style=\"color: #339933;\"><<\/span>Cadena<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> llame a<span style=\"color: #009900;\">(<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Astring+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Cadena<\/span><\/a> nombre<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Asystem+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Sistema<\/span><\/a>.<span style=\"color: #006633;\">fuera<\/span>.<span style=\"color: #006633;\">println<\/span><span style=\"color: #009900;\">(<\/span>nombre<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><\/div>\n<\/div>\n<p>Hay dos aspectos importantes aqu\u00ed: Cada m\u00e9todo que se encadena aqu\u00ed tambi\u00e9n se ejecuta de forma as\u00edncrona, por lo que no est\u00e1 bloqueando el hilo de origen. Una vez que la llamada get contra couchbase retorna, mapeamos el firstname desde el documento JSON y finalmente lo imprimimos. No necesitas proporcionar un Observer completo, si s\u00f3lo est\u00e1s interesado en el valor onNext puedes simplemente implementarlo (como se muestra aqu\u00ed). Ver los m\u00e9todos sobrecargados para m\u00e1s ejemplos.<\/p>\n<p>Tambi\u00e9n tenga en cuenta que estoy mostrando deliberadamente Java 6\/7 estilo clases an\u00f3nimas aqu\u00ed. Tambi\u00e9n soportamos Java 8, pero hablaremos de ello m\u00e1s adelante. Ahora, \u00bfc\u00f3mo podr\u00edamos extender esta cadena si s\u00f3lo queremos imprimir el nombre si empieza por \"a\"?<\/p>\n<div class=\"geshifilter\">\n<div class=\"java geshifilter-java\" style=\"font-family:monospace;\">cubo<br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">consiga<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"usuario::1\"<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">mapa<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Func1<span style=\"color: #339933;\"><<\/span>JsonDocument, Cadena<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Astring+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Cadena<\/span><\/a> llame a<span style=\"color: #009900;\">(<\/span>JsonDocument jsonDocument<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">devolver<\/span> jsonDocument.<span style=\"color: #006633;\">contenido<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">getString<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"nombre\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">filtro<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Func1<span style=\"color: #339933;\"><<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Astring+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Cadena<\/span><\/a>Booleano<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Aboolean+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Booleano<\/span><\/a> llame a<span style=\"color: #009900;\">(<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Astring+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Cadena<\/span><\/a> s<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">devolver<\/span> s.<span style=\"color: #006633;\">empiezaCon<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"a\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">suscr\u00edbase a<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Acci\u00f3n1<span style=\"color: #339933;\"><<\/span>Cadena<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> <span style=\"color: #000066; font-weight: bold;\">void<\/span> llame a<span style=\"color: #009900;\">(<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Astring+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Cadena<\/span><\/a> nombre<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Asystem+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Sistema<\/span><\/a>.<span style=\"color: #006633;\">fuera<\/span>.<span style=\"color: #006633;\">println<\/span><span style=\"color: #009900;\">(<\/span>nombre<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><\/div>\n<\/div>\n<p>Por supuesto, una simple sentencia if ser\u00eda suficiente, pero puedes imaginar que tu c\u00f3digo para filtrar podr\u00eda ser mucho m\u00e1s complejo (y probablemente llamando a algo m\u00e1s tambi\u00e9n). Como ejemplo final sobre la transformaci\u00f3n de observables, vamos a hacer algo que ocurre muy a menudo: cargas un documento, modificas su contenido y luego lo guardas de nuevo en couchbase:<\/p>\n<div class=\"geshifilter\">\n<div class=\"java geshifilter-java\" style=\"font-family:monospace;\">cubo<br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">consiga<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"usuario::1\"<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">mapa<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Func1<span style=\"color: #339933;\"><<\/span>JsonDocument, JsonDocument<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> Llamada a JsonDocument<span style=\"color: #009900;\">(<\/span>JsonDocument original<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 original.<span style=\"color: #006633;\">contenido<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">poner<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"nombre\"<\/span>, <span style=\"color: #0000ff;\">\"Otra cosa\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">devolver<\/span> original<span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">flatMap<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Func1<span style=\"color: #339933;\"><<\/span>JsonDocument, Observable<span style=\"color: #339933;\"><<\/span>JsonDocument<span style=\"color: #339933;\">>><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> Observable<span style=\"color: #339933;\"><<\/span>JsonDocument<span style=\"color: #339933;\">><\/span> llame a<span style=\"color: #009900;\">(<\/span>JsonDocument modificado<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">devolver<\/span> cubo.<span style=\"color: #006633;\">sustituir<\/span><span style=\"color: #009900;\">(<\/span>modificado<span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">suscr\u00edbase a<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><\/div>\n<\/div>\n<p>FlatMap se comporta de forma muy parecida a map, la diferencia es que devuelve un observable, por lo que es perfectamente adecuado para map sobre operaciones as\u00edncronas.<\/p>\n<p>Otro aspecto es que con Observables, el manejo sofisticado de errores est\u00e1 al alcance de tu mano. Implementemos un ejemplo que aplique un tiempo de espera de 2 segundos y si la llamada no retorna devuelva otra cosa en su lugar:<\/p>\n<div class=\"geshifilter\">\n<div class=\"java geshifilter-java\" style=\"font-family:monospace;\">cubo<br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">consiga<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"usuario::1\"<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">tiempo de espera<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #cc66cc;\">2<\/span>, TimeUnit.<span style=\"color: #006633;\">SEGUNDOS<\/span><span style=\"color: #009900;\">)<\/span><br \/>\u00a0 \u00a0 .<span style=\"color: #006633;\">onErrorReturn<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #000000; font-weight: bold;\">nuevo<\/span> Func1<span style=\"color: #339933;\"><<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Athrowable+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Throwable<\/span><\/a>JsonDocument<span style=\"color: #339933;\">><\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 @Override<br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">p\u00fablico<\/span> Llamada a JsonDocument<span style=\"color: #009900;\">(<\/span><a href=\"https:\/\/www.google.com\/search?hl=en&#038;q=allinurl%3Athrowable+java.sun.com&#038;btnI=I%27m%20Feeling%20Lucky\"><span style=\"color: #003399;\">Throwable<\/span><\/a> arrojadizo<span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #000000; font-weight: bold;\">devolver<\/span> JsonDocument.<span style=\"color: #006633;\">crear<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"usuario::an\u00f3nimo\"<\/span>JsonObject.<span style=\"color: #006633;\">vac\u00edo<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span>.<span style=\"color: #006633;\">poner<\/span><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">\"nombre\"<\/span>, <span style=\"color: #0000ff;\">\"john-doe\"<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><br \/>\u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><br \/>\u00a0 \u00a0 <span style=\"color: #009900;\">}<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">;<\/span><\/div>\n<\/div>\n<p>Aqu\u00ed se devuelve un documento ficticio (pretendiendo algunos valores predeterminados razonables para nuestro ejemplo) si la llamada get no vuelve en 2 segundos. Esto es s\u00f3lo un ejemplo simple, pero se pueden hacer muchas cosas con las excepciones, como reintentar, ramificarse a otros observables y as\u00ed sucesivamente. Por favor, consulte la documentaci\u00f3n oficial (y la documentaci\u00f3n de Rx) para saber c\u00f3mo utilizarlas correctamente.<\/p>\n<h2>Espera, hay m\u00e1s<\/h2>\n<p>Hay muchas m\u00e1s funciones disponibles, como combinar (merging, zipping, concat) diferentes observables, agrupar los resultados en intervalos de tiempo, hacer efectos secundarios y otras. Una vez superado el (peque\u00f1o) obst\u00e1culo inicial de entender el concepto, se siente muy natural y le prometemos que no querr\u00e1 volver atr\u00e1s (si nos equivocamos, sin embargo, siempre se puede bloquear en un Observable o convertirlo en un futuro).<\/p>\n<p>RxJava tambi\u00e9n tiene soporte decente para Java 8, as\u00ed que si eres un afortunado que ya puede usarlo en sus proyectos puedes simplificar un ejemplo de arriba a esto:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">cubo<br \/>\u00a0 \u00a0 .get(\"usuario::1\")<br \/>\u00a0 \u00a0 .map(jsonDocument -&gt; jsonDocument.content().getString(\"firstname\"))<br \/>\u00a0 \u00a0 .filter(s -&gt; s.startsWith(\"a\"))<br \/>\u00a0 \u00a0 .subscribe(System.out::println);<\/div>\n<\/div>\n<p>Genial, \u00bfverdad? RxJava tambi\u00e9n proporciona diferentes adaptadores de lenguaje en la parte superior, en el momento de escribir Scala, Clojure, Groovy, JRuby y Kotlin. Se pueden utilizar para proporcionar una integraci\u00f3n a\u00fan m\u00e1s espec\u00edfica del lenguaje y tambi\u00e9n estamos planeando utilizar algunos de ellos para mejorar el soporte de couchbase para cada uno de esos lenguajes a medida que veamos la demanda. Nuestra prioridad m\u00e1s importante, aparte del SDK de Java, es sin duda Scala, \u00a1as\u00ed que estate atento a algunos anuncios m\u00e1s pronto que tarde!<\/p>\n<p>Esperamos que ahora est\u00e9 tan entusiasmado como nosotros y esperamos sus comentarios y preguntas a trav\u00e9s de los canales habituales.<\/p>","protected":false},"excerpt":{"rendered":"<p>This blog post explains our reasoning and motivation behind choosing RxJava as one of the integral components in our new Java SDK. Motivation There are many ways to design an API and every one has its own set of benefits [&hellip;]<\/p>\n","protected":false},"author":19,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"ppma_author":[8987],"class_list":["post-1833","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Why Couchbase chose RxJava for the new Java SDK - The Couchbase Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/es\/why-couchbase-chose-rxjava-new-java-sdk\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Why Couchbase chose RxJava for the new Java SDK\" \/>\n<meta property=\"og:description\" content=\"This blog post explains our reasoning and motivation behind choosing RxJava as one of the integral components in our new Java SDK. Motivation There are many ways to design an API and every one has its own set of benefits [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/es\/why-couchbase-chose-rxjava-new-java-sdk\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-16T17:38:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Michael Nitschinger\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daschl\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michael Nitschinger\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/\"},\"author\":{\"name\":\"Michael Nitschinger\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/e5d4d332756da6f361dd88c1576de61d\"},\"headline\":\"Why Couchbase chose RxJava for the new Java SDK\",\"datePublished\":\"2014-12-16T17:38:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/\"},\"wordCount\":1092,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/\",\"name\":\"Why Couchbase chose RxJava for the new Java SDK - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-16T17:38:21+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/why-couchbase-chose-rxjava-new-java-sdk\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Why Couchbase chose RxJava for the new Java SDK\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/e5d4d332756da6f361dd88c1576de61d\",\"name\":\"Michael Nitschinger\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g95e178617974d46e3b02dd1754a3f60b\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g\",\"caption\":\"Michael Nitschinger\"},\"description\":\"Michael Nitschinger works as a Principal Software Engineer at Couchbase. He is the architect and maintainer of the Couchbase Java SDK, one of the first completely reactive database drivers on the JVM. He also authored and maintains the Couchbase Spark Connector. Michael is active in the open source community, a contributor to various other projects like RxJava and Netty.\",\"sameAs\":[\"https:\\\/\\\/nitschinger.at\",\"https:\\\/\\\/x.com\\\/daschl\"],\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/es\\\/author\\\/michael-nitschinger\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Why Couchbase chose RxJava for the new Java SDK - The Couchbase Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/es\/why-couchbase-chose-rxjava-new-java-sdk\/","og_locale":"es_MX","og_type":"article","og_title":"Why Couchbase chose RxJava for the new Java SDK","og_description":"This blog post explains our reasoning and motivation behind choosing RxJava as one of the integral components in our new Java SDK. Motivation There are many ways to design an API and every one has its own set of benefits [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/es\/why-couchbase-chose-rxjava-new-java-sdk\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-16T17:38:21+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Michael Nitschinger","twitter_card":"summary_large_image","twitter_creator":"@daschl","twitter_misc":{"Written by":"Michael Nitschinger","Est. reading time":"5 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/"},"author":{"name":"Michael Nitschinger","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d"},"headline":"Why Couchbase chose RxJava for the new Java SDK","datePublished":"2014-12-16T17:38:21+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/"},"wordCount":1092,"commentCount":2,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Uncategorized"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/","url":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/","name":"Why Couchbase chose RxJava for the new Java SDK - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2014-12-16T17:38:21+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/why-couchbase-chose-rxjava-new-java-sdk\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Why Couchbase chose RxJava for the new Java SDK"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"El blog de Couchbase","description":"Couchbase, la base de datos NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"El blog de Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d","name":"Michael Nitschinger","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g95e178617974d46e3b02dd1754a3f60b","url":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","caption":"Michael Nitschinger"},"description":"Michael Nitschinger trabaja como Ingeniero de Software Principal en Couchbase. Es el arquitecto y mantenedor del SDK Java de Couchbase, uno de los primeros controladores de bases de datos completamente reactivos en la JVM. Tambi\u00e9n es autor y mantiene el conector Spark de Couchbase. Michael participa activamente en la comunidad de c\u00f3digo abierto, contribuyendo a otros proyectos como RxJava y Netty.","sameAs":["https:\/\/nitschinger.at","https:\/\/x.com\/daschl"],"url":"https:\/\/www.couchbase.com\/blog\/es\/author\/michael-nitschinger\/"}]}},"acf":[],"authors":[{"term_id":8987,"user_id":19,"is_guest":0,"slug":"michael-nitschinger","display_name":"Michael Nitschinger","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/1833","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/comments?post=1833"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/posts\/1833\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/media?parent=1833"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/categories?post=1833"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/tags?post=1833"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/es\/wp-json\/wp\/v2\/ppma_author?post=1833"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}