Friday, August 28, 2020

gogo shellコマンドを作ってみよう

 とたにです。

今回は実は色々な用途に使えるgogo shellコマンドの作り方を紹介したします。

※本記事はLiferay DXP 7.1を使用していますがバージョン7.0〜7.2でも(おそらく7.3も)問題なく動くと思います。

そもそもgogo shellとは

gogo shellコマンドの前にgogo shellとはなんでしょうか。LiferayはDXP(7.0)以降、アーキテクチャがOSGiベースに刷新されました。gogo shellはそのOSGiランタイムのコマンドラインシェルのことで、正しくはApache felix gogo shellといいます。
Liferayにも、このgogo shellを組み込まれているためgogo shellにアクセスしてさまざまな情報を取得したりOSGiバンドルの操作をしたりすることができます。

gogo shellへの接続方法

gogo shellへの接続方法は大きく2通りあります。
1つ目はLiferayのコントロールパネルからgogo shellにアクセスする方法です。
コントロールパネルの設定からGogo shellをクリックすると以下のようなGogo shellコマンドをWebページから入力できます。


2つ目は、telnetを使って接続する方法です。ただし7.1以降でtelnetを使って接続するためには以下の設定をportal-ext.propertiesに設定しておく必要があります。

 module.framework.properties.osgi.console=localhost:11311

この状態でLiferayを起動すると以下のようにtelnetからgogo shellに接続することができます。

$ telnet localhost 11311
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
____________________________
Welcome to Apache Felix Gogo

gogo shellではさまざまなコマンドが標準で用意され、主にOSGiバンドルの状態確認や調査、状態変更などが行えます。helpコマンドで使用できるコマンドの一覧を確認することができるので興味のある方は確認してみてください。

gogo shellコマンドの作成方法

gogo shellでは用意されたコマンドを使うだけではなく新しくコマンドを追加することができます。
今回は非常に簡単なコマンドを作成してみたいと思います。

step.1 Liferayモジュールプロジェクトの準備

Liferay IDEやbladeコマンドでLiferay workspaceとコマンドを追加するためのモジュールプロジェクトを作成します。プロジェクトの種類はシンプルでよいのでactivator等を選んでおくのが簡単かと思います。

今回はLiferayのサイト一覧とサイトメンバの一覧をコマンドで表示するコマンドを作ろうと思っているので、Liferayのサービスが呼び出せるようにbuild.gradleを以下のようにしておきます。
dependencies {
	compileOnly group: "org.osgi", name: "org.osgi.core"
	compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"
	compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"	
}

step.2 コマンドクラスの作成

package sample;

import com.liferay.portal.kernel.dao.orm.QueryUtil;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.model.Group;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.service.GroupLocalService;
import com.liferay.portal.kernel.service.UserLocalService;
import com.liferay.portal.kernel.util.PortalUtil;

import java.util.List;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;



@Component(
        property = {
                "osgi.command.function=listSites",
                "osgi.command.function=siteMembers",
                "osgi.command.scope=sample"
        },
        service = Object.class
)
public class SIteMemberCommand {

    public void listSites() {
    	List>group> sites = this.groupLocalService.getGroups(QueryUtil.ALL_POS, QueryUtil.ALL_POS);
    	
    	sites.stream().forEach(g -> System.out.println(g.getFriendlyURL()));
    	System.out.println("-- Total: " + sites.size());
    }
    
    public void siteMembers(String siteUrl) throws PortalException {
    	
    	Group g = this.groupLocalService.getFriendlyURLGroup(PortalUtil.getDefaultCompanyId(), siteUrl);
    	List>user> users = this.userLocalService.getGroupUsers(g.getGroupId());
    	
    	users.stream().forEach(u -> System.out.println(u.getScreenName() + ", " + u.getEmailAddress()));
    }
    
    @Reference
    private GroupLocalService groupLocalService;
    
    @Reference
    private UserLocalService userLocalService;
}
大した長さではないので、クラスのコードを全部はっています。

一番大切な部分は、クラスに付与されたアノテーションで、osgi.comand.functionとosgi.comnand.scopeプロパティの部分です。
osgi.command.functionはコマンドの名前と対応するメソッド名を定義しています。今回の例だとlistSitesと入力するとこのクラスのlsitSitesメソッドが実行されるようになります。
またosgi.command.functionは複数行記述することで複数のコマンドをひとつのクラスにまとめて定義することができます。

osgi.command.scopeはコマンドの名前空間でコマンド実行時には省略することもできますが、コマンド名が衝突しているケースで[スコープ名]:[コマンド名]のように入力することでコマンドを限定することができます。

コマンドの中身はLiferayの標準サービスを使って簡単な情報を出力しているだけなので詳細は省略しますが、コマンドを実行すると以下のように動きます。

  • listSitesコマンドはLiferay上のサイトのフレンドリURL一覧を出力します。
  • siteMembersコマンドはフレンドリURLを引数にとって、そのサイトの所属ユーザ一覧を出力します。

step.3 結果確認

モジュールをビルドしてLiferayにデプロイしたらコマンドの動作を確認してみましょう。

g! listSites  
/landing1
/landing2
...
/uitest
/personal_site
/template-35187
/template-35237
/template-33896
/template-20154
/template-33875
/template-33851
/template-33862
-- Total: 115

サイトテンプレートなどもサイトのひとつとして表示されていますが、いちおうサイトの一覧は取得できているようです。
次にsiteMembersもためしてみましょう。

g! siteMembers /contacttest
test, test@liferay.com

サイトメンバが1人しかいないですが、サイトのメンバーが表示されていることがわかります。

まとめ

Liferayのサービスと連携したgogo shellコマンドを作成しました。
gogo shellコマンドはこのようにLiferayのサービスやサービスビルダで作成したサービスを呼び出すことができるので、例えば初期データの登録やサービスレイヤーのテストなどさまざまな用途に活用することができます。
作成方法も簡単なのでぜひ活用してみてください。

Alfresco 201911GAで管理ツールからユーザ検索できない問題の解決方法

こんにちは。てらしたです。今回はAlfresco 201911GAのリリースノートにKnown Issuesとして記載されている、Shareの管理ツールからユーザ検索ができない問題の解決方法についてです。

リリースノートからもリンクが貼られているこちらのissueに問題の内容と解決方法が書いてあるので、その内容のご紹介になります。どうやらEnterprise版(有償版)のための機能のバグ修正の結果として生まれた新たなバグのようです。

解決方法の前に、まずは問題の内容を確認します。Alfrescoを起動し、Shareにadminでログインしてヘッダの「管理ツール」をクリックします。次に管理ツール画面で左メニューの「ユーザー」をクリックします。本来はこのページでユーザを検索できるはずですが、検索しても「アイテム読み込み時のエラー」というエラーメッセージが表示されて検索できません。ブラウザの開発ツールで確認してみると、people-enterpriseというapiにリクエストを投げて404が返ってきていることが原因のようです(Enterprise版用のAPIだから)。

上にリンクを貼ったissueによると、share-config.xmlでshow-authorization-statusというプロパティがtrueになっていることが原因のようなので、これをfalseにしてあげれば解決します。

Alfresco SDK 4.1で修正する場合

SDKを使って修正する場合(SDK4.1の開発環境構築についてはこちら)は、share-jarプロジェクトの [artifactId]-share/src/main/resources/META-INF/share-config-custom.xmlの<alfresco-config>タグの間の適当な場所に以下のコードを追記してリビルドすればOKです。

<config evaluator="string-compare" condition="Users" replace="true">
    <users>
        <!-- minimum length for username and password -->
        <username-min-length>2</username-min-length>
        <password-min-length>3</password-min-length>
        <show-authorization-status>false</show-authorization-status>
     </users>
     <!-- This enables/disables the Add External Users Panel on the Add Users page. -->
     <enable-external-users-panel>false</enable-external-users-panel>
</config>
  

Dockerfileで修正する場合

201911GAをdocker composeを使って試用している場合(やり方についてはこちら)でも、show-authorization-statusというプロパティを書き換えればいいだけなので方法はいろいろあると思いますが、手っ取り早く確認したいのであれば以下の方法が簡単なのではないかと思います。

docker-compose.ymlと同じディレクトリに以下の内容を記載したDockerfileを作成します。

FROM alfresco/alfresco-share:6.2.0

ARG TOMCAT_DIR=/usr/local/tomcat

# Patch for https://github.com/Alfresco/acs-community-packaging/issues/367
RUN sed -i 's@true@false@' \
	$TOMCAT_DIR/webapps/share/WEB-INF/classes/alfresco/share-config.xml

次に、docker-compose.ymlの以下の部分を

share:
    image: alfresco/alfresco-share:6.2.0
    mem_limit: 1g
        environment:
    ...

以下のように書き換えます。image名は既存のものと被らなければ何でもいいと思いますし、指定しなくても動くはずです。

share:
    image: custom-alfresco-share:development
    build:
        dockerfile: ./Dockerfile
        context: ./
    mem_limit: 1g
        environment:
    ...

修正した後に確認してみると、以下のようにユーザ検索が問題なく実行できると思います。

こんなことをしなくてもいいようにいずれ修正されるのではないかと思いますが、今のところはこのような方法で修正することが可能です。

Tuesday, August 25, 2020

Liferayテーブルを見てみよう〜サイト情報編

こんにちはナクラです。

前回はユーザの情報についてみましたが、
今回はサイトに関連する情報についてみていきましょう。
LiferayではいくつかのWebページをまとめてサイトを構成しています。
表示しているサイトに関する情報はコントロールパネルのサイトのセクションで確認できます。
サイトのセクションでは、サイトの所属するユーザの情報や、
サイト内のWebコンテンツやWiki、ドキュメントなどの情報を確認することができます。
特にサイト自体についての設定情報は
「設定」> 「サイトの設定」になります。

サイト設定では4つタブがあります。

・共通
・ソーシャル
・言語
・詳細設定

それぞれ見ていきましょう。


1.共通タブ

共通タブの画面はこのようになっています。


この画面の設定項目の大半はサイト情報のメインのデータであるGroup_テーブルに含まれている情報です。
(このテーブルも最後に"_"がついてます。)
サイトなのにGroup_という名前になっているので、注意してください。
実は、Group_テーブルには、この記事で取り扱っている"サイト"以外にも
いろいろな"サイト"的なものを登録するテーブルになっていて、
"サイト"自体は、Group_の一部という取扱いになっています。
Group_テーブルの定義は、前回でも確認しましたが、以下のようになっています。
Group_テーブル
+-------------------------------------+------------------+---------+---------+----------+-------+
| Field                                     | Type              | Null     | Key    | Default | Extra |
+-------------------------------------+------------------+---------+---------+----------+-------+
| mvccVersion                        | bigint(20)        | NO     |           | 0           |          |
| uuid_                                    | varchar(75)    | YES   | MUL   | NULL    |          |
| groupId                                 | bigint(20)       | NO     | PRI     | NULL   |          |
| companyId                           | bigint(20)        | YES  | MUL    | NULL   |          |
| creatorUserId                       | bigint(20)        | YES  |            | NULL   |          |
| classNameId                        | bigint(20)        | YES  | MUL    | NULL   |          |
| classPK                                | bigint(20)        | YES  |            | NULL   |          |
| parentGroupId                      | bigint(20)        | YES  |            | NULL    |         |
| liveGroupId                           | bigint(20)        | YES  | MUL   | NULL   |          |
| treePath                                | longtext          | YES  |            | NULL   |          |
| groupKey                              | varchar(150)  | YES  |            | NULL   |          |
| name                                     | longtext         | YES  |             | NULL   |         |
| description                            | longtext          | YES  |            | NULL    |         |
| type_                                     | int(11)            | YES  | MUL    | NULL    |         |
| typeSettings                          | longtext         | YES  |             | NULL    |         |
| manualMembership              | tinyint(4)        | YES  |             | NULL    |         |
| membershipRestriction         | int(11)            | YES  |            | NULL    |          |
| friendlyURL                           | varchar(255)  | YES  |            | NULL    |          |
| site                                        | tinyint(4)         | YES  |            | NULL    |          |
| remoteStagingGroupCount   | int(11)            | YES  |            | NULL    |          |
| inheritContent                        | tinyint(4)        | YES  |            | NULL    |          |
| active_                                   | tinyint(4)        | YES  |            | NULL    |          |
+--------------------------------------+------------------+-------+----------+-----------+--------+

さて、共通タブの項目とデータベースでの設定値との対応についてみていきましょう。

●詳細セクション
・サイトID:groupIdカラム
この値がサイトのプライマリキーになります。 
・説明: descriptionカラム
・メンバーシップタイプ:type_カラム
各設定に対応する値は下記のようになります。
公開
制限付き 2
非公開 3
・手動メンバーシップ管理を許可する:manualMembershipカラム
対応する値は
はい 1
いいえ 2
・親サイト:parentGroupIdカラム 
親サイトを指定した場合は親サイトのサイトID(groupIdカラムの値)が入ります。

●ページセクション

・公開ページ、非公開ページ
ページが存在する場合は、公開ページと非公開ページへのリンクが表示されます。
ページが存在しない場合は、サイトテンプレートを指定できるようになっていて、
それで保存すると、サイトテンプレートに従ってページが作成されます。
ページとサイトの関係については、後日詳しくみることにしましょう。

●カテゴリの設定セクション

・タグ
この設定値はAssetEntries_AssetTagsテーブルに登録されます。
入力したタグが生成されて、tagIdを割り当てらます。
サイトに対しては、アセットとしてみた場合のentryIdが割り当てられており、それを使ってタグとの関連情報が登録されます。
AssetEntries_AssetTagsテーブル
+---------------+-------------+------+-------+-----------+-------+
| Field           | Type        | Null | Key   | Default | Extra |
+---------------+-------------+------+-------+-----------+-------+
| companyId | bigint(20) | NO  | MUL | NULL    |          |
| entryId        | bigint(20) | NO  | PRI  | NULL    |          |
| tagId           | bigint(20) | NO  | PRI  | NULL    |          |
+---------------+-------------+------+-------+-----------+-------+
アセットの情報については
AssetEntryテーブルで確認できます。

●サイトURLセクション

・フレンドリURL:friendlyURLカラム
サイト作成時にはサイト名からfriendlyURLは自動生成されますが、
この設定で変更することができます。
・バーチャルホストの公開ページと非公開ページ
この設定値はVirtualHostテーブルに登録されます。
VirtualHostテーブル
+-----------------+------------------+-------+------+-----------+-------+
| Field             | Type              | Null  | Key  | Default | Extra |
+-----------------+------------------+-------+------+-----------+-------+
| mvccVersion | bigint(20)      | NO    |        | 0           |          |
| virtualHostId | bigint(20)       | NO   | PRI  | NULL    |         |
| companyId   | bigint(20)       | YES | MUL | NULL    |         |
| layoutSetId   | bigint(20)       | YES |         | NULL    |         |
| hostname     | varchar(200)  | YES | UNI  | NULL   |          |
+-----------------+------------------+-------+-------+----------+-------+
layoutSetIdカラムの値がサイトの公開ページセットのIDおよび非公開ページセットのIDになっており、
hostnameカラムに設定した値が登録されます。

以下の項目はいずれもtypeSettingsカラムで登録されます。
・ディレクトリのインデックスを有効にする
・このサイトでアセットの自動タグ付けを有効にする
・共有
それぞれの設定方法は次のとおりです。
directoryIndexingEnabled=false   
assetAutoTaggingEnabled=true
sharingEnabled=true 


2.ソーシャルタブ

ソーシャルタブの画面はこのようになっています。

●評価セクション

ここでは、サイトのコンテンツの評価方法を設定できます。
項目とデータベースの設定値との対応は以下の様になっています。
「高評価」:like
「スター(縦方向)」:stacked-stars
「スター」:stars
「評価」:thumbs
それぞれの設定情報は
Group_テーブルのtypeSettingsカラムに以下のようなに登録されます。
com.liferay.blogs.model.BlogsEntry_RatingsType=stars
com.liferay.document.library.kernel.model.DLFileEntry_RatingsType=thumbs
com.liferay.journal.model.JournalArticle_RatingsType=thumbs
com.liferay.knowledge.base.model.KBArticle_RatingsType=stacked-stars
com.liferay.message.boards.model.MBDiscussion_RatingsType=like
com.liferay.wiki.model.WikiPage_RatingsType=thumbs

●コメントセクション

・他ユーザーへのメンションを許可する。
これの設定も、typeSettingsカラムで下記のように登録されます。
mentionsEnabled=true


3.言語タブ

言語タブの画面はこのようになっています。

ここでは、サイトのデフォルト言語と切り替え可能な言語を設定できます。
「デフォルト言語オプションを使用します」のラジオボタンが選択されている場合は、
インスタンス設定の"ローカライズ"で設定されている項目が引き継がれます。
「このサイトでのデフォルトの言語と指定可能な言語を定義してください」にラジオボタンを変更すると
デフォルト言語と選択可能が言語の設定が行えます。
ここの部分の設定情報でデータベースでは、
Group_テーブルのtypeSettingsカラムに登録されます。
まず、ラジオボタンの情報が
inheritLocales=true
のような形で設定されています。
「デフォルト言語オプションを使用します」を選択している場合は true
「このサイトでのデフォルトの言語と指定可能な言語を定義してください」を選択している場合は false
になります。
デフォルトの言語は
languageId=en_US
利用可能な言語は
locales=en_US,nl_NL,ja_JP
のように登録されています。
ただし、この設定情報は「デフォルト言語オプションを使用します」を選択すると
初期設定に戻ってしまうのでラジオボタンを戻したときにまた、一から選択しなおす必要があるので注意してください。


4.詳細設定タブ

詳細設定タブの画面はこのようになっています。

このタブの設定項目は全てtypeSettingsカラムに登録されます。
項目と登録方法を一緒に確認していきましょう。

●デフォルトの関連付けセクション

・サイトロール」
defaultSiteRoleIds=34520
・チーム
defaultTeamIds=37534

●分析セクション

・Google アナリティクスID
googleAnalyticsId=XXXXXX
・Piwik
analytics_piwik=XXXXXXX

●地図セクション

・OpenStreetMap
MAP_PROVIDER_KEY=OpenStreetMap
・Google マップおよび「Google Maps API キー (オプション)」
MAP_PROVIDER_KEY=GoogleMaps
googleMapsAPIKey=XXXXXXXX
ラジオボタンでの設定なので
MAP_PROVIDER_KEYはどちらか一方が登録されます。

●ゴミ箱セクション

・ゴミ箱を有効にする
trashEnabled=true
・ゴミ箱内エントリーの最大保存日数
trashEntriesMaxAge=43200

●コンテンツセクション

・このサイトから子サイトの内容を表示できるようにする。
contentSharingWithChildrenEnabled=-1
値については以下のようになっています。
デフォルト値(有効):-1
有効:3
無効:0

まとめ

今回はサイト設定の項目とデータベースとの対応を確認しました。
サイトの情報は比較的Group_テーブルにまとまって登録されています。
特にtypeSettingsカラムに、サイトに固有のさまざまな設定値が登録されます。
また、一部はAssetEntries_AssetTagsテーブルやVirtualHostテーブルにも登録されているデータがありました。

それではまた、次回は別の設定項目を見ていきたいと思います。




Monday, August 24, 2020

Alfresco SDK 4.1を使って開発環境を構築する

こんにちは。てらしたです。 今回は現時点(2020年8月)での最新のSDKである4.1を使って、Alfrescoをカスタマイズするための開発環境を構築する手順をご紹介します。

以前のSDK 3.xとは、動作確認用のAlfrescoがDockerコンテナとして起動するようになっている点が大きく異なっています。これによって、本番環境でもコンテナを使う場合は、開発環境との環境差異に起因する問題が従来より少なくなることが期待できるかもしれません。

開発環境の構築手順については3.xの時と基本的には同じです。以下のドキュメントに沿って1つずつ手順をご説明していきます。
Getting started with Alfresco SDK 4.1

準備

開発用のプロジェクトを作るためには、JDK11、Maven、DockerおよびDocker Composeのインストール/設定が必要です。

まずJDK11をインストールし、環境変数JAVA_HOMEを適切に設定します。インストールと設定が終わったら以下のコマンドで確認します。

java -version
echo $JAVA_HOME

Mavenをインストールします(バージョンは3.3以上)。こちらも以下のコマンドでバージョンを確認します。

mvn -v

Dockerをインストールします。Docker ComposeがDockerのインストール時に一緒にインストールされていない場合は個別にインストールします。終わったら以下のコマンドで確認します。

docker -v
docker-compose -v

プロジェクトの作成

準備が整ったので、適当なディレクトリに移動し、以下のコマンドを実行してMaven Archetypeからプロジェクトを作成します。

mvn archetype:generate -Dfilter=org.alfresco:

ここからは対話形式で設定していきます。どのarchetypeを使用するか聞かれるので、

  • alfresco-allinone-archetype
  • alfresco-platform-jar-archetype
  • alfresco-share-jar-archetype
の3つ(以下の2, 4, 5)のいずれかを選択します。
Choose archetype:
1: remote -> org.alfresco.maven.archetype:activiti-jar-archetype (DEPRECATED - UNSUPPORTED - EXPERIMENTAL)
2: remote -> org.alfresco.maven.archetype:alfresco-allinone-archetype (Sample multi-module project for All-in-One development on the Alfresco platform. Includes modules for Platform/Repository JAR and Share JAR)
3: remote -> org.alfresco.maven.archetype:alfresco-amp-archetype (Sample project with full support for lifecycle and rapid development of Repository AMPs (Alfresco Module Packages))
4: remote -> org.alfresco.maven.archetype:alfresco-platform-jar-archetype (Sample project with full support for lifecycle and rapid development of Platform/Repository JARs and AMPs (Alfresco Module Packages))
5: remote -> org.alfresco.maven.archetype:alfresco-share-jar-archetype (Share project with full support for lifecycle and rapid development of JARs and AMPs (Alfresco Module Packages))
6: remote -> org.alfresco.maven.archetype:share-amp-archetype (Share project with full support for lifecycle and rapid development of AMPs (Alfresco Module Packages))
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 

Alfresco Platformのみカスタマイズする場合は4. alfresco-platform-jar-archetype、Shareのみカスタマイズする場合は5. alfresco-share-jar-archetype、両方の場合は2. alfresco-allinone-archetypeを選べばよいと思います。

次に、どのバージョンを使用するか聞かれるので4.1.0を選択します(デフォルトで選択されているはずなのでEnterを押すだけでOKです)。

Choose org.alfresco.maven.archetype:alfresco-allinone-archetype version: 
1: 2.0.0-beta-1
2: 2.0.0-beta-2
3: 2.0.0-beta-3
4: 2.0.0-beta-4
5: 2.0.0
6: 2.1.0
7: 2.1.1
8: 2.2.0
9: 3.0.0
10: 3.0.1
11: 3.1.0
12: 4.0.0-beta-1
13: 4.0.0
14: 4.1.0
Choose a number: 14:

最後に、groupIdやartifactIdといった情報の入力を求められるので適当に入力します。ここで入力したartifactIdが、プロジェクトのディレクトリ名やビルド時に作成されるJARファイルのファイル名として使用されます。

Define value for property 'groupId': jp.aegif
Define value for property 'artifactId': alfresco-allinone-test
[INFO] Using property: version = 1.0-SNAPSHOT
Define value for property 'package' jp.aegif: : jp.aegif.alfresco

入力内容が合っているか聞かれるので、問題なければYを入力します(何も入力せずEnterでも同じです)。Y以外を入力するとgroupIdの入力からやり直すことができます。archetypeの選択からやり直したい場合はCtrl+Cで終了して最初からやり直せば大丈夫です。

Confirm properties configuration:
groupId: jp.aegif
artifactId: alfresco-allinone-test
version: 1.0-SNAPSHOT
package: jp.aegif.alfresco
 Y: :

「BUILD SUCCESS」と表示されたらプロジェクト作成完了です。

Buildして起動

最初にmvnコマンドを実行したディレクトリにartifactIdと同名のディレクトリ(ここではalfresco-allinone-test)が作成されているはずなのでそのディレクトリに移動します。

cd alfresco-allinone-test

このディレクトリで、LinuxやMacでは

./run.sh build_start

Windowsでは

run.bat build_start

を実行すると、カスタマイズが適用されたAlfresco(厳密に言うとAlfrescoを動かすために必要なコンテナ群)が起動します。

デフォルトではホスト側のポート8080がAlfresco Platform、8180がShareに割り当てられるので、Shareにアクセスするためには http://localhost:8180/share を開く必要がある点にご注意ください。使用するポートを変更したい場合もあると思うので、その方法については下の方でご説明します。

停止したい場合はCtrl+Cでログ出力を中止して、

./run.sh stop

または

 run.bat stop

で停止できます。

run.shやrun.batを見ていただけるとわかるように、build_startやstop以外にもいくつかコマンドが用意されています。PlatformやShareだけを再起動するreload_acsやreload_shareは実際に開発する際に使用頻度が高そうです。

また、作成されたPlatformやShareのプロジェクトは空ではなく、それぞれサンプルの設定ファイル等が入っているので、どこにどういうファイルを置けば変更が反映されるのか確認しやすいようになっています。カスタマイズが思ったように反映されないという時にはサンプルを参考にしてみると解決するかもしれません。

バージョンの変更

Alfrescoのバージョンを201911GAに合わせるには、run.shやrun.batがあるディレクトリのpom.xmlで以下のようにplatformのバージョンを6.2.0-gaに、shareのバージョンを6.2.0に設定してください(デフォルトではplatformが6.2.0-eaになっているはずです)。

<alfresco.platform.version>6.2.0-ga</alfresco.platform.version>
<alfresco.share.version>6.2.0</alfresco.share.version>

後で説明しますと上に書いたポートの変更方法ですが、このpom.xmlの以下の部分を書き換えると変更できます。

<share.port>8180</share.port>
...
<acs.port>8080</acs.port>

pom.xmlを変更したら、以下のコマンドでbuildし直せば完了です(run.batの方は省略)。

  ./run.sh stop
  ./run.sh purge
  ./run.sh build_start

不要なDockerイメージの掃除

最後に注意点として、このSDK4.1ではbuildする度にDockerのimageを作るので、何度もbuildしていると以下のようにdanglingなimageが大量にできてしまいます。これらのimageを使うことはないと思うので定期的に掃除した方が良さそうです。

REPOSITORY                                          TAG                 IMAGE ID            CREATED             SIZE
alfresco-content-services-alfresco-allinone-test    development         3182d8b5ebad        45 minutes ago      1.43GB
alfresco-share-alfresco-allinone-test               development         dc21bb791a51        45 minutes ago      786MB
<none>                                              <none>              51fe77a145c1        49 minutes ago      1.43GB
<none>                                              <none>              6cc266a96034        49 minutes ago      786MB
<none>                                              <none>              82290779e1a0        59 minutes ago      1.43GB
<none>                                              <none>              20aab698f49a        59 minutes ago      786MB
...

以上、SDK4.1を使用した開発環境の作り方をご紹介しました。作成したプロジェクトをEclipseやInteliJ IDEAといったIDEにインポートして開発したい場合は以下のドキュメントを参考に設定していただければと思います。
Setting up your development environment using Eclipse
Setting up your development environment using Intellij IDEA

Thursday, August 20, 2020

CentOS7にApache (httpd)の最新版2.4.43をインストールする(IUSリポジトリURLが変わってて若干はまった話)

 こんにちは。おおたにです。


今回はCentOS7にApache HTTP Server (httpd)の最新版をインストールする方法を備忘代わりに書いておこうと思います。

CentOS7向けのhttpdについては、CentOSのBaseリポジトリで公開されているバージョンが2.4.6と古いため、IUSリポジトリからインストールすることが一般的です。

最記事執筆時点ではIUSリポジトリで公開されているバージョンが2.4.43、Apache公式の最新版は2.4.46です。IUSリポジトリで公開されているよりも新しいバージョンが欲しい場合はソースコードからビルドする必要があります。

インストールされている古いhttpdの削除

2.4.6等の古いhttpdがインストールされている場合はアンインストールしましょう。

まず、起動しているhttpdを停止し、systemdへのサービス登録を解除します。

systemctl stop httpd
systemctl disable httpd.service

次に、httpdをアンインストールします。

yum remove httpd
yum remove httpd-tools

yumリポジトリの追加

必要なソフトウェアを入手するために、yumリポジトリEPELとIUSを追加します。

yum -y install epel-release
vi /etc/yum.repos.d/epel.repo
  ([epel]のenabledを0に変更する)
yum -y install https://repo.ius.io/ius-release-el7.rpm
vi /etc/yum.repos.d/ius.repo
  ([ius]のenabledを0に変更する)

これらのリポジトリをデフォルトで無効にしておくためにenabled=0に変更しています。なお、記事によってはIUSのURLがhttps://centos7.iuscommunity.org/ius-release.rpmとなっていますが、これは古いURLなので追加しようとするとエラーが出て失敗します(比較的最近リポジトリURLが変わったようです)。

依存ライブラリとhttpdのインストール

では必要なソフトウェアをインストールしてきましょう。

yum -y install centos-logos.noarch mailcap openldap-devel expat-devel libdb-devel openssl perl
yum --enablerepo=epel -y install nghttp2 brotli
yum --disablerepo=base,extras,updates --enablerepo=ius -y install httpd httpd-devel mod_ssl

以上で必要なソフトウェアがインストールされました。依存ライブラリが足りないよと言われた場合は適宜インストールしてください。

サービス登録と動作確認

最後にsystemdへのサービス登録を行いhttpdを起動します。

systemctl enable httpd.service
systemctl start httpd

start実行時にエラーが出ず、ブラウザでアクセスして It works! と表示されればインストール成功です!yumでインストールした時の設定ファイルのありかは以下のとおりですので参考にしてください。

  • /etc/httpd/conf/httpd.conf : httpd設定
  • /etc/httpd/conf.d/ssl.conf : httpd設定
  • /etc/logrotate.d/httpd : ログローテーション設定

Friday, August 7, 2020

Liferay 7とGoogle Drive / Google Docsを連携させる

こんにちは。おおたにです。

昨今のクラウドサービスの浸透に加えてコロナ禍もあり、オンラインストレージサービスやオンラインオフィスソフトウェアも一般的と言っていいまでに普及しているかと思います。今回は、これらのサービスの代表格であるGoogle Drive / Google DocsとLiferayの連携について紹介します。

Liferayはドキュメントライブラリと呼ばれるファイル管理の機能を持っています。Google Drive / Google Docs連携はドキュメントライブラリとの連携を行うもので、以下の2種類の連携があります。
  • ドキュメントライブラリ上にGoogle Driveのファイルのリンクを作成する
  • ドキュメントライブラリ上のファイルをGoogle Docsを使ってブラウザ上で編集する(=オンライン編集)
1つ目の連携はLiferay MarketplaceのアプリLiferay Plugin for Google Driveで実現できます。詳しい説明はGoogle Driveへのリンクを参照してください。

2つ目の連携はLiferay DXP 7.2で追加された新機能になります。本記事ではこちらの機能の詳細と設定方法を説明します。なお、同様の機能を提供するOffice 365連携も新機能として追加されましたが、こちらは別の機会に紹介したいと思います。

新しいGoogle Drive/Google Docs連携機能の紹介


前述のとおり、ドキュメントライブラリ上のファイルをGoogle Docsを使ってブラウザ上で編集することができます。具体的にできることは以下のとおりです。
  • Google Docsを使い、新規ファイル(Doc, Slide, Sheet)をブラウザ上で作成する
  • 作成したファイルをMS Office形式(Word, PowerPoint, Excel)でドキュメントライブラリに保存する
  • ドキュメントライブラリ上のMS Office形式のファイルをGoogle Docsを使ってブラウザ上で編集する
なお、Google Docsでファイル編集を開始するとGoogle Drive上にファイルがコピーされ、Google Docsでの編集を終えてファイルをLiferayに保存するとGoogle Drive上のファイルは削除されます。詳しい説明はLiferayヘルプセンターのこちらの記事こちらの記事を参照してください。

Google Cloud Platformの連携設定を行う


次に、設定方法を紹介します。Google側とLiferay側の両方に設定が必要ですが、まずはGoogle側の設定を行います。具体的には、Google Drive APIをLiferayが利用できるように有効化し、Liferay向けにOAuth2.0クライアントIDを発行します。

1. Google Cloud Platform Consoleにアクセスし、管理ユーザでログインする
2. 適当なプロジェクトを選択する。もしくは新しいプロジェクトを作成する
3. 「APIとサービス」に移動し、「APIとサービスの有効化」をクリックする
4. Google Drive APIを検索し、「有効にする」をクリックして有効化する
5. 「APIとサービス」の「OAuth同意画面」に移動して同意画面を設定する(最低限アプリケーション名を入力すればOK)
6. 「APIとサービス」の「認証情報」に移動する
7. 「認証情報を作成」の「OAuthクライアントID」をクリックする
8. 以下のとおり入力して「作成」をクリックする
  • アプリケーションの種類 : ウェブアプリケーション
  • 名前 : アプリケーション名を入力する(認証時に表示されます)
  • 承認済みの JavaScript 生成元URI : LiferayサーバのURL(http://<host or IP>:<port>)
  • 承認済みのリダイレクトURI : http(s)://<host or IP>:<port>/o/document_library/google/oauth2
9. クライアントIDとクライアントシークレットが表示されるので、それらを手元に控える

以上でGoogle側の設定は完了です。

Liferayの設定を行う


続いて、Liferay側の設定を行います。

1. Liferay DXP 7.2に管理者でログインする
2. 「Control Panel」->「Configuration」->「Instance Settings」->「Documents and Media」をクリックする(この場合、インスタンス毎の設定になります。グローバルに設定する場合は「System Settings」->「Documents and Media」をクリックします)
3. 「Google Drive」を選択し、Client IDとClient Secretに先ほど控えたクライアントIDとクライアントシークレットを入力して「Save」をクリックする

以上です。とても簡単ですね!

動作確認してみよう


では早速動作確認してみましょう。ドキュメントとメディア(管理者向けでもページ上に配置されたユーザ向けポートレットでもOK)で新規作成メニューをクリックすると、Google Doc、Google Slide、Google Sheetが表示されるようになります。
これらをクリックするとGoogleアカウントの認証画面に遷移するので認証情報を入力します。初回はアクセス許可を行う必要があり、それが完了するとLiferayユーザとGoogleアカウントが紐づき、次回からは聞かれないようになります。そして、Google Drive上にファイルが生成されGoogle Docsでオンライン編集できるようになります。
「Save and Return to Liferay DXP」をクリックするとGoogle Drive上のファイルをLiferayに保存し、Liferayの画面に戻ります(この時Google Drive上のファイルは削除されます)。アクションメニューの「Edit in Google Docs」をクリックすると、Google DriveにファイルをコピーしてGoogle Docsでのオンライン編集が始まります。

今回の紹介は以上です。簡単な設定でGoogle Drive / Google Docsを使ったファイルのオンライン編集が実現できますので、是非みなさまも試してみてください。

Monday, August 3, 2020

Alfresco 201911GAをzipからインストールしてみよう【その3】

こんにちは。たなかです。

ステイホーム中に家の片付けをして粗大ゴミを出したり達成感はあるのに、階段下収納に力を入れてしまったせいで見た目のごっちゃり感が変わらない現実から目を背けている今日この頃です。

前回SolrをインストールしてAlfrescoを起動するところまで紹介したので、今回はAlfresco CE 201911GAをzipからインストールしてみようの最終回としてLibreOfficeやImageMagick等のインストールをご紹介します。
環境等については第1回の記事をご覧いただけたらと思います。

先にLibreOffice_6.3.6_Linux_x86-64_rpm.tar.gzを公式サイトからダウンロードしておきます。

LibreOfficeのインストール


Alfresco CEでは、MS Officeのファイルの変換をしたり、テキストファイルをPDFファイルに変換するなどドキュメントの形式を変換したりすることができます。
それらの機能を使用するためにもLibreOfficeを連携する必要があります。

ダウンロードしておいたLibreOffice_6.3.6_Linux_x86-64_rpm.tar.gzを作業用ディレクトリに配置し、展開してインストールする
cd [作業用ディレクトリ]
tar xzvf LibreOffice_6.3.6_Linux_x86-64_rpm.tar.gz
cd LibreOffice_6.3.6.2_Linux_x86-64_rpm/RPMS/

yum localinstall *rpm
cd /opt/alfresco
rm -rf LibreOffice_6.3.6.2_Linux_x86-64_rpm

※ 実体は以下にインストールされています
/opt/libreoffice6.3/program/soffice

alfresco-global.properties を編集して保存する
vim tomcat/shared/classes/alfresco-global.properties
以下のように変更する
jodconverter.officeHome=/opt/libreoffice6.3
jodconverter.portNumbers=8101
jodconverter.enabled=true 

ImageMagickのインストール


ImageMagickはサムネイルやプレビュー画像用の画像操作等に使用されており、有効にするためにはインストールと設定が必要になります。
alfresco-global.propertiesを変更することでAlfrescoと連携することができます。

依存性解決のためにEPELリポジトリを追加し、ImageMagickをインストールする
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

yum install https://imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-7.0.10-24.x86_64.rpm https://imagemagick.org/download/linux/CentOS/x86_64/ImageMagick-libs-7.0.10-24.x86_64.rpm

alfresco-global.properties を編集して保存する
vim tomcat/shared/classes/alfresco-global.properties
以下を追記する
img.exe=/bin/convert
PDFファイル等を準備して、以下のようなコマンドでテストをすることも可能です。
convert test.pdf test.png

alfresco-pdf-rendererのインストール


alfresco-pdf-rendererは、ドキュメントのサムネイルとプレビューを作成するため等に使用されています。
alfresco-global.propertiesを変更することでAlfrescoと連携することができます。
alfresco-pdf-rendererは、Alfrescoのzipファイルから入手できるため今回はAlfrescoインストール時に展開したものを使用しています。

alfresco-pdf-rendererを展開する
cd /opt/alfresco
tar xzvf /[作業ディレクトリ]/alfresco-content-services-community-distribution-6.2.0-ga/alfresco-pdf-renderer/alfresco-pdf-renderer-1.1-linux.tgz

alfresco-global.properties を編集して保存する
vim tomcat/shared/classes/alfresco-global.properties
以下を追記する
alfresco-pdf-renderer.root=/opt/alfresco
alfresco-pdf-renderer.exe=${alfresco-pdf-renderer.root}/alfresco-pdf-renderer 
Alfrescoインストール時にfalseにしておいた以下の設定をtrueに変更する
legacy.transform.service.enabled=true
以上で『Alfresco 201911GAをzipからインストールしてみよう』完結です。
ご覧いただきありがとうございました。