From cf7922283664a04d8d891ef447de5f76a1118894 Mon Sep 17 00:00:00 2001 From: bipoool Date: Sun, 11 May 2025 12:42:17 +0000 Subject: [PATCH 1/2] Added chatroom-java --- .gitignore | 4 +- examples/chatroom-java/.gitignore | 35 +++ .../.mvn/wrapper/maven-wrapper.properties | 19 ++ examples/chatroom-java/README.md | 59 ++++ examples/chatroom-java/assets/chatroom.png | Bin 0 -> 68269 bytes .../chatroom-java/dependency-reduced-pom.xml | 43 +++ examples/chatroom-java/mvnw | 259 ++++++++++++++++++ examples/chatroom-java/mvnw.cmd | 149 ++++++++++ examples/chatroom-java/pom.xml | 62 +++++ .../me/vipulgupta/dice/example/ChatRoom.java | 147 ++++++++++ .../dice/example/DiceDbChatBackend.java | 33 +++ .../java/me/vipulgupta/dice/example/Main.java | 17 ++ 12 files changed, 825 insertions(+), 2 deletions(-) create mode 100755 examples/chatroom-java/.gitignore create mode 100755 examples/chatroom-java/.mvn/wrapper/maven-wrapper.properties create mode 100755 examples/chatroom-java/README.md create mode 100755 examples/chatroom-java/assets/chatroom.png create mode 100644 examples/chatroom-java/dependency-reduced-pom.xml create mode 100755 examples/chatroom-java/mvnw create mode 100755 examples/chatroom-java/mvnw.cmd create mode 100755 examples/chatroom-java/pom.xml create mode 100755 examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/ChatRoom.java create mode 100755 examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java create mode 100755 examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/Main.java diff --git a/.gitignore b/.gitignore index 5e340da91..362ec1507 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,8 @@ __pycache__ .idea/ ./dice *.rdb -dice -main +/dice/ +/main/ tmp/ vendor/ diff --git a/examples/chatroom-java/.gitignore b/examples/chatroom-java/.gitignore new file mode 100755 index 000000000..efc30b0fe --- /dev/null +++ b/examples/chatroom-java/.gitignore @@ -0,0 +1,35 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +# .idea/* +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/examples/chatroom-java/.mvn/wrapper/maven-wrapper.properties b/examples/chatroom-java/.mvn/wrapper/maven-wrapper.properties new file mode 100755 index 000000000..57fed9863 --- /dev/null +++ b/examples/chatroom-java/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip diff --git a/examples/chatroom-java/README.md b/examples/chatroom-java/README.md new file mode 100755 index 000000000..bed4cbd0c --- /dev/null +++ b/examples/chatroom-java/README.md @@ -0,0 +1,59 @@ +# DiceDB Java Chatroom + +A terminal-based chatroom application built in Java using [DiceDB](https://github.com/DiceDB/dice) and the [DiceDB-Java SDK](https://github.com/bipoool/dicedb-java). Each instance of the application connects to a shared DiceDB backend and communicates in real-time through a simple terminal interface. + +--- + +## ⚙️ Requirements + +- Java 21 +- Maven (use included `mvnw` wrapper) +- DiceDB running locally on port `7379` + +> Make sure DiceDB is up and running before you start the application. +> Refer to [DiceDB README](https://github.com/DiceDB/dice/blob/master/README.md) for setup instructions. + +--- + +## 🚀 Running the Application + +### Using JAR + +To build and run the JAR: + +```bash +# Step 1: Build the jar +./mvnw clean install + +# Step 2: Run the jar with a username +java -jar target/chatroom.jar +java -jar target/chatroom.jar +``` + +### Using IntelliJ (Not in windows) + +```text +Just run the `main` method in the `Main` class with your desired username passed as an argument. +``` + +## 💬 Interface Instructions + +```text +1. A popup terminal window will appear. + +2. Type your message in the input box. + +3. Use the Left Arrow Key to shift focus to the Send button. + +4. Press Enter to send the message. + +5. Write 'exit' to leave the chatroom. +``` + +## 📸 Screenshots +![Chatroom Screenshot](assets/chatroom.png) + +## Want to contribute? +``` +If you have suggestions or improvements, feel free to open an issue or submit a pull request. Your feedback is always welcome! +``` \ No newline at end of file diff --git a/examples/chatroom-java/assets/chatroom.png b/examples/chatroom-java/assets/chatroom.png new file mode 100755 index 0000000000000000000000000000000000000000..2f74929f899ef086185a5f14e732d651278c1ed4 GIT binary patch literal 68269 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

fYTkMOm|Hl+2&BDZF+XuS1 z6c?&c4Y8Xy82~T0zPGL;NYqSk0`A_!LBQ1}fa5mV&Pfrowe_sG&ck;0059EK;T~2) zuBxw(D3NSo!k5n@d#K~|y!e1gRdcI2uFyLjo%tV?X&oLfQLr$VS@Uy(^Ad=0L@pi5 zS*$bNjgx6jp5Z(w8#XQ{M#l&%w^`Kf?4kqiA8ub|!=VuD_P&1=JdhL^7{~{{08Xxx zzl!R45n;gybEY4u?$WrhYJ)oof3H^ zmFscY{B_5xu#>}AEXUmtk1$H)jqossD3_SU02z->fEWp4SHWwrn$qq2 zf#etW=`zG?la0ddf(=+#Qz8SROU1%~ za9sjkEMO!A`OUL_^a6iOV)gpsKzCynS7hi97q6ex(bICe+`qV( z`PvHt2TAPDhrbtNI5-W(t!CJ|?WWNv%dj)FmXR7p}CtgK(m5-q1n zy}2wVN)0=t#WJ3Vi+3d?BxrsFi@$dt(5F352&F){OcWw2IMR)jNM@bRwD4g_)S8ES^9 z;wPp@i*nFKoYvc%98gXVAz|J1*DD=-D;o9J4etZ8=AS(JB{ylkZyvdNvr| ztQ8fNhVkegxD=*_IP3(w0{jCzvt4fR8!Y5FTi^{r#N&V&2=^<|HH}xp{dR!0>9z z3s&{cQN-*k|3Llhwyw=okJMY+Q!L{x1R`>Cb7M=;TJ}VYaYGyvwD)41o3bhvvG3)b z2?V|&*7dYOZ3Awpd1F@6XWubHaLhLaar~Z)V`QLz?}#%*)@-CMc1t<@RhtGQ8ims8 zCk@#b+#IsZb|IGbehEEP3t*$<&D6A|i^HGKWz!ISny){sXYP_=olMCnHB^hp$d4P| z!+abT(PrAR`%{9MPl}4~9oX5AXOX{MX=sq0lT(&41D-@_vkJK$5XG$JB~|6JJJ_>; zZxiyIRI)4vXJArCextme7XWXvxI{^tXjK0Qy0X^luz|q&o8T~v!(7gYx8H3%tr&3U zYeTp^@lTzUhv%MjSiGf1(OuzG^*BU1qBhQ>krC3!PY9kBP3=VC%s}av?GKm3iIO6t zi%K@^I{V}WcMZ577+6*@-`aldrWxX$Wx)JMp@F?kAywfRN(gc@)$^9Ux2qckec;K; zgSK_?06xZAyGAeILb(>FAXkQLp*r>#B=ExIe|s-JksiLrq(sNK>>i?bfTM zzzedUE6>*=U#&fRwL9+o$bpjUn+9ls@-Jie>9NIL3AFqRtg7wx$(-53;a&iqw#FgN2_p9q1V8;eeAEDm1&~2pkKKsG960`Rx32!)2VjovZ_`J>}lVz$qWlK)FjZf5X)c{ zPQwK_?ZuOH;Kq)#GiR}kk5X>*VBvaI_1FFe{X9;C#^po--b0(>0zwoFS%>gs1l{0A z=D5`$y3{2RL>IE#rRjtmSX_NCDT#4w$-*xun+H|YbRG@fL>quVRA-8PmC@~~?gBq? zwef+V@LPH3Qfs}~M zZxgsEDOQ>jopx9qt>DVXFGN(+Vnw?t|5<%Ro@n;ct61PRrH(Mj842mZL_> zhTd~Z&(OB6jSuUxXL}<3Llh8y5#$2&dJ~DDhQNI3jxLwZNDWl<@Kvcg5#qkrr$IdM zl0}biB3FY@@TN^_i^b>t8ous2e3-VU8?ILIX}ReT3Iw4xbhy{-79??rI6-P;l`I5ez=SU^!9~arG9$ z$bS8~L`Tp);?uAU?OycIwMfqi{(^JV@e2;Sj})%kwUh8P5pe8*7gD0>>PGFN@1VKm zyATlM(;=Q3IH3MOHlfph|QKzgOYU&bXcQ41t$6Mx>1vJ+-eV_yY`paKKwzTg!Dj#jD;J6iclb zl*Xgk3?Fhv8*a{KW##0&9ZDSEv|6UlBoGZG2*L;)$0o{tR>ys)@Bx(TZa-E)#^IGG z;A3A`U$0(e$=4S*t7K!tf{%~iaVotyS}8JH?JNBn)f*+&BtkwXc&C0KZ0Nmk+A3^P zk1lP3KG@GusNH5x*EWQr46bnfL@xTtx2A?JhBu%*w+1SFcamx_f9<`Pyjf`5JuX+k` z4;j063^~!!S`=yN{Z)In(544n?ukGjb?n%PdItB9pL=>2*nqz}sm-@t7VH}hm{dPg z@OUU;UW05^uk5gbNLkhaTi zKM2hl*34ilWle^A9s9WW88`1{7=SXQf>DiRkFBTj&D$$aljIo7T< zc+?E*z`ovyn;8E6tmEVK3YW(UJ`1q4+V%U8vXm-Q%D! zjs*hmn{yZvdiOHo7@Hu5EN#i3^7`u}V)>JEYAD&s&_fq zXz{+kJ5w2K>D=VoKZ>@9BAk|X3%$g1&*B!ka{XCG#4aA$?sR$fU) zR|HV+Q9F?$5BtakFR7Ke{A>3nNQ6BhXt?u~8`}jhmVEoTIqeP_G8NvI@^>>;tDf{+y#gP5(`yw6e5U>g)>CEh{VYMAB9mS~ z3T`TOxZ%ZBW(C4BX?~KEBy@E475Vr{+Z=F6We-xG`28DgUg!yy@)zzscQ;Sk(6QTn zIq?4dZpEyUXP)7U6NAm{0a7L=_<#jhs8#*Fx3^bm&ZS@E<=_@-CWlhP`Cxqm5Kz}` zzb9v^>c&%9=9LwXu1sAOX4^qdPJL2mCoN!JPFLGddYtc@082W6mW_FkPPbojsxxKF zD+`#00U6)gPTCF23EIJ~_Fa6$`7)HnA9mNbsmV z>eetZopaxzyO>|R(TP^PUI{fvq%{W_Ez>+>-`c|()=n{4ECb>Jy&m?uqNK3ODE(YO zw&9&*esL;JN<_JN#x#IbQ#(&G7_$j zBw}82E=gg70fN7u(5KKPgxMP7Iq#Fc%3&CGm4{pD5Xu2}7;@e3+H^h8$2ojdi`rV3!6;H-Otk(?KoCS zjf2tbOzHW(lCB@=a@j^`z-gxt8X5O3YoByt7i%fOHDy0fNzjx?I9*KGkKaT;|5%PW zR$k;5aULb|Rd6Q+wN{Zo%8qb3ky-k>`$x0)RrFEP1s%<(ZsEMD(T)2@iF5Zn)SKEGtN}D`sIK zxt*f_z~CM_DiJ1aZ?_h^nlcJIl7yT}&N*x>6iU(Sdf>Na6|ueYmH3<#_G{NSRZ1;fqgJP)8KCl2o}y z{kcIFUc`s^{Csm@!7?*5lRoRSm6e1=sELNGtbBOi#%D9Ld#0|bTU%zp^$P(8cwK1& z#_Sc9mH1)nV!fLubKsK!qJUQDkg!&h`a`?a|J;|DR14Kx+i*p&TC^k+;VB{u3IW-{ zmtR=^pTiHbfW(B3V$n)qfW~kAUN@5NEjp+qmRP|IQjLIpZNz%>yVt&Y4WBwFZwAQF zeCTyrK1#{1tUZjF{Dh~!jjD^^)kZdt%>iC+@+xis-B)P(e6-hmi9cFPd+i=Fu=C@( z9^y$Hc;420EkZ#hC4h!6W)w;HF0~uk+$aznv0k^si?~YLPuLRRnRHnMTRrPCIPqzv z`pWwakLoRB=c7krm|~3OKOVkr5hrV>?O5Sbq!5eD`S8%sH3)@D!qD#P$78=o-Odk< zshryz+x@13JmaS8>Jfs;N-~qmL#Ow@I+a7fO&KB2aii+TdVusQDIxj^~_L5L#MP97cPt9%tk^PvSrE9 zV3j|TFlS-~ahTRLgK|U{BeY~Z$(6Kbw=aS)2`nXI&Q^wdB*+gF-kon5%1&-lcs!GhHVQ8>%G$g=SsZ$;9;f&r^-x$=q=ZE+&LQ9_=p_9bmv`a#N4^}I!aFlEUc0?HU}adU``-^*2n#mpRl2sTpYzslIkT5})$=*$H#4)RNe6J^n<*{I;Yp;{ zX`IpXV8+>nX}-TQ-+x_otd(e z?H$)$>TY(lV4?BEx=^LUW`TlK`R;y`Z(J!tT9dJZc?Hk6NXF8OXb<97?_%sbW$QLRQ8!*mD$B9BiTCN2OONLs~n{SoHY~p%Mz-pD^}?$ zw+MltK;}wumFt@odz+OeY89EI=4g`&h>KV5oAnDBw{z3WaXo}Y;{ne?=5v=1$m`Q; zqmqU^XWmgZCnxzNFO8(SA96a%L-O=W0>XMbd;GNHQkXNp&8&6`wTn0x*9nqHx>lbD z_HAv&S2?L_)fHkl|6tOYs2a@6S>3kKndR3LJdo4*T{Tz$w8^+p$Fjb}Y41-Vx04j9 zmjr2DAydjHJ*$NEt95{#YFn($|n zr>H7)#Y{`Plee?b%n4dUm#0|SfZqTFb30piYt?ur0<5K2^7*sF@UiCfaWLX$?UU*Z zjwnk>1#D&JTe0&@-Gs*PU<)fxQ<~2LA2dG1U5@emPJbP;aitPBRIo1qT=5C)wv4|q zH=!97pqQRm4J*zgcgHmFNt~t=e)0OxXxhQnD+ofbw<6ZPE_A@`_`Elk8+NnksnLv( z5y`k(d|_n+y6lZZDnVe?L)&^yH5sXtQI>KH?ouL`zJ#!==BpETghi733a-cxx%n9L z2PaXnz}@pCnl#cK*~IHfrwb{h%5i&MMkOL6cqQ1yLuAP&ibeOc>}T(LXbHw0yZvOa z{-)EzLotavqiSlR)O_B)dbx}t#}HYb8f`K{*nGit)1ilmO7#$(`JHDdvg+l!J7=!1 zFiPye64Mb&*<~0vA{IOwHbO`pV<;%%oedv>+Sg}PV4cmO54ge?jdgab_@0Oa z!iqgp>LNVf^>!ukU6n~{v@p6rB6UTZD!6DwubnZ;Pv&q%o@Z{m1?8L_G-VCPG%J-3 zw(AKwnhRhrVU|Tr4Mngn+psi6U@Wn^fK{tbt8)bj_vxXpn&WwgER&VFsle#KfQk@O zBq6og{S~)H)x^?*EAbnQFnN>Bz^_-S2N2l94mUU(W15LcUyS|0s))uqJzi+;H(37F z^S&cId!v)R2Ftw}@vn@$$aIDj7dIY3f)q0&AcSyveZ3MGw zJ%ZXmjO+iPyzxs{%8}pt<^R~oZ`yUha#23t!gNhsQy|F+A5TCSb0*qC&bn)rt5`F} zO;94i8Lxr{%E)z~qomhGqV;K$?*55uVpPD*{uyuIm^}XYm9K+Jvg0-v)OT}<-Fm%x zJ8QD9=U{V|+*zI{uHQZH^_gm2Ks8<5>k}>*ehI#FC5Dd$-0E!U?7fnw@Bn(+x_)|0 z+`49#>O}C~x`FcrA|~hZGN>{88Hmf4tj~sLr7Qh#qz4y(wvDcGy7$mH18 zOVb|bhN}p1mjtv)h@XQ5Y^~Y+wR`i|5SZ_0W*+>f}(Egr*Zpi z8KLS&z5Nr5V?c2GEOmScy?uVk5|2l_{ll2@C~#w1dbJ(7xpWN!0DQKGZL0_YUYZ=FiJK!?GVY^E3(9&SPmMLQ z6+E|<%&WC7PjirVyF*`5&YYD4Hxd~8o7`l=MEC{!H;lSEk3bl0g$Zl>_LO95u{=yD zD7Hi(d=OjhwZn36@3&OvavUBtSfaOI#Q-8E($~_dEiPnHS`l5io0OK|AQ|EWUg;qXw1^yCr{w(r6F+iVB zVaPyP3h$@spXds=Vt2LbLG0W|LFuO;mqBeQPn7vffBn>d9pZpuFi~rJ*GsHQ4v(N6 zH5PgI>3=ZZR<9qs@eFj=v++4k+Zde+ZWF(B{3Zj*v9)Mc*@QE7s*}Ft=KEfKu8w{8 zErKgh!>w)1xWq&yR+ZF5=Qa`LjGOu|JCp)^b(bw`ln6B6MX5wb`3>VP!Oa2-`umSm z6@T#^V3d<8$^Q^#d-@jx8B^wZ)fHG)gs*6_qXHk3?_mh zjB>XxC}hb&zY5=Yl8;8Q-M%iR%aQ%9hnMlW|8xUI?2hhT!vYO{{3T_J!OQ=6cCg)G zLUB_e)4^RB{kCj>d%J;iq4qXK<}U9o8v=Cs+SB$I&p^L_9U=b9(yBW}^GY9m?Jf^l zcDlQy{JuGvaO~s1pdK5382DQ%IQU;F(a46G;;F(~2|J@%quZ)ca2CQ7r!^Cc(5ABs z@A|k!l=#0+P}lw^UI}jTPUnVqBBoCPA^|-ry)F91mv!{N#)!W7{|O-ZufJWqwfhvr zbTj8slM>Mx%@w85By?L9N;cp(DCg!pl)QaabeGW5zeoO;g6ePop#dOf#*cOTSzTLn zM1NCu-+X(hM^OH*09h3k*IjR;Ff#vx^&qRvP=+?Z@2?IhpXY+AUIWYtNS4^lzuNyt zhfIs~Z!mp7w{q*Rxx?v;Zy6*$rl;T7EfF?fJ02J!_m@6`Ay588jPZXEqv{{=BD$@( zRQ(JWN>LJY2T}jiF6Dn&S^s67CI>Yd?2=0@u-a(aeV`10-Su8b4gtu>*a|C7IPL9U zC^gQL|1t5>KPFas45f`S=H?~51@uLtydE?mJJR}7;}zFkn`lb~{_he{h4{*Orti4L z`0Tf3P(sfhL67Pt1nXm~@7{R@ul|#80_=a9Gazt!?8j7N(_MxyZR13s)x#3nAnH4` z)CEKT=KCV?{-0*;WEI$VDkqqw!L@aP*O30@k_VzNR(=B%E6j?!diuqU{_$eSKVEde zgo-D=;pwNSRw>);L_xufka{Po>}KD9Q*9uATk4BWe!>nt%z_ijszrgv!dzcO$*H!B zXMTL2$al9L_fC?@9&tQ|n%G*&-+;JT*E6_F%$&kJ6|j?5oKGIz)=`>fZn9ESWJs9e z#BX6uz_FLzBvTZHYrfY{T4_)cS4g9wl^y%D%2?DoySn*SdDrDT|LN;@+#WO2sj(F$ zB_*x%x~c1z1w4Yvfvxx0Ult#t&=Vg9egtjZ;Ou(!-Su95SrEk|bEh0?>M2~8ygW}cDWej|i&!l{ zGu;*-1(8DRM)`95*U<(OOaUW6L$tz>+QcA*^B$G%(R0upil98_Sy?Kkl@yhy>$&EiGBYTV}eIXe-UYw|wM zEjcBn8l84OJ%n;>q2w=!+j)uD*lUv|O0S#4^gCY%j2S2`M6opz-?C%NpZ7&?wYdSM zIsR5t>!nohacVGw_=&QGi6o&#z#Z8#Nku%EniBk`>jZNr3d#%m>{oRkYe58W0qNJ+ zaZHxS|3AYARMMu?EP2{{A!PN5fXLMct>)uD#FYak88b@jkF ztL#xdc*qhi@~Z6oLvYbWd>*Hj7g@9jd2iaFL0rk}^X1aMNvt#P;~a7LDBtce*Sav7 zGd!_X_#?uR9>QPk0Z+82#Hj}l=u>7hF472H!J^z(#F4=CrGOLjWh2GR5+|1okl1tk>lWxGt!>PZ z?dE&EB|{`(GNZe#z=w~B<=B#h2J{>^G(|*4+|XutUaw2-oVMQ0dr8Q(=}`VA9eV8h zD4S;MRC+0ZWnF$RmIKGJ{sXG5oNTsa-cP>j_T2o9=WnuXXH}m(FqQ&a3c6yV@Wl}Ld zDsa`p%M)d1==wYNp4>S`9u0f}F92nuf(l4VmKb zUzW1SaaPi3b5Km;BV}_C^ar;KQ4)e@D*8tko5Uze(6PP;f}=4rSaAgn*4`~cqjat*p&$Pq;OGy~X?#d1=XwIq#OS(Qrl(X{1WY}^WLVn6Hx3-olPwxQ z>y2`2+1>gnwi&6}Rh(;K`i*2ly*_cWE<0@;E}=dUxRA$5HE5x4QvQRsI(bz2-pVblYys6^8Iz&5uc+$yqgCn^c}gYR(jwu$QUU&%3kZ#tWq=tJmjFT&8T# zY?ZqmeK6qW;*vkI#ll z#2Azq1-5)Ww)NjaLD{k<5@_q?p8<>iaFch$=v(*< znGD95!y$FY-4J2Tz}8>)?Q(c3n6>BGEu7LCABLgAJOZZ~w&2@$lz1o+=&|tff1^5C za=K20Q=-M+0X4okeDP}|HtBzZB!Mpdj>*XqKiD=o;dSwESS{h*0L<$y)*!Fi8~CSe zMRVFsmt!ZgcFhiJhJV}dP62tm?n;2UD|EI?-GXZ|%n#+Tu=jU-%>>K5P59D*r!5?> z;ZlA1cQnsvXJx>zEM4b?VhlgUyUl^}oW3N1Y3$%`{4G^CpX~o;_ZPp%EYa9OCt93L zcUqgViU<^psUFAo4_&P%5%{;|OO3_6+TBT*b=TE9;&v2gZq=YXFk|0VCc?{W>tgj zsxP=i31X+M#&T`6O8MI>xg93^2aun-a~3m~h$LLz8Q?9)#D&AjCLG2O%V_;MS@cxjsl+Ap6wXl8y?zxZNZXi=vx0?SbaFt!9dl~7Yt2*nvCjM-trf`&xK!BawOvc3=_WfXVCLyo_Uzb5m zOK~?>DkCN!3!7~%+t#8NLLfeo-Bs~zOb6>+3F}^T6<=Y3JtnkG$%9LfCDrgCK;(|j z>h9LktEy^Cf8scN$&gpcert0pvDIN}m4BsVLZyBak`JWJ}F zRTZ_$U9pSu@GU^&-x4N9_Ejt_MvXz31ig%LliRT!`@|nk5?7Xw6Bj!;uM=*;w0wG& zX<=MRA~c$>J1%{YSnLUdYM$88UodIJ%W0NZ4%T5fXoS}xNMMd)#ZFQ?F`&-ZrJB2n z8mUqX3PId7v+-|}jOL123pQZyxqp%|;+hu$)qZ)EKEkJnAZ~VFtip5DVQ^Qmf=Gx8 zh?D;LUSJ7g>={?huF_`enTcHYB-h$C;ay}`t}W z;_d3l;CJTNF^-KybwFaXv?a0E>EwBuwr$FaR$JP$XBSTFILZhU#m zMRV4%FZ&5rhiJK16LrZ1&qHjefmCbpQPBMt)zJpA{EeB0$CI~m7>l2_9;Z>LrX8}F z;l!V!6J$6wh@AvE3=#3kk~FddS~L3`$f1QGMjVRtP1Y0L38nrrlidJg>|$};t^WNk oDBQ==+;KtH{PVAcYb$UCQ9g$)pQ>i%0N+uhB;?-}i|PCPFBe3~t^fc4 literal 0 HcmV?d00001 diff --git a/examples/chatroom-java/dependency-reduced-pom.xml b/examples/chatroom-java/dependency-reduced-pom.xml new file mode 100644 index 000000000..ff5c1a486 --- /dev/null +++ b/examples/chatroom-java/dependency-reduced-pom.xml @@ -0,0 +1,43 @@ + + + 4.0.0 + me.vipulgupta.dice.example + chatroom-java + 1.0-SNAPSHOT + + + + maven-jar-plugin + 3.3.0 + + + + true + me.vipulgupta.dice.example.Main + + + + + + maven-shade-plugin + 3.4.1 + + + package + + shade + + + chatroom + + + + + + + + 21 + 21 + UTF-8 + + diff --git a/examples/chatroom-java/mvnw b/examples/chatroom-java/mvnw new file mode 100755 index 000000000..19529ddf8 --- /dev/null +++ b/examples/chatroom-java/mvnw @@ -0,0 +1,259 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.2 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/examples/chatroom-java/mvnw.cmd b/examples/chatroom-java/mvnw.cmd new file mode 100755 index 000000000..b150b91ed --- /dev/null +++ b/examples/chatroom-java/mvnw.cmd @@ -0,0 +1,149 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/examples/chatroom-java/pom.xml b/examples/chatroom-java/pom.xml new file mode 100755 index 000000000..0fa8bb3c2 --- /dev/null +++ b/examples/chatroom-java/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + me.vipulgupta.dice.example + chatroom-java + 1.0-SNAPSHOT + + + + me.vipulgupta.dice + dicedb-java + 1.0.2 + + + com.googlecode.lanterna + lanterna + 3.1.2 + + + + + 21 + 21 + UTF-8 + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + true + me.vipulgupta.dice.example.Main + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.4.1 + + + package + shade + + chatroom + + + + + + + + \ No newline at end of file diff --git a/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/ChatRoom.java b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/ChatRoom.java new file mode 100755 index 000000000..97053ee86 --- /dev/null +++ b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/ChatRoom.java @@ -0,0 +1,147 @@ +package me.vipulgupta.dice.example; + +import static me.vipulgupta.dice.Reponse.Status.Status_ERR; + +import com.googlecode.lanterna.TerminalSize; +import com.googlecode.lanterna.gui2.BasicWindow; +import com.googlecode.lanterna.gui2.BorderLayout; +import com.googlecode.lanterna.gui2.BorderLayout.Location; +import com.googlecode.lanterna.gui2.Borders; +import com.googlecode.lanterna.gui2.Button; +import com.googlecode.lanterna.gui2.Direction; +import com.googlecode.lanterna.gui2.LinearLayout; +import com.googlecode.lanterna.gui2.MultiWindowTextGUI; +import com.googlecode.lanterna.gui2.Panel; +import com.googlecode.lanterna.gui2.TextBox; +import com.googlecode.lanterna.gui2.Window; +import com.googlecode.lanterna.screen.Screen; +import com.googlecode.lanterna.terminal.DefaultTerminalFactory; +import java.io.IOException; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import me.vipulgupta.dice.Exceptions.DiceDbException; +import me.vipulgupta.dice.Reponse.Response; + +public class ChatRoom { + + String username; + DiceDbChatBackend diceDbChatBackend; + BlockingQueue messageQueue; + TextBox messagesBox; + ExecutorService executorService; + Screen screen; + MultiWindowTextGUI gui; + BasicWindow window; + + ChatRoom(String username, DiceDbChatBackend diceDbChatBackend) + throws IOException, DiceDbException, InterruptedException { + this.username = username; + this.diceDbChatBackend = diceDbChatBackend; + this.messageQueue = this.diceDbChatBackend.register(); + this.executorService = Executors.newFixedThreadPool(2); + this.initUi(); + this.receiveMessage(); + this.sendFirstMessage(); + this.gui.addWindowAndWait(this.window); + } + + public void sendMessage(String message) { + try { + diceDbChatBackend.broadcast(message); + } catch (DiceDbException e) { + System.err.println("Error sending message: " + e.getMessage()); + } + } + + public void receiveMessage() { + this.executorService.submit(() -> { + while (true) { + try { + Response response = messageQueue.take(); + if (response.getStatus() == Status_ERR) { + System.out.println("Stopping receiving message: " + response.getMessage()); + break; + } + String message = response.getGETRes().getValue(); + messagesBox.addLine(message); + } catch (InterruptedException e) { + System.out.println("Stopping receiving message: " + e.getMessage()); + } + } + }); + } + + public void sendFirstMessage() { + try { + String message = username + ": Joined the chat room!"; + diceDbChatBackend.broadcast(message); + } catch (DiceDbException e) { + System.err.println("Error sending message: " + e.getMessage()); + } + } + + public void initUi() throws IOException { + this.screen = new DefaultTerminalFactory().setInitialTerminalSize(new TerminalSize(80, 20)) + .createScreen(); + this.screen.startScreen(); + this.gui = new MultiWindowTextGUI(this.screen); + this.window = new BasicWindow("DiceDB Chat Room"); + this.window.setHints(Set.of(Window.Hint.CENTERED, + Window.Hint.NO_POST_RENDERING, + Window.Hint.EXPANDED)); + Panel rootPanel = new Panel(new BorderLayout()); + + this.messagesBox = new TextBox(new TerminalSize(80, 12), TextBox.Style.MULTI_LINE); + this.messagesBox.setReadOnly(true); + rootPanel.addComponent(this.messagesBox, Location.TOP); + + Panel inputPanel = new Panel(new LinearLayout(Direction.HORIZONTAL)); + TextBox inputBox = new TextBox("Type Message Here...") + .setPreferredSize(new TerminalSize(60, 1)); + + Button sendButton = new Button("Send").setSize(new TerminalSize(20, 1)); + sendButton.addListener((button1) -> { + String message = inputBox.getText(); + if (message.isEmpty()) { + return; + } + if (message.equalsIgnoreCase("exit")) { + this.close(); + return; + } + inputBox.setText(""); + sendMessage(username + ": " + message); + }); + + inputPanel.addComponent(inputBox.withBorder(Borders.singleLine())); + inputPanel.addComponent(sendButton.withBorder(Borders.singleLine())); + + rootPanel.addComponent(inputPanel); + this.window.setComponent(rootPanel); + + inputBox.setCaretPosition(inputBox.getCaretPosition().getColumn()); + inputBox.takeFocus(); + } + + public void close() { + try { + messageQueue.put(Response.newBuilder().setStatus(Status_ERR) + .setMessage("Stopping receiving message").build()); + executorService.shutdown(); + if (!executorService.awaitTermination(10, java.util.concurrent.TimeUnit.SECONDS)) { + executorService.shutdownNow(); + } + this.diceDbChatBackend.close(); + this.screen.close(); + } catch (IOException e) { + System.err.println("Error closing chat room: " + e.getMessage()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + } + +} diff --git a/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java new file mode 100755 index 000000000..3c8726e62 --- /dev/null +++ b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java @@ -0,0 +1,33 @@ +package me.vipulgupta.dice.example; + +import java.util.List; +import java.util.concurrent.BlockingQueue; +import me.vipulgupta.dice.DiceDbManager; +import me.vipulgupta.dice.Exceptions.DiceDbException; +import me.vipulgupta.dice.Reponse.Response; + +class DiceDbChatBackend { + + BlockingQueue messageQueue; + DiceDbManager diceDbManager; + String username; + + DiceDbChatBackend(String username) throws DiceDbException, InterruptedException { + this.diceDbManager = new DiceDbManager("localhost", 7379, 2, 2); + this.username = username; + } + + public BlockingQueue register() throws DiceDbException, InterruptedException { + messageQueue = diceDbManager.watch("GET.WATCH", List.of("last_message")); + messageQueue.take(); // consume the first message + return this.messageQueue; + } + + public void broadcast(String message) throws DiceDbException { + this.diceDbManager.fire("SET", List.of("last_message", message)); + } + + public void close() { + diceDbManager.close(); + } +} diff --git a/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/Main.java b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/Main.java new file mode 100755 index 000000000..fd276b23f --- /dev/null +++ b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/Main.java @@ -0,0 +1,17 @@ +package me.vipulgupta.dice.example; + +import java.io.IOException; +import me.vipulgupta.dice.Exceptions.DiceDbException; + +public class Main { + + public static void main(String[] args) throws DiceDbException, InterruptedException, IOException { + + String username = args.length > 0 ? args[0] : "Anonymous"; + DiceDbChatBackend chatBackend = new DiceDbChatBackend(username); + ChatRoom chatRoom = new ChatRoom(username, chatBackend); + Runtime.getRuntime().addShutdownHook(new Thread(chatRoom::close)); + + } + +} From 1ca5ea3f05b0783376b9febd2b85fe242dab10d9 Mon Sep 17 00:00:00 2001 From: bipoool Date: Tue, 13 May 2025 15:41:48 +0000 Subject: [PATCH 2/2] Added docker file --- examples/chatroom-java/.gitignore | 2 +- examples/chatroom-java/Dockerfile | 9 ++++++++ examples/chatroom-java/README.md | 16 ++++++++++++++ examples/chatroom-java/docker-compose.yml | 21 +++++++++++++++++++ .../dice/example/DiceDbChatBackend.java | 4 +++- 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100755 examples/chatroom-java/Dockerfile create mode 100755 examples/chatroom-java/docker-compose.yml diff --git a/examples/chatroom-java/.gitignore b/examples/chatroom-java/.gitignore index efc30b0fe..f1b939beb 100755 --- a/examples/chatroom-java/.gitignore +++ b/examples/chatroom-java/.gitignore @@ -4,7 +4,7 @@ target/ !**/src/test/**/target/ ### IntelliJ IDEA ### -# .idea/* +.idea/* *.iws *.iml *.ipr diff --git a/examples/chatroom-java/Dockerfile b/examples/chatroom-java/Dockerfile new file mode 100755 index 000000000..479f69ad7 --- /dev/null +++ b/examples/chatroom-java/Dockerfile @@ -0,0 +1,9 @@ +# Use OpenJDK 21 base image +FROM openjdk:21-jdk + +WORKDIR /app + +COPY target/chatroom.jar . + +ENTRYPOINT ["java", "-jar", "chatroom.jar"] +CMD [] \ No newline at end of file diff --git a/examples/chatroom-java/README.md b/examples/chatroom-java/README.md index bed4cbd0c..1e163425e 100755 --- a/examples/chatroom-java/README.md +++ b/examples/chatroom-java/README.md @@ -30,6 +30,22 @@ java -jar target/chatroom.jar java -jar target/chatroom.jar ``` +### Using Docker + +To build and run the Container: + +```bash +# Step 1: Build the jar +./mvnw clean install + +# Step 2: Run DiceDB docker container first +docker-compose up -d dicedb + +# Step 3: Run Container for each chatroom session +docker-compose run chatroom username1 +docker-compose run chatroom username2 +``` + ### Using IntelliJ (Not in windows) ```text diff --git a/examples/chatroom-java/docker-compose.yml b/examples/chatroom-java/docker-compose.yml new file mode 100755 index 000000000..5da3d4757 --- /dev/null +++ b/examples/chatroom-java/docker-compose.yml @@ -0,0 +1,21 @@ +version: '3.8' + +services: + dicedb: + image: dicedb/dicedb:latest + container_name: dicedb + ports: + - "7379:7379" + + chatroom: + build: + context: . + dockerfile: Dockerfile + container_name: chatroom-app + depends_on: + - dicedb + environment: + - DICEDB_HOST=dicedb + - DICEDB_PORT=7379 + stdin_open: true + tty: true diff --git a/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java index 3c8726e62..74e373c02 100755 --- a/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java +++ b/examples/chatroom-java/src/main/java/me/vipulgupta/dice/example/DiceDbChatBackend.java @@ -13,7 +13,9 @@ class DiceDbChatBackend { String username; DiceDbChatBackend(String username) throws DiceDbException, InterruptedException { - this.diceDbManager = new DiceDbManager("localhost", 7379, 2, 2); + String host = System.getenv("DICEDB_HOST") == null ? "localhost" : System.getenv("DICEDB_HOST"); + int port = System.getenv("DICEDB_PORT") == null ? 7379 : Integer.parseInt(System.getenv("DICEDB_PORT")); + this.diceDbManager = new DiceDbManager(host, port, 2, 2); this.username = username; }