LoginSignup
0
0

Open Liberty+ReactでWEBアプリを作ってみる

Posted at

Open Libertyの公式ページにある以下サンプルを使用して、Webアプリを作成してみましょう。
https://openliberty.io/guides/rest-client-reactjs.html

Open Libertyってなに?

  • 高速で効率的なクラウドネイティブJavaマイクロサービスを構築するための軽量なオープンフレームワークです。
  • 要するにJava製のアプリケーションサーバーです。
  • Open Liberty 公式ページ:https://openliberty.io/

環境

  • Windows11 + WSL2(Ubuntu 20.04.5)
  • Mavenインストール済み
  • ブラウザはEdge
  • node v16.13.2
  • openjdk 17.0.8

リポジトリのクローンと完成品の確認

リポジトリをクローンし、ディレクトリを移動します。

git clone https://github.com/openliberty/guide-rest-client-reactjs.git
cd guide-rest-client-reactjs

中にはfinishとstartという2つのディレクトリが含まれており、finishの方にサンプルの完成品が格納されています。
finishディレクトリに移動し、完成品を確認してみましょう。

cd finish
mvn liberty:run

ブラウザでhttp://localhost:9080/を開くと、以下のような画面を見ることができます。

react-table.png

未完成のWebアプリを実行してみる

startディレクトリに移動し、mvn liberty:devコマンドを実行してみます。今回はブラウザでhttp://localhost:9080/を開いても真っ白なページしか表示されません。http://localhost:9080/artistsにアクセスすると、jsonが返却されます。

image.png

http://localhost:9080/artistsからjsonデータを受け取り、Reactで表示できるようにする必要がありそうです。

React部分の実装

まず、index.jsを作成します。このファイルはreactアプリのエントリーポイントになります。

src/main/frontend/src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './Styles/index.css';
import App from './Components/App';

ReactDOM.render(<App />, document.getElementById('root'));

さらに、以下のようにApp.jsファイルを作成します。

src/main/frontend/src/Components/App.js
import React from 'react';
import {ArtistTable} from './ArtistTable';

function App() {
  return (
      <ArtistTable/>
  );
}

export default App;

ArtistTable.jsを作成します。このコンポーネントでテーブルを作成します。

src/main/frontend/src/Components/ArtistTable.js
import React, { useEffect, useMemo, useState } from 'react';
import { useTable, usePagination, useSortBy } from 'react-table';
import '../Styles/table.css'

export function ArtistTable() {

  const [posts, setPosts] = useState([]);


  const data = useMemo(() => [...posts], [posts]);

  const columns = useMemo(() => [{
    Header: 'Artist Info',
    columns: [
      {
        Header: 'Artist ID',
        accessor: 'id'
      },
      {
        Header: 'Artist Name',
        accessor: 'name'
      },
      {
        Header: 'Genres',
        accessor: 'genres',
      }
    ]
  },
  {
    Header: 'Albums',
    columns: [
      {
        Header: 'Number of Tracks',
        accessor: 'ntracks',
      },
      {
        Header: 'Title',
        accessor: 'title',
      }
    ]
  }
  ], []
  );

  const tableInstance = useTable(
    {
      columns,
      data,
      initialState: { pageIndex: 0, pageSize: 4 }
    },
    useSortBy,
    usePagination
  )

  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,
    page,
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: { pageIndex, pageSize }
  } = tableInstance;


  return (
    <>
      <h2>Artist Web Service</h2>
      <table {...getTableProps()}>
        <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map((column) => (
                <th {...column.getHeaderProps(column.getSortByToggleProps())}>
                  {column.render('Header')}
                  <span>
                    {column.isSorted
                      ? column.isSortedDesc
                        ? ' 🔽'
                        : ' 🔼'
                      : ''}
                  </span>
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {page.map((row, i) => {
            prepareRow(row)
            return (
              <tr {...row.getRowProps()}>
                {row.cells.map(cell => {
                  return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                })}
              </tr>
            )
          })}
        </tbody>
      </table>
      <div className="pagination">
        <button onClick={() => previousPage()} disabled={!canPreviousPage}>
          {'Previous'}
        </button>{' '}
        <div class="page-info">
          <span>
            Page{' '}
            <strong>
              {pageIndex + 1} of {pageOptions.length}
            </strong>{' '}
          </span>
          <span>
            | Go to page:{' '}
            <input
              type="number"
              defaultValue={pageIndex + 1}
              onChange={e => {
                const page = e.target.value ? Number(e.target.value) - 1 : 0
                gotoPage(page)
              }}
              style={{ width: '100px' }}
            />
          </span>{' '}
          <select
            value={pageSize}
            onChange={e => {
              setPageSize(Number(e.target.value))
            }}
          >
            {[4, 5, 6, 9].map(pageSize => (
              <option key={pageSize} value={pageSize}>
                Show {pageSize}
              </option>
            ))}
          </select>
        </div>
        <button onClick={() => nextPage()} disabled={!canNextPage}>
          {'Next'}
        </button>{' '}
      </div>
    </>
  );
}

上記のままでは、jsonデータを受け取ることができません。そこで、以下のようにaxiosのインポートとGetArtistsInfo関数を追加します。GetArtistsInfo関数では、axiosでhttp://localhost:9080/artistsからデータを受け取っています。

src/main/frontend/src/Components/ArtistTable.js

import React, { useEffect, useMemo, useState } from 'react';
import axios from 'axios';
import { useTable, usePagination, useSortBy } from 'react-table';
import '../Styles/table.css'

export function ArtistTable() {

  const [posts, setPosts] = useState([]);

  const GetArtistsInfo = async () => {
    const response = await axios.get('http://localhost:9080/artists')
      .then(response => {
        const artists = response.data;
        for (const artist of artists) {
          const { albums, ...rest } = artist;
          for (const album of albums) {
            setPosts([...posts, { ...rest, ...album }]);
            posts.push({ ...rest, ...album });
          }
        };
      }).catch(error => { console.log(error); });
  };
  const data = useMemo(() => [...posts], [posts]);

  const columns = useMemo(() => [{
    Header: 'Artist Info',
    columns: [
      {
        Header: 'Artist ID',
        accessor: 'id'
      },

// 以下省略・・・・・

以上がすべて終わったら、startディレクトリに戻り、以下コマンドを実行します。このコマンドでビルドが走ります。

mvn process-resources

http://localhost:9080 にアクセスしてみましょう。以下のような画面が表示されます。

image.png

まとめ

Open LibertyとReactを利用して、簡単なWebサービスを実装できました。みなさんも試してみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0