2019年9月12日木曜日

RFC 7230 HTTPのABNF拡張を考えている

最近ABNF界隈のテストでRFCに書かれているABNFをいろいろ実装してみているのですが、ABNFを拡張したものがいくつかあり、RFC 7230 HTTPでは *の他に#というのが追加されていて、ABNFをわかっていないのか、なぜか中途半端なところまでしか書かれていない。
というわけでどうやって実装しようか悩んでみて拡張を投入してみた。

RFC 2373 IPv6
RFC 2396 URI
RFC 3986 URI
RFC 3987 IRI
RFC 6874
RFC 7230 HTTP
RFC 8259 JSON

このあたりのABNFを実装したりしなかったりしてGitHubへ投下してみたり。

NFCからIFTTTのIoTへ繋げるヒント

Google Homeなどで家電の操作ができ、ほとんどリモコンは必要なくなってきていたりしますが、素早く操作したいこともあるのでAndroidで操作画面を開いてアプリを開いてボタンを押す、みたいな長々とした操作をなんとかしたいところ。
というわけで、イベント駆動にNFCタグを使ってIFTTTをつつく方法を探してみたりしていました。IFTTTから先は連携できる機器が沢山あるので省略。
AndroidのIFTTTでもトリガーにNFCタグを読み取るという機能はないので、 NFCタグ側でなんとかしてみたいところです。
部屋の前で電気をつけたり、音楽を再生したり、音声操作が苦手でもNFCタグにタッチでできるようになったりならなかったり。

NFCタグ→URL→IFTTT


NFCに埋め込めるのは、アプリ固有の情報、URLなどいくつかあります。NFCからIFTTTに連携できそうなアプリはないようです。IFTTT側ではURLをトリガーにすることができるようなのでNFCタグにURLを埋め込み、タッチしてAndroidのブラウザで開くとIFTTTが動くという方向で考えてみます。
前提条件(制限事項)
  • FelicaではないのでAndroid画面が使える状態でしかNFCタグには反応しません。たぶん。
  • 数回操作があります。
  • ブラウザで開くので閉じるのが面倒です。

IFTTTのWebhooks

IFTTTをURLからつつくには、Webhooksというのがあるようです。IFTTTの画面が迷路のようなのでどこに何があるのかさっぱり…。

Appletにする

PCだと、IFTTTサイトのCreate でAppletを作ることができます。
If +This then That
  • ThisでWebhooksを探します。基本設定があるかもしれません。(Step 1 of 6)
  • ひとつしかないので Receive a web request を選び、英数で?イベント名を入力します。(Step 2 of 6)
  • Thatで操作対象サービスを選びます (Step 3 of 6)
  • 操作を選びます。(Step 4 of 6)
  • ボタンなどを選択します (Step 5 of 6)
  • できあがった機能に名前をつけて確認してFinish (Step 6 of 6)
追加したWebHooksの基本設定はMy services で確認することができます。
AppletはMy Applets で機能の有効/無効のON/OFFができます。

使う


Webhooksを追加できたらURLを使えるようにします。タグの機能にあわせててきとーに名前っぽいものをつけてON用とかOFF用とか用意します。
Applet? でIoT機器などと連携すればとりあえず完成。

NFCタグを作る

IFTTTで用意したURLをNFCタグに書き込みます。
標準的なURLを埋め込んだNFCタグを作ります。URLは共通仕様なので、書き込みアプリはどれでもいいです。サンワサプライのタグとアプリで書き込んでみました。
URLはIFTTTのMy servicesからWebHooksを選び、右上のDocumentationで書き方を確認できます。個人用のものは公開しないよう注意しましょう。
NFCのデータサイズはURLが入る程度なので小さいものでも問題なく書き込めました。

Androidでタッチ

URLを開きますか? と問われてブラウザが開きます。IFTTTが反応したらとりあえず成功です。あまりさくっと使えるものではないですが、使える場所にNFCタグを張っておくとリモコンがないときに便利かもしれません。

置き換えてみる

NFCタグの他に、QRコードでもURLを開くことはできますね。WindowsやAndroidのショートカットやブラウザのブックマークでもいいのですが、IFTTTのURLがつつければ、何でもできます。

2019年8月19日月曜日

Raspberry PiのTomcat 9にLet's Encryptを

Raspberry Piといえども最近はTLSが必要らしいので早々にTLS化する必要があります。
Let's Encryptを使用してみました。

# apt-get install python-certbot-apache
というのでいろいろインストールされた。
いろいろつついてしまった中で、最初はメールアドレスやライセンスの質問があった気がします。
とりあえず全部rootで実行してしまいましたがtomcatかなにかで使えるのかな?

何度か試してみた後…
# certbot certonly -d siisise.net
How would you like to authenticate with the ACME CA?
(認証方法どないする?)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Apache Web Server plugin (apache)
(Apacheのプラグイン使う)
2: Spin up a temporary webserver (standalone)
(仮の独立Webサーバ立ててサインアップする)
3: Place files in webroot directory (webroot)
(webのrootディレクトリにファイル置いて認証する)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3つの選択肢、サーバを止められるなら2、止められないなら3かな
とりあえず2と3で試してみた。ワイルドカード証明書はこれとは別でDNSを使うと取れるらしいです。

2の場合はポート80を使っているサーバを止めてから実行するだけ。
# service tomcat9 stop を先に実行しておく
仮のサーバが起動し、ドメイン接続確認後、 /etc/letsencrypt/live/siisise.net/ に各種ファイルを作ってくれました。developer.jpも同じように作成。

3の場合は
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for siisise.net
Input the webroot for siisise.net: (Enter 'c' to cancel):
webrootどこにある? と聞かれます。Tomcatの場合は webapps/ROOT/ のことです。
/var/lib/tomcat9/webapps/ROOT/ (マルチドメインにしていない場合)などフルパスで指定すると勝手にファイルを作って勝手に認証され、勝手にファイルを消すか何かで終わってくれます。

証明書とチェーン証明書は
/etc/letsencrypt/live/siisise.net/fullchain.pem
キーファイル(秘密鍵)は
/etc/letsencrypt/live/siisise.net/privkey.pem
2019年11月16日(3カ月くらい)で証明書は切れるよと。
新しい証明書とりたいときはcertbotを走らせるべし。
手動で全証明書更新するなら"certbot renew"を実行するべし。みたいな説明が出て完了。

最近の? Tomcat 9はJKSでもPKCS#11?でもPKCS#12でも使えますが、今回はApacheと同じcertbotが吐き出したPKCS#11かなにか(鍵と証明書が別ファイル)の形式のまま。PKCS12にまとめたりJKSに変換したりはしていないのでお手軽です。ディレクトリと/etc/letsencrypt/archive/ドメイン/privkey.pemのアクセス権をtomcatで利用可能なように調整。
# chgrp tomcat /etc/letsencrypt/archive
他いろいろ
tomcatのconfからシンボリックリンクを張り。使うのは証明書(cert.pemとchain.pem
 かfullchain.pem)と秘密鍵(privkey.pem)

# ln -s /etc/letsencrypt/live/siisise.net/fullchain.pem /etc/tomcat9/siisisenet-rsa-fullchain.pem
# ln -s /etc/letsencrypt/live/siisise.net/privkey.pem /etc/tomcat9/siisisenet-rsa-key.pem

Tomcatの /etc/tomcat9/server.xml を修正、起動。

HTTP/2の使えるport 8443の設定コメントを使ってport 443を設定してみた。(例によって<>括弧は全角)
< Connector port="443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnable="true" >
 <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol">
 <SSLHostConfig>
  <Certificate
 certificateKeyFile="conf/siisisenet-rsa-key.pem"
 certificateFile="conf/siisisenet-rsa-fullchain.pem"
 type="RSA" />
 </SSLHostConfig>
 <SSLHostConfig hostName="developer.jp">
  <Certificate
 certificateKeyFile="conf/developerjp-rsa-key.pem"
 certificateFile="conf/developerjp-rsa-fullchain.pem"
 type="RSA" />
 </SSLHostConfig></Connector>

とこんなかんじでマルチドメインでも使えます。SSLHostConfig デフォルト以外はhostNameを付けています。
certificateFileをfullchain.pem  にするとcertificateChainFileは要らないので省略しています。(Apache httpd 2.4.8以上と同じ、らしい)
# service tomcat9 restart かなにかで再起動。
使えないときは /var/log/tomcat9/catalina.2019-08-19.log などでエラーが出ていないかチェックします。
https://siisise.net/ や https://developer.jp/ にアクセスできることを確認。その他ドメインでもアクセスできますがドメインが違うと警告がでます。

Tomcatでサーバ運用は危険といわれていたこともありましたが、今は何が危険なのか。
自動更新までは試していないので、それはまたそのときかな。このまま更新を自動化してもアクセス権が死ぬかもしれない。秘密鍵は更新されない? さてどうでしょう。

2019年8月9日金曜日

Raspberry PiでTomcat 9とPostgreSQLをぐりぐりする

Raspberry Pi Zero WでJava SE 8が使えるようになったところでApache TomcatやPostgreSQLを使いたいのです。アクセス負荷に耐えられるようmicroSDカードは大容量や高耐久のものにしてみたのでした。

Tomcatは9だった

tomcatはパッケージを入れても動くのですが、常時動いてほしいのでaptで取ってくるとどうなるのかというお試し。最新のTomcat 9はJDK 8でも動きます。

# apt-get install tomcat9
で、だいたい入ります。tomcat9-admin も入れてみるといいのでしょうか。
他のパッケージはtomcat9-docs, tomcat9-examples, tomcat9-users とあるようです。
/usr/share/tomcat9 がCATALINA_HOME、/var/lib/tomcat9 がCATALINA_BASE となり、tomcatグループとユーザも作られ、サーバもtomcat権限で動いています。アプリ系のアカウントは基本rootやsudoで作業すればいいのでパスワードを設定してはいけません。
CATALINA_HOMEは基本的に触れません。CATALINA_BASEのconf内をいろいろカスタマイズすることで、いろいろと動いてくれます。/etc/tomcat9 にリンクされています。
初期ポートは8080なので、conf/server.xml でport 80にしたり、複数仮想サーバを作ったりできます。
サービス開始/停止は
# service tomcat9 start
# service tomcat9 stop
でできるようです。どこに設定があるのかよくわからない。 RedHat系で/etc/rc.d/init.d/ にあるようなものは /etc/default/ にあるのかな。
Webはオートデプロイにして、webapps相当のグループをtomcatにして書き込みもできるようにしておくと、管理も楽かもしれませぬ。

PostgreSQLはもう11か

Raspberry Pi Zero WとWH、ふたつあるのでTomcatとは別の方にPostgreSQL入れます。
# apt-get install postgresql だったかもう忘れた。
 rootではpsqlコマンドが使えなくなっているのでpostgresユーザでpsqlコマンドをたたきます。
# su - postgres
$ psql --version
psql (PostgreSQL) 11.4 (Raspbian 11.4-1)
これはrootでもできます。
$ psql
postgres=# \l
 でデータベースの一覧がでてきます。qで終わり? 基本的にいろいろ省略するとユーザ名と同じpostgresというPostgreSQLのユーザで同名のデータベースに繋がっています。
psqlから抜けるのは
postgres=# \q
です。\hでヘルプが出るかもしれません。
外部からのアクセスを許可するには、
/var/lib/postgresql/11/main/ がデータの位置、/etc/postgresql/11/main/ が設定ファイルの位置、らしいです。pg_hba.confで特定IPアドレスからのアクセスを許可します。アカウントも作っておきましょう。postgresql.confの設定も変える必要があるかもしれません。
雑に終了。

公開の際にはIPv4でフィルタリングしていてもIPv6で丸見えになることが予想されるので注意しましょう。

2019年8月7日水曜日

RazpberryPi Zero WでJavaを使おう

というわけでRaspberryPiどころか家でPCにも触ってなかったのですが最近Ryzen 5 2600XなPCを組んでからプログラミングやらいろいろ再開中で、RaspberryPiでWebサーバでもと思ったら2Bが行方不明なのでZero Wを買って挑戦してみることに。
いろいろ罠にはまります。
  • RaspberryPi Zero WとWHをスイッチサイエンスで1つずつ購入
  • microSDXCカード 128GBを2枚購入していた(危険 class 10、UHS-Ⅰ Speed Class 1、A1対応)
  • microSDHC 8~32GBが推奨
  • USBキーボードがなかった(Logiのワイヤレスドングルので可。SANWAのキーボードもあった)
  • てきとーなmicroUSBで繋がる電源
  • PuTTYとWinSCPでリモート接続

本体の選択

まずは本体の選択、初心者はできれば3B+かな。Zeroは2台目以降でもいいのかもしれない。
フルサイズUSB端子がある、有線LANがある、無線LANもある、HDMIがフルサイズ、などの理由です。変換ケーブル類も高いので予備がないなら3B+です。
Zero Wは、シングルコアARMv6、microUSB OTGがある、有線LANがない、無線LANがある、HDMIがminiサイズ、といろいろと不便です。Zeroになると無線LANまでないので別途用意しないといけません。
Javaを動かしたいならARMv7以降のCPUのものを選ぼう。NOOBSにはARMv7対応のJava11くらいが入っていた。Zero WはARMv6です。あとで対応したJavaを探します。

メモリーカード、OSの選択

メモリーカードの設定から入ります。microSDHC、microSDXCが使えますが、推奨は8GB以上のようです。microSDXCはフォーマットがFAT32ではないという理由で初心者にはおすすめしません。というわけで、初心者向けの容量は8GBから32GBの間で選びます。挑戦したい人はmicroSDXCも今は512GBくらいまであるので選び放題です。
速度など容量以外の選択基準では、class10、UHS不要、A1かA2対応のスマホ用に最適化されているようなものや、書き換えに高耐久なもの、がおすすめです。PCで最初に書き込むのが速い方がいいという理由でUHSスピードクラスの速いものを選んでも全然かまいません。

次にOS(インストーラ)ですが、NOOBSにしてみます。ファイルをコピーするだけで簡単です。OSは、Raspbianなども選択できます。

書き込んでみる(microSDXCで難儀)

64GB以上のmicroSDXCは特殊事情により標準のフォーマットがexFATです。RaspberryPiではこれをFAT32にする必要があります。
http://www.ridgecrop.demon.co.uk/index.htm?guiformat.htm
RasPiサイトでおすすめのフォーマッタはこれなのでこれでFAT32にフォーマットしてみました。
次にNOOBSのファイルをダウンロード、解凍して入れるだけ。Torrentも利用できるようです。とりあえずインストーラは完成。

繋ぐ+トラブル

RaspberryPi Zero WにmicroSDXCカード、miniHDMI、microUSB電源、キーボードを繋ぎ起動、インストーラ選択画面まで表示、操作できません。
原因は電源不足電源とデータの接続が逆。USBとPWRの刻印があるので注意しましょ。電源が外側の端子のようです。また、データ側のUSBを抜き差ししても再起動してしまうことがよくあるのでインストール用にUSB HUBなどをあらかじめ繋いでおきます。
無線LANを設定、OSを選んでインストールでなんとか進みます。インストーラの言語を日本語にしたりもできます。

OS入れた

インストールが進むと再起動、何かのOSがGUIで起動しました。このあとWi-Fi(選択するだけ、パスワードは設定済み?)など少し設定を進めます。言語のダウンロードなどがなぜか失敗。とりあえず完了のようなのでsshで繋ぐのとCUIで起動するくらいに少し設定を触ってみたりで再起動。
# java うごかない openjdk-11-jdkが入っていてARMv7以降に対応していました。RaspberryPi Zero WはARMv6のようですよ。なぜ。

設定が終わればキーボードマウスは使わないのではずしてしまっても安全です。
というわけで、いろいろ設定できるものを探してみるところからまたはじめようかと思います。
Bluetoothが繋がるタイミングも調べてみないとわかりませんね。

Javaを探す

Raspberry Pi Zero Wではopenjdk11が入っていても動かないのでバージョンを下げる対策が必要なようです。

# java -version
Error occurred during initialization of VM
Server VM is only supported on ARMv7+ VFP
javaコマンドを叩いてみるも、JDKが動きません。 server VMがARMv7用だとか。
何が入っているのか探してみます。
# which java
コマンドの位置を調べるコマンド which
 /usr/bin/java
# dpkg -S /usr/bin/java
ファイルのパッケージを調べるコマンド dpkg
反応がない…リンクされているのでその先をたどります。
# ls -l /usr/bin/java
最終的にたどりついたのは /usr/lib/jvm/java-11-openjdk-armhf/bin/java のようです
# dpkg -S /usr/lib/jvm/java-11-openjdk-armhf/bin/java
openjdk-11-jre-headless というパッケージに当たったので消し去ります。
openjdk-10-jre-headlessやopenjdk-9-jre-headlessも入っていたら消します。
# apt-get remove openjdk-11-jre-headless
openjdkとopenjreが消えてくれます。
# apt-get install openjdk-8-jdk
openjdk 8をインストール
# java -version
openjdk version "1.8.0_212"
OpenJDK Runtime Environment (build 1.8.0_212-8u212-b01-1+rpi1-b01)
OpenJDK Client VM (build 25.212-b01, mixed mode)
動いてくれました。

ここまでくれば、あとはてきとーに楽しめます。

2019年7月21日日曜日

Ryzen 5 2600XでAndroid Studio のx86エミュレータを使えないWindows May 2019 Update

WindowsのAndroid StudioではAndroidのエミュレータが使えるのですが、x86版のエミュレータにはIntelのVT-xかAMDのSVMをUEFI(BIOS)上で有効にする必要があります。
今回はAMD Ryzen 5 2600xなので初回セットアップでVT-xつかえないよといわれ、UEFI上でSVMを有効にしてみました。OSのバグかなにかで失敗したのですが、いろいろ調べた挙げ句のメモです。
AndroidエミュレータがAMD CPUとHyper-V に対応した、というニュースのAMD CPUとHyper-Vは別々の話なので混ぜるな注意です。Hyper-VはAMD CPUにたいおうしていないっぽいたぶん。

Android Studioでエミュレータを動かす条件 3種類
  • Intel VT-x
  • AMD SVM
  • Microsoft Hyper-V
どれかが必要、ということらしいので今回はAMD SVMを有効にする方法

今回の前提

AMD Ryzen CPU
Windows 10 Pro April 2018 Update 以降 (Homeでも可?)
Windows 10 バージョン 1903 (OS ビルド 18362.239) (失敗するバージョン)
Android Studio 3.4.2 (3.2 Beta以降)
Avastかなにかのソフト使ってないこと

状態の確認

Windowsのバージョンを確認します。
スタートメニューを右クリックで「システム(Y)」を開き、Windowsの仕様というところにバージョンとOSビルドがあります。
コマンドプロンプトでwinver と入力してもバージョンが確認できます。
バージョン1903 (OS ビルド 18362.239) と出てくればバグ持ちなのでエミュレータは動きません。(注 : 7月末のKB4505903のアップデートでOS ビルド 18362.267になり修正されました)
エミュレータが実行可能なのは現状では1803と1809です。
Windows Insider Programで18932を使用するとエミュレータが利用可能という情報もありますが、元には戻せません。

AMD RyzenでAndroid x86エミュレータの利用可能状況(1803以降対応)
○ バージョン 1803 April 2018 Update
○ バージョン 1809 October 2018 Update
× バージョン 1903 May 2019 Update (OSビルド 18362.239)
○ バージョン 1903 May 2019 Update + KB4505903 (OSビルド 18362.267)
○ ビルド 18932

コマンドプロンプトで systeminfo
最初にOSのバージョンなど、最後にHyper-Vの要件が4つ出てきます。

systeminfoのHyper-Vの項目で、ファームウェアで仮想化が有効になっています : いいえ
となっていれば、UEFIの設定を変更します。
4つとも有効になっていればWindowsでハイパーバイザーを有効にします。
ハイパーバイザーが検出されました。と出てくればWindowsの設定も済んでいるのでAndroid Studioの方へ

UEFIの設定

仮想化技術はふつう使わないのでUEFIの初期設定でも無効化されていることが多いようです。
今回はASUSのTUF X470-PLUS GAMINGというマザーボードです。
Windowsを再起動させ、起動する前にdelete(DEL)キーでUEFIに入ります。キーボードもマウスも使えます。メニューを日本語にすることもできます。
UEFIの詳細設定の方を開き、CPUのSVMという項目をなんとなく見つけてEnabled にします。他の項目は触らなくてもいいですがてきとーに設定して保存して再起動します。

Windowsの設定

Windows 10では設定のメニューがコンパクトになってしまったのですたーとメニューから[Windows システムツール]→ [コントロールパネル]と開きます。[コントロールパネル > すべてのコントロールパネル項目] と開いていればOK。
[プログラムと機能]を開き、左の[Windowsの機能の有効化と無効化]までたどりつきます。
関連する項目は2つ
 [Hyper-V]のチェックをはずします。もともとはずれているはずです。
 [Windows ハイパーバイザー プラットフォーム]をチェックします。
Windowsの再起動をします。
systeminfo でHyper-Vの要件にハイパーバイザーが検出されました。と表示されていればWindowsまでの準備は終了のはずです。

Android Studo

ToolsからSDK ManagerとAVD Manager を開き、環境を整えます。

SDK Manager


[SDK Tools]の Intel x86 Emulator Accelerator (HAXM installer) はAMD Ryzenには不要なので入れてしまったら削除します。
Android Emulator、Android SDK Platform-Tools、Android SDK Toolsなどが入っていれば大丈夫なのかもしれません。

AVD Manager

VT-xが有効ではありません、などのエラーメッセージがでたら、Windowsハイパーバイザーの設定までがうまくいっていないので、もう一度UEFI、Windowsの設定を見直してください。
ここまでで起動しない…。
Windows バージョン1903 (May 2019 Update)はバグ持ちのようなので、次のアップデートまで待つしかないようです。(7月末 Updateで修正済み)

Hyper-Vだとどうなる 

Android エミュレータはHyper-Vにも対応しています。試してみましょうか。Hyper-V側をチェックし、ハイパーバイザーをはずして再起動します。Android StuidoではVT-xか何かがないよというメッセージが表示されるだけで使えませんでした。

参考
 窓の杜 https://forest.watch.impress.co.jp/docs/news/1132197.html
 Android StudioとAMD製CPU https://blog.misatowater.com/entry/tech/amd-androidstudio

2019年7月15日月曜日

MavenでTomcatにJAX-RSのせるだけ

TomcatにはJava EE 改め Jakarta EEのWeb系の機能しか載っていないので、その他のサービスを利用するにはwarの中に封じ込めてあげるのが楽です。
とりあえずJDK 12 + Apache NetBeans IDE 11.0の場合
Mavenで構築、Tomcatに公開する場合です。
GlassFishのJAX-RSライブラリを使います。

MavenでWebつくる
JAX-RS の機能でRESTfulなものを作る

Servlet相当のクラスをひとつ作り、タグだけつけます。Applicationというクラスを継承するようです。@ApplicationPath で公開パスを決めます。

package net.siisise.example.rest;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/api")
public class RestSetup extends Application {
}

次に機能のclassを作ります。
@の機能は推測どおりかと思うので GET /api/menu/hello に公開されます。

package net.siisise.example.rest;

@Path("/menu")
public class Mmmmm {
    @Path("/hello")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String exHelloName() {
        return "おはよう";
    }
}

そのまま公開してもTomcatではライブラリ等不足しています。

web.xml の編集。GlassFishサーバの設定をしていると、<dependencies> にjavaee-web-api があるかもしれません。
(Bloggerの都合上XMLタグは全角で囲んでいます。)

<dependencies>
   <dependency>
       <groupid>javax</groupid>
       <artifactid>javaee-web-api</artifactid>
       <version>7.0</version>
       <scope>provided</scope>
   </dependency>
</dependencies>
これはコメントアウトします。

<dependencies>

    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
        <version>2.29</version>
    </dependency>
    <dependency>
       <groupId>org.glassfish.jersey.inject</groupId>
       <artifactId>jersey-hk2</artifactId>
       <version>2.29</version>
    </dependency>
</dependencies>
とりあえずこのふたつがあれば動くようです。Servletを手動で設定する必要はありませんでした。
ビルドしてデプロイすれば /api/menu/hello で動いてくれます。
JAX-RS のMavenパッケージは jakarta.ws.rs-api というのに変わっていくっぽいです。

Web Application Description Language (WADL)

それから JAX-WS の SOAPにWSDL があるように、JAX-RSなRESTにはWADL というのがあるようで、これにはJAXBのライブラリも必要らしい。
仕様 https://www.w3.org/Submission/wadl/
<dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.4.0-b180830.0359</version>
</dependency>
<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
  <version>2.4.0-b180830.0438</version>
</dependency>
少し省略して書く。
 /api/application.wadl が表示されればOK、エラーなら何か見直し。