Unable to find CDI BeanManager.となったときの対応方法

# 事象 : JSFのプロジェクトをPayaraで起動したらエラーが表示された

```text:エラーログのメッセージ
cannot Deploy tryJsf
deploy is failing=Error occurred during deployment: Exception while loading the app : java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: javax.faces.FacesException: Unable to find CDI BeanManager. Please see server.log for more details.]
```

```log:server.log
[2020-07-20T21:13:22.486+0900] [Payara 5.194] [重大] [] [javax.enterprise.resource.webcontainer.jsf.config] [tid: _ThreadID=49 _ThreadName=admin-thread-pool::admin-listener(1)] [timeMillis: 1595247202486] [levelValue: 1000] [[
  Critical error during deployment: 
javax.faces.FacesException: Unable to find CDI BeanManager
    at com.sun.faces.el.ELUtils.tryAddCDIELResolver(ELUtils.java:288)
    at com.sun.faces.el.ELUtils.buildFacesResolver(ELUtils.java:218)
    at com.sun.faces.application.ApplicationAssociate.initializeELResolverChains(ApplicationAssociate.java:467)
...省略...
]]

[2020-07-20T21:13:22.490+0900] [Payara 5.194] [重大] [AS-WEB-CORE-00174] [javax.enterprise.web.core] [tid: _ThreadID=49 _ThreadName=admin-thread-pool::admin-listener(1)] [timeMillis: 1595247202490] [levelValue: 1000] [[
  Startup of context /tryJsf failed due to previous errors]]

[2020-07-20T21:13:22.492+0900] [Payara 5.194] [重大] [AS-WEB-CORE-00175] [javax.enterprise.web.core] [tid: _ThreadID=49 _ThreadName=admin-thread-pool::admin-listener(1)] [timeMillis: 1595247202492] [levelValue: 1000] [[
  Exception during cleanup after start failed
org.apache.catalina.LifecycleException: Manager has not yet been started
    at org.apache.catalina.session.StandardManager.stop(StandardManager.java:868)
    at org.apache.catalina.core.StandardContext.stop(StandardContext.java:5940)
    at com.sun.enterprise.web.WebModule.stop(WebModule.java:648)
...省略...
]]

[2020-07-20T21:13:22.493+0900] [Payara 5.194] [重大] [AS-WEB-CORE-00108] [javax.enterprise.web.core] [tid: _ThreadID=49 _ThreadName=admin-thread-pool::admin-listener(1)] [timeMillis: 1595247202493] [levelValue: 1000] [[
  ContainerBase.addChild: start: 
org.apache.catalina.LifecycleException: java.lang.RuntimeException: javax.faces.FacesException: Unable to find CDI BeanManager
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:5760)
    at com.sun.enterprise.web.WebModule.start(WebModule.java:619)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:956)
...省略...
Caused by: java.lang.RuntimeException: javax.faces.FacesException: Unable to find CDI BeanManager
    at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:283)
    at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:5165)
...省略...
Caused by: javax.faces.FacesException: Unable to find CDI BeanManager
    at com.sun.faces.el.ELUtils.tryAddCDIELResolver(ELUtils.java:288)
    at com.sun.faces.el.ELUtils.buildFacesResolver(ELUtils.java:218)
...省略...
]]

[2020-07-20T21:13:22.495+0900] [Payara 5.194] [警告] [] [javax.enterprise.web] [tid: _ThreadID=49 _ThreadName=admin-thread-pool::admin-listener(1)] [timeMillis: 1595247202495] [levelValue: 900] [[
  java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: javax.faces.FacesException: Unable to find CDI BeanManager
java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: javax.faces.FacesException: Unable to find CDI BeanManager
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:960)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:939)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:684)
...省略...
]]

[2020-07-20T21:13:22.504+0900] [Payara 5.194] [重大] [] [javax.enterprise.system.tools.deployment.common] [tid: _ThreadID=49 _ThreadName=admin-thread-pool::admin-listener(1)] [timeMillis: 1595247202504] [levelValue: 1000] [[
  Exception while invoking class com.sun.enterprise.web.WebApplication start method
java.lang.Exception: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: javax.faces.FacesException: Unable to find CDI BeanManager
    at com.sun.enterprise.web.WebApplication.start(WebApplication.java:136)
    at org.glassfish.internal.data.EngineRef.start(EngineRef.java:123)
...省略...
]]

[2020-07-20T21:13:22.505+0900] [Payara 5.194] [重大] [NCLS-CORE-00026] [javax.enterprise.system.core] [tid: _ThreadID=49 _ThreadName=admin-thread-pool::admin-listener(1)] [timeMillis: 1595247202505] [levelValue: 1000] [[
  Exception during lifecycle processing
java.lang.Exception: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: java.lang.RuntimeException: javax.faces.FacesException: Unable to find CDI BeanManager
    at com.sun.enterprise.web.WebApplication.start(WebApplication.java:136)
    at org.glassfish.internal.data.EngineRef.start(EngineRef.java:123)
...省略...
]]
```

## 原因 : JSFと動的WebモジュールのバージョンがMavenで定義したjavax.facesと合わなから
- 環境
    - macOS Big Sur バージョン11.1
    - Eclipse IDE for Enterprise Java Developers. Version: 2020-12 M1 (4.18.0 M1)
    - openjdk version "11.0.8"
    - Payara Server 5.2020.7
    - Apache Maven 3.6.3

ログにあるエラーになった`com.sun.faces.el.ELUtils.tryAddCDIELResolver`をみてみると「JSFのバージョン2.3」と「動的Webモジュールのバージョン4.0」だとエラーになるようだ。

```java:com.sun.faces.el.ELUtils.tryAddCDIELResolver
private static boolean tryAddCDIELResolver(FacesCompositeELResolver composite) {
    FacesContext facesContext = FacesContext.getCurrentInstance();

    javax.enterprise.inject.spi.BeanManager beanManager = getCdiBeanManager(facesContext);

    if (beanManager == null) {
        // TODO: use version enum and >=
        if (getFacesConfigXmlVersion(facesContext).equals("2.3") || getWebXmlVersion(facesContext).equals("4.0")) {
            throw new FacesException("Unable to find CDI BeanManager");
        }
```

そして、このコードはpom.xmlに定義したjavax.facesの「2.3.9」に含まれているようだ・・・バージョンを「2.4.0」にしても同じだったのでJSFと動的Webモジュールのバージョンを変えるしかない・・・のかなぁ。

```xml:pom.xml
<!-- ...省略... -->
    <dependency>
      <groupId>org.glassfish</groupId>
      <artifactId>javax.faces</artifactId>
      <version>2.3.9</version>
    </dependency>
<!-- ...省略... -->
```

### 対応 : JSFと動的Webモジュールのバージョンを下げる
|対象|変更前<br/>バージョン|変更後<br/>バージョン|
|:--|:--|:--|
|動的Webモジュール(web.xml)|4.0|3.1|
|JSF(faces-config.xml)|2.3|2.2|

1. Eclipseを落とす
1. `org.eclipse.wst.common.project.facet.core.xml`でJSFと動的Webモジュールのバージョンを下げる
    - 場所 : `{プロジェクトのディレクトリ}/.settings/org.eclipse.wst.common.project.facet.core.xml`
    - プロジェクトのプロパティで変更できないのでXMLで変更します。
        - ![スクリーンショット 2020-12-28 23.32.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/aad375a2-ce7d-9446-3b52-afbb56dc03fc.png)

        - 参考 : [プロジェクト・ファセットのバージョンを 動的 Web モジュール からx.xに変更できません。となったときの対応方法 - Qiita](https://qiita.com/ponsuke0531/items/fa85408dd22dd130873d)
1. Eclipseをクリーン起動する
    - Macの場合 : `/Applications/Eclipse_2020-12.app/Contents/MacOS/eclipse -clean`
1. プロジェクトのプロパティでJSFと動的Webモジュールのバージョンが下がっていることを確認する
1. `web.xml`の`web-app`タグのバージョンを下げる
    - [web.xmlのバージョン別DTD・XSDの宣言方法 | KATSUMI KOKUZAWA&#39;S BLOG](https://kokuzawa.github.io/blog/2015/04/07/web-dot-xmlfalsebaziyonbie-dtdxsdfalsexuan-yan-fang-fa/)
1. `faces-config.xml`の`faces-config`タグのバージョンを下げる
1. サーバーをクリーン
1. プロジェクトをクリーン
1. サーバで起動

```xml:org.eclipse.wst.common.project.facet.core.xml
<!-- ...省略... -->
  <!-- ↓↓変更前↓↓ -->
  <installed facet="jst.web" version="4.0"/>
  <installed facet="jst.jsf" version="2.3"/>
  <!-- ↓↓変更後↓↓ -->
  <installed facet="jst.web" version="3.1"/>
  <installed facet="jst.jsf" version="2.2"/>
<!-- ...省略... -->
```

```xml:web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  <!-- ↓↓変更前↓↓ -->
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  id="WebApp_ID" version="4.0">
  <!-- ↓↓変更後↓↓ -->
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  id="WebApp_ID" version="3.1">
<!-- ...省略... -->
```

```xml:faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  <!-- ↓↓変更前↓↓ -->
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd"
    version="2.3">
  <!-- ↓↓変更後↓↓ -->
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
    version="2.2">
<!-- ...省略... -->
```












## 原因 : JSFのライブラリを指定していないから
- 環境
    - CentOS Linux release 7.8.2003 (Core)
    - Eclipse IDE for Enterprise Java Developers. Version: 2020-03 (4.15.0)
    - openjdk version "11.0.7"
    - Payara Server  5.194

プロジェクトに[JavaServer Faces]で「2.3」と指定したわりにライブラリをなんにも指定していなかった・・・。

参考 : [新卒SEのJavaEE挑戦記2(JSF編) | 株式会社イテレイティブ](https://www.iterative.co.jp/blog/javaee2-%EF%BD%8A%EF%BD%93%EF%BD%86/)

```xml:pom.xmlは初期状態でなんにもしていなかった
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.ponsuke</groupId>
  <artifactId>tryJsf</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
</project>
```

### 対応 : JSFのライブラリをpom.xmlに入れる
1. [Maven Repository: org.glassfish » javax.faces](https://mvnrepository.com/artifact/org.glassfish/javax.faces)から任意のバージョンの定義をコピる
1. pom.xmlに追記する
1. Payaraをクリーン > プロジェクトをクリーン > プロジェクトで[Run As] > [Run Os Server]

```xml:pom.xml
...省略...
  <dependencies>
    <dependency>
      <groupId>org.glassfish</groupId>
      <artifactId>javax.faces</artifactId>
      <version>2.3.9</version>
    </dependency>
  </dependencies>
</project>
```