Documente Academic
Documente Profesional
Documente Cultură
Documentation
Page 1 of 1804
WildFly 9
Table of Contents
1 Administrator Guides ________________________________________________________________ 17
2 Developer Guides __________________________________________________________________ 18
3 Quickstarts _______________________________________________________________________ 19
4 More Resources ___________________________________________________________________ 20
5 Admin Guide ______________________________________________________________________ 21
5.1 Target audience _______________________________________________________________ 32
5.1.1 Prerequisites ____________________________________________________________ 32
5.1.2 Examples in this guide _____________________________________________________ 32
5.2 Management clients ____________________________________________________________ 32
5.2.1 Web Management Interface _________________________________________________ 32
5.2.2 Command Line Interface ___________________________________________________ 35
5.2.3 Configuration Files ________________________________________________________ 43
5.3 Core management concepts ______________________________________________________ 43
5.3.1 Operating modes _________________________________________________________ 43
5.3.2 General configuration concepts ______________________________________________ 48
5.3.3 Management resources ____________________________________________________ 52
5.4 Configuring interfaces and ports ___________________________________________________ 63
5.4.1 Interface declarations ______________________________________________________ 63
5.4.2 Socket Binding Groups ____________________________________________________ 65
5.4.3 IPv4 versus IPv6 _________________________________________________________ 65
5.5 Administrative security __________________________________________________________ 67
5.5.1 Security realms __________________________________________________________ 67
5.5.2 Authorizing management actions with Role Based Access Control __________________ 100
5.6 Subsystem configuration ________________________________________________________ 129
5.6.1 EE Subsystem Configuration _______________________________________________ 129
5.6.2 Naming ________________________________________________________________ 139
5.6.3 Data sources ___________________________________________________________ 145
5.6.4 Messaging _____________________________________________________________ 149
5.6.5 Web (Undertow) _________________________________________________________ 162
5.6.6 Web services ___________________________________________________________ 168
5.6.7 Logging _______________________________________________________________ 174
5.6.8 Security _______________________________________________________________ 183
5.6.9 JMX __________________________________________________________________ 193
5.6.10 Resource adapters _______________________________________________________ 197
5.6.11 Deployment Scanner _____________________________________________________ 199
5.6.12 Simple configuration subsystems ____________________________________________ 201
5.7 Domain setup ________________________________________________________________ 201
5.7.1 Domain Controller Configuration ____________________________________________ 202
5.7.2 Host Controller Configuration _______________________________________________ 203
5.7.3 Server groups ___________________________________________________________ 204
5.7.4 Servers ________________________________________________________________ 206
5.8 Other management tasks _______________________________________________________ 207
Page 2 of 1804
WildFly 9
5.8.1 Controlling operation via command line parameters _____________________________ 208
5.8.2 Application deployment ___________________________________________________ 215
5.8.3 Deployment overlays _____________________________________________________ 222
5.8.4 Starting & stopping Servers in a Managed Domain ______________________________ 222
5.8.5 Controlling JVM settings __________________________________________________ 224
5.8.6 Administrative audit logging ________________________________________________ 225
5.8.7 Canceling management operations __________________________________________ 234
5.8.8 Configuration file history ___________________________________________________ 240
5.9 Management API reference _____________________________________________________ 243
5.9.1 Global operations ________________________________________________________ 243
5.9.2 Detyped management and the jboss-dmr library ________________________________ 247
5.9.3 Description of the Management Model _______________________________________ 259
5.9.4 The native management API _______________________________________________ 268
5.10 CLI Recipes __________________________________________________________________ 289
5.10.1 Properties ______________________________________________________________ 290
5.10.2 Configuration ___________________________________________________________ 292
5.10.3 Runtime _______________________________________________________________ 297
5.10.4 Scripting _______________________________________________________________ 297
5.10.5 Statistics _______________________________________________________________ 297
5.11 All WildFly 9 documentation _____________________________________________________ 298
5.12 CLI Recipes __________________________________________________________________ 298
5.12.1 Properties ______________________________________________________________ 298
5.12.2 Configuration ___________________________________________________________ 300
5.12.3 Runtime _______________________________________________________________ 305
5.12.4 Scripting _______________________________________________________________ 305
5.12.5 Statistics _______________________________________________________________ 305
5.13 Core management concepts _____________________________________________________ 305
5.13.1 Operating modes ________________________________________________________ 305
5.13.2 General configuration concepts _____________________________________________ 310
5.13.3 Management resources ___________________________________________________ 314
5.13.4 General configuration concepts _____________________________________________ 325
5.13.5 Management resources ___________________________________________________ 328
5.13.6 Operating modes ________________________________________________________ 339
5.14 Domain Setup ________________________________________________________________ 343
5.14.1 Domain Controller Configuration ____________________________________________ 344
5.14.2 Host Controller Configuration _______________________________________________ 345
5.14.3 Server groups ___________________________________________________________ 346
5.14.4 Servers ________________________________________________________________ 348
5.15 Interfaces and ports ____________________________________________________________ 349
5.15.1 Interface declarations _____________________________________________________ 350
5.15.2 Socket Binding Groups ___________________________________________________ 352
5.15.3 IPv4 versus IPv6 ________________________________________________________ 352
5.16 Management API reference _____________________________________________________ 354
5.16.1 Global operations ________________________________________________________ 354
5.16.2 Detyped management and the jboss-dmr library ________________________________ 358
5.16.3 Description of the Management Model _______________________________________ 370
Page 3 of 1804
WildFly 9
5.16.4 The native management API _______________________________________________ 379
5.16.5 Description of the Management Model _______________________________________ 400
5.16.6 Detyped management and the jboss-dmr library ________________________________ 409
5.16.7 Global operations ________________________________________________________ 422
5.16.8 The HTTP management API _______________________________________________ 426
5.16.9 The native management API _______________________________________________ 432
5.17 Management Clients ___________________________________________________________ 453
5.17.1 Web Management Interface ________________________________________________ 454
5.17.2 Command Line Interface __________________________________________________ 457
5.17.3 Configuration Files _______________________________________________________ 465
5.17.4 Default HTTP Interface Security ____________________________________________ 465
5.17.5 Default Native Interface Security ____________________________________________ 468
5.18 Management tasks ____________________________________________________________ 468
5.18.1 Controlling operation via command line parameters _____________________________ 468
5.18.2 Application deployment ___________________________________________________ 475
5.18.3 Deployment overlays _____________________________________________________ 482
5.18.4 Starting & stopping Servers in a Managed Domain ______________________________ 482
5.18.5 Controlling JVM settings __________________________________________________ 484
5.18.6 Administrative audit logging ________________________________________________ 485
5.18.7 Canceling management operations __________________________________________ 494
5.18.8 Configuration file history ___________________________________________________ 500
5.18.9 Application deployment ___________________________________________________ 503
5.18.10Audit logging ___________________________________________________________ 510
5.18.11Canceling Management Operations _________________________________________ 519
5.18.12Command line parameters ________________________________________________ 525
5.18.13Configuration file history __________________________________________________ 532
5.18.14Deployment Overlays ____________________________________________________ 536
5.18.15JVM settings ___________________________________________________________ 536
5.18.16Starting & stopping Servers in a Managed Domain _____________________________ 538
5.18.17Suspend, Resume and Graceful shutdown ____________________________________ 539
5.19 Authorizing management actions with Role Based Access Control _______________________ 542
5.19.1 Access Control Providers __________________________________________________ 543
5.19.2 RBAC provider overview __________________________________________________ 543
5.19.3 Switching to the "rbac" provider _____________________________________________ 545
5.19.4 Mapping users and groups to roles __________________________________________ 546
5.19.5 Adding custom roles in a managed domain ____________________________________ 553
5.19.6 Configuring constraints ___________________________________________________ 557
5.19.7 RBAC effect on administrator user experience _________________________________ 564
5.19.8 Learning about your own role mappings ______________________________________ 568
5.19.9 "Run-as" capability for SuperUsers __________________________________________ 568
5.20 Security Realms ______________________________________________________________ 571
5.20.1 General Structure ________________________________________________________ 572
5.20.2 Using a Realm __________________________________________________________ 572
5.20.3 Authentication __________________________________________________________ 574
5.20.4 Authorization ___________________________________________________________ 576
5.20.5 Out Of The Box Configuration ______________________________________________ 576
Page 4 of 1804
WildFly 9
5.20.6 add-user.sh ____________________________________________________________ 580
5.20.7 JMX Security ___________________________________________________________ 587
5.20.8 Detailed Configuration ____________________________________________________ 587
5.20.9 Plug Ins _______________________________________________________________ 595
5.20.10Example Configurations __________________________________________________ 602
5.20.11add-user utility __________________________________________________________ 605
5.20.12Detailed Configuration ____________________________________________________ 610
5.20.13Examples ______________________________________________________________ 618
5.20.14Plug Ins _______________________________________________________________ 621
5.21 Subsystem configuration ________________________________________________________ 628
5.21.1 EE Subsystem Configuration _______________________________________________ 629
5.21.2 Naming ________________________________________________________________ 639
5.21.3 Data sources ___________________________________________________________ 645
5.21.4 Messaging _____________________________________________________________ 649
5.21.5 Web (Undertow) _________________________________________________________ 662
5.21.6 Web services ___________________________________________________________ 668
5.21.7 Logging _______________________________________________________________ 674
5.21.8 Security _______________________________________________________________ 683
5.21.9 JMX __________________________________________________________________ 693
5.21.10Resource adapters ______________________________________________________ 697
5.21.11Deployment Scanner _____________________________________________________ 699
5.21.12Simple configuration subsystems ___________________________________________ 701
5.21.13DataSource configuration _________________________________________________ 701
5.21.14Deployment Scanner configuration __________________________________________ 705
5.21.15EE Subsystem Configuration ______________________________________________ 708
5.21.16JMX subsystem configuration ______________________________________________ 727
5.21.17Logging Configuration ____________________________________________________ 731
5.21.18Messaging configuration __________________________________________________ 752
5.21.19Naming Subsystem Configuration ___________________________________________ 765
5.21.20OSGi subsystem configuration _____________________________________________ 775
5.21.21Resource adapters ______________________________________________________ 775
5.21.22Security subsystem configuration ___________________________________________ 777
5.21.23Simple configuration subsystems ___________________________________________ 790
5.21.24Threads subsystem configuration ___________________________________________ 790
5.21.25Undertow (web) subsystem configuration _____________________________________ 792
5.21.26Web services configuration ________________________________________________ 799
5.22 Target Audience ______________________________________________________________ 806
5.22.1 Prerequisites ___________________________________________________________ 806
5.22.2 Examples in this guide ____________________________________________________ 806
6 Developer Guide __________________________________________________________________ 807
6.1 WildFly 8 Developer Guide ______________________________________________________ 810
6.1.1 Target Audience _________________________________________________________ 810
6.1.2 Prerequisites ___________________________________________________________ 810
6.2 Class loading in WildFly 8 _______________________________________________________ 810
6.2.1 Deployment Module Names ________________________________________________ 811
6.2.2 Automatic Dependencies __________________________________________________ 811
Page 5 of 1804
WildFly 9
6.2.3 Class Loading Precedence ________________________________________________ 811
6.2.4 WAR Class Loading ______________________________________________________ 811
6.2.5 EAR Class Loading ______________________________________________________ 811
6.2.6 Global Modules _________________________________________________________ 815
6.2.7 JBoss Deployment Structure File ____________________________________________ 815
6.2.8 Accessing JDK classes ___________________________________________________ 817
6.3 Implicit module dependencies for deployments ______________________________________ 817
6.3.1 What's an implicit module dependency? ______________________________________ 818
6.3.2 How and when is an implicit module dependency added? ________________________ 818
6.3.3 Which are the implicit module dependencies? __________________________________ 818
6.4 How do I migrate my application from JBoss AS 5 or AS 6 to WildFly 8? __________________ 821
6.5 EJB invocations from a remote standalone client using JNDI ____________________________ 821
6.5.1 Deploying your EJBs on the server side: ______________________________________ 821
6.5.2 Writing a remote client application for accessing and invoking the EJBs deployed on the
server ________________________________________________________________________ 823
6.5.3 Setting up EJB client context properties ______________________________________ 829
6.5.4 Summary ______________________________________________________________ 833
6.6 EJB invocations from a remote server _____________________________________________ 833
6.6.1 Application packaging ____________________________________________________ 833
6.6.2 Beans _________________________________________________________________ 834
6.6.3 Security _______________________________________________________________ 834
6.6.4 Configuring a user on the "Destination Server" _________________________________ 835
6.6.5 Start the "Destination Server" ______________________________________________ 836
6.6.6 Deploying the application __________________________________________________ 836
6.6.7 Configuring the "Client Server" to point to the EJB remoting connector on the "Destination
Server" ________________________________________________________________________ 836
6.6.8 Start the "Client Server" ___________________________________________________ 837
6.6.9 Create a security realm on the client server ____________________________________ 837
6.6.10 Create a outbound-socket-binding on the "Client Server" _________________________ 839
6.6.11 Create a "remote-outbound-connection" which uses this newly created
"outbound-socket-binding" ________________________________________________________ 839
6.6.12 Packaging the client application on the "Client Server" ___________________________ 841
6.6.13 Contents on jboss-ejb-client.xml ____________________________________________ 842
6.6.14 Deploy the client application _______________________________________________ 842
6.6.15 Client code invoking the bean ______________________________________________ 843
6.7 Remote EJB invocations via JNDI - Which approach to use? ____________________________ 843
6.8 JBoss EJB 3 reference guide ____________________________________________________ 843
6.8.1 Resource Adapter for Message Driven Beans __________________________________ 844
6.8.2 Run-as Principal _________________________________________________________ 844
6.8.3 Security Domain _________________________________________________________ 845
6.8.4 Transaction Timeout _____________________________________________________ 845
6.8.5 Timer service ___________________________________________________________ 846
6.9 JPA reference guide ___________________________________________________________ 848
6.9.1 Introduction ____________________________________________________________ 850
6.9.2 Update your Persistence.xml for Hibernate 4.3.0 _______________________________ 850
6.9.3 Entity manager __________________________________________________________ 850
Page 6 of 1804
WildFly 9
6.9.4 Application-managed entity manager _________________________________________ 851
6.9.5 Container-managed entity manager __________________________________________ 851
6.9.6 Persistence Context ______________________________________________________ 851
6.9.7 Transaction-scoped Persistence Context _____________________________________ 852
6.9.8 Extended Persistence Context ______________________________________________ 852
6.9.9 Entities ________________________________________________________________ 854
6.9.10 Deployment ____________________________________________________________ 855
6.9.11 Troubleshooting _________________________________________________________ 855
6.9.12 Background on the Jipijapa project __________________________________________ 857
6.9.13 Packaging persistence providers with your application and which Jipijapa artifacts to include
858
6.9.14 Using the Hibernate 4.3.x JPA persistence provider _____________________________ 858
6.9.15 Using the Infinispan second level cache ______________________________________ 859
6.9.16 Replacing the current Hibernate 4.3.x jars with a newer version ____________________ 860
6.9.17 Packaging the Hibernate 4.x (or greater) JPA persistence provider with your application
860
6.9.18 Packaging the Hibernate 3.5 or greater 3.x JPA persistence provider with your application __
861
6.9.19 Sharing the Hibernate 3.5 or greater JPA persistence provider between multiple applications
861
6.9.20 Using OpenJPA _________________________________________________________ 863
6.9.21 Using EclipseLink ________________________________________________________ 863
6.9.22 Using DataNucleus ______________________________________________________ 865
6.9.23 Using Hibernate OGM ____________________________________________________ 865
6.9.24 Native Hibernate use _____________________________________________________ 867
6.9.25 Injection of Hibernate Session and SessionFactoryInjection of Hibernate Session and
SessionFactory _________________________________________________________________ 867
6.9.26 Hibernate properties ______________________________________________________ 867
6.9.27 Persistence unit properties _________________________________________________ 868
6.9.28 Determine the persistence provider module ___________________________________ 870
6.9.29 Binding EntityManagerFactory/EntityManager to JNDI ___________________________ 871
6.9.30 Community _____________________________________________________________ 872
6.10 OSGi developer guide __________________________________________________________ 872
6.11 JNDI reference guide __________________________________________________________ 872
6.11.1 Overview ______________________________________________________________ 873
6.11.2 Local JNDI _____________________________________________________________ 873
6.11.3 Remote JNDI ___________________________________________________________ 878
6.12 Spring applications development and migration guide _________________________________ 879
6.12.1 Dependencies and Modularity ______________________________________________ 879
6.12.2 Persistence usage guide __________________________________________________ 880
6.12.3 Native Spring/Hibernate applications _________________________________________ 880
6.12.4 JPA-based applications ___________________________________________________ 880
6.13 All WildFly 8 documentation _____________________________________________________ 883
6.14 Application Client Reference _____________________________________________________ 883
6.14.1 Getting Started __________________________________________________________ 883
6.14.2 Connecting to more than one host ___________________________________________ 883
6.14.3 Example _______________________________________________________________ 884
Page 7 of 1804
WildFly 9
6.15 CDI Reference ________________________________________________________________ 884
6.15.1 Using CDI Beans from outside the deployment _________________________________ 885
6.15.2 Suppressing implicit bean archives __________________________________________ 886
6.15.3 Non-portable mode ______________________________________________________ 887
6.16 Class Loading in WildFly ________________________________________________________ 887
6.16.1 Deployment Module Names ________________________________________________ 888
6.16.2 Automatic Dependencies __________________________________________________ 888
6.16.3 Class Loading Precedence ________________________________________________ 888
6.16.4 WAR Class Loading ______________________________________________________ 888
6.16.5 EAR Class Loading ______________________________________________________ 888
6.16.6 Global Modules _________________________________________________________ 892
6.16.7 JBoss Deployment Structure File ____________________________________________ 892
6.16.8 Accessing JDK classes ___________________________________________________ 894
6.17 Deployment Descriptors used In WildFly ___________________________________________ 894
6.18 Development Guidelines and Recommended Practices ________________________________ 898
6.19 EE Concurrency Utilities ________________________________________________________ 898
6.19.1 Overview ______________________________________________________________ 898
6.19.2 Context Service _________________________________________________________ 899
6.19.3 Managed Thread Factory __________________________________________________ 899
6.19.4 Managed Executor Service ________________________________________________ 901
6.19.5 Managed Scheduled Executor Service _______________________________________ 901
6.20 EJB 3 Reference Guide _________________________________________________________ 903
6.20.1 Resource Adapter for Message Driven Beans __________________________________ 903
6.20.2 Run-as Principal _________________________________________________________ 904
6.20.3 Security Domain _________________________________________________________ 904
6.20.4 Transaction Timeout _____________________________________________________ 904
6.20.5 Timer service ___________________________________________________________ 906
6.20.6 Container interceptors ____________________________________________________ 908
6.20.7 EJB3 Clustered Database Timers ___________________________________________ 912
6.20.8 EJB3 subsystem configuration guide _________________________________________ 915
6.20.9 EJB IIOP Guide _________________________________________________________ 921
6.20.10jboss-ejb3.xml Reference _________________________________________________ 921
6.20.11Securing EJBs __________________________________________________________ 923
6.21 EJB invocations from a remote client using JNDI _____________________________________ 927
6.21.1 Deploying your EJBs on the server side: ______________________________________ 928
6.21.2 Writing a remote client application for accessing and invoking the EJBs deployed on the
server ________________________________________________________________________ 930
6.21.3 Setting up EJB client context properties ______________________________________ 936
6.21.4 Summary ______________________________________________________________ 940
6.22 EJB invocations from a remote server instance ______________________________________ 940
6.22.1 Application packaging ____________________________________________________ 940
6.22.2 Beans _________________________________________________________________ 941
6.22.3 Security _______________________________________________________________ 941
6.22.4 Configuring a user on the "Destination Server" _________________________________ 942
6.22.5 Start the "Destination Server" ______________________________________________ 943
6.22.6 Deploying the application __________________________________________________ 943
Page 8 of 1804
WildFly 9
6.22.7 Configuring the "Client Server" to point to the EJB remoting connector on the "Destination
Server" ________________________________________________________________________ 943
6.22.8 Start the "Client Server" ___________________________________________________ 944
6.22.9 Create a security realm on the client server ____________________________________ 944
6.22.10Create a outbound-socket-binding on the "Client Server" _________________________ 946
6.22.11Create a "remote-outbound-connection" which uses this newly created
"outbound-socket-binding" ________________________________________________________ 946
6.22.12Packaging the client application on the "Client Server" ___________________________ 948
6.22.13Contents on jboss-ejb-client.xml ____________________________________________ 949
6.22.14Deploy the client application _______________________________________________ 949
6.22.15Client code invoking the bean ______________________________________________ 950
6.23 Example Applications - Migrated to WildFly _________________________________________ 950
6.23.1 Example Applications Migrated from Previous Releases __________________________ 951
6.23.2 Example Applications Based on EE6 _________________________________________ 952
6.23.3 Porting the Order Application from EAP 5.1 to WildFly 8 __________________________ 952
6.23.4 Seam 2 Booking Application - Migration of Binaries from EAP5.1 to WildFly __________ 957
6.24 How do I migrate my application from AS7 to WildFly 9 ________________________________ 977
6.24.1 Overview of WildFly 9 ____________________________________________________ 977
6.24.2 Review The List of Deprecated and Unsupported Features _______________________ 977
6.25 How do I migrate my application to WildFly from other application servers _________________ 977
6.25.1 Choose from the list below: ________________________________________________ 977
6.25.2 How do I migrate my application from WebLogic to WildFly _______________________ 977
6.25.3 How do I migrate my application from WebSphere to WildFly _____________________ 1020
6.26 Implicit module dependencies for deployments _____________________________________ 1063
6.26.1 What's an implicit module dependency? _____________________________________ 1063
6.26.2 How and when is an implicit module dependency added? _______________________ 1064
6.26.3 Which are the implicit module dependencies? _________________________________ 1064
6.27 JAX-RS Reference Guide ______________________________________________________ 1066
6.27.1 Subclassing javax.ws.rs.core.Application and using @ApplicationPath _____________ 1067
6.27.2 Subclassing javax.ws.rs.core.Application and using web.xml _____________________ 1067
6.27.3 Using web.xml _________________________________________________________ 1068
6.28 JNDI Reference ______________________________________________________________ 1068
6.28.1 Overview _____________________________________________________________ 1069
6.28.2 Local JNDI ____________________________________________________________ 1069
6.28.3 Remote JNDI __________________________________________________________ 1074
6.28.4 Local JNDI ____________________________________________________________ 1075
6.28.5 Remote JNDI Reference _________________________________________________ 1080
6.29 JPA Reference Guide _________________________________________________________ 1083
6.29.1 Introduction ___________________________________________________________ 1085
6.29.2 Update your Persistence.xml for Hibernate 4.3.0 ______________________________ 1085
6.29.3 Entity manager _________________________________________________________ 1085
6.29.4 Application-managed entity manager ________________________________________ 1086
6.29.5 Container-managed entity manager _________________________________________ 1086
6.29.6 Persistence Context _____________________________________________________ 1086
6.29.7 Transaction-scoped Persistence Context ____________________________________ 1087
6.29.8 Extended Persistence Context _____________________________________________ 1087
Page 9 of 1804
WildFly 9
6.29.9 Entities _______________________________________________________________ 1089
6.29.10Deployment ___________________________________________________________ 1090
6.29.11Troubleshooting ________________________________________________________ 1090
6.29.12Background on the Jipijapa project _________________________________________ 1092
6.29.13Packaging persistence providers with your application and which Jipijapa artifacts to include
____________________________________________________________________________ 1093
6.29.14Using the Hibernate 4.3.x JPA persistence provider ____________________________ 1093
6.29.15Using the Infinispan second level cache _____________________________________ 1094
6.29.16Replacing the current Hibernate 4.3.x jars with a newer version __________________ 1095
6.29.17Packaging the Hibernate 4.x (or greater) JPA persistence provider with your application 1095
6.29.18Packaging the Hibernate 3.5 or greater 3.x JPA persistence provider with your application _
1096
6.29.19Sharing the Hibernate 3.5 or greater JPA persistence provider between multiple applications
____________________________________________________________________________ 1096
6.29.20Using OpenJPA ________________________________________________________ 1098
6.29.21Using EclipseLink ______________________________________________________ 1098
6.29.22Using DataNucleus _____________________________________________________ 1100
6.29.23Using Hibernate OGM ___________________________________________________ 1100
6.29.24Native Hibernate use ____________________________________________________ 1102
6.29.25Injection of Hibernate Session and SessionFactoryInjection of Hibernate Session and
SessionFactory ________________________________________________________________ 1102
6.29.26Hibernate properties ____________________________________________________ 1102
6.29.27Persistence unit properties _______________________________________________ 1103
6.29.28Determine the persistence provider module __________________________________ 1105
6.29.29Binding EntityManagerFactory/EntityManager to JNDI __________________________ 1106
6.29.30Community ___________________________________________________________ 1107
6.30 OSGi ______________________________________________________________________ 1107
6.31 Remote EJB invocations via JNDI - EJB client API or remote-naming project ______________ 1107
6.31.1 Purpose ______________________________________________________________ 1107
6.31.2 History _______________________________________________________________ 1108
6.31.3 Overview _____________________________________________________________ 1108
6.31.4 Summary _____________________________________________________________ 1113
6.31.5 Remote EJB invocations backed by the remote-naming project ___________________ 1113
6.31.6 Why use the EJB client API approach then? __________________________________ 1116
6.32 Scoped EJB client contexts _____________________________________________________ 1119
6.32.1 Overview _____________________________________________________________ 1119
6.32.2 Potential shortcomings of a single EJB client context ___________________________ 1119
6.32.3 Scoped EJB client contexts _______________________________________________ 1121
6.32.4 Lifecycle management of scoped EJB client contexts ___________________________ 1122
6.33 Spring applications development and migration guide ________________________________ 1127
6.33.1 Dependencies and Modularity _____________________________________________ 1128
6.33.2 Persistence usage guide _________________________________________________ 1128
6.33.3 Native Spring/Hibernate applications ________________________________________ 1128
6.33.4 JPA-based applications __________________________________________________ 1128
6.34 Sharing sessions between wars in an ear __________________________________________ 1131
6.35 Webservices reference guide ___________________________________________________ 1131
Page 10 of 1804
WildFly 9
6.35.1 JAX-WS User Guide ____________________________________________________ 1132
6.35.2 JAX-WS Tools _________________________________________________________ 1147
6.35.3 Advanced User Guide ___________________________________________________ 1167
6.35.4 JBoss Modules and WS applications ________________________________________ 1352
7 High Availability Guide ____________________________________________________________ 1356
7.1 Introduction to High Availability Services __________________________________________ 1357
7.1.1 What are High Availability services? ________________________________________ 1358
7.1.2 High Availability through fail-over ___________________________________________ 1359
7.1.3 High Availability through load balancing _____________________________________ 1359
7.1.4 Aims of the guide _______________________________________________________ 1359
7.1.5 Organization of the guide _________________________________________________ 1360
7.2 HTTP Services ______________________________________________________________ 1360
7.2.1 Subsystem Support _____________________________________________________ 1360
7.2.2 Clustered Web Sessions _________________________________________________ 1378
7.2.3 Clustered SSO _________________________________________________________ 1378
7.2.4 Load Balancing ________________________________________________________ 1378
7.2.5 Load balancing with Apache + mod_jk ______________________________________ 1378
7.2.6 Load balancing with Apache + mod_cluster __________________________________ 1378
7.3 EJB Services ________________________________________________________________ 1385
7.3.1 EJB Subsystem ________________________________________________________ 1385
7.4 EJB Timer __________________________________________________________________ 1385
7.4.1 Marking an EJB as clustered ______________________________________________ 1386
7.4.2 Deploying clustered EJBs ________________________________________________ 1387
7.4.3 Failover for clustered EJBs _______________________________________________ 1387
7.5 Hibernate ___________________________________________________________________ 1390
7.6 Related Issues _______________________________________________________________ 1391
7.6.1 Modularity And Class Loading _____________________________________________ 1391
7.6.2 Monitoring ____________________________________________________________ 1391
7.7 Changes From Previous Versions ________________________________________________ 1391
7.7.1 Key changes __________________________________________________________ 1391
7.7.2 Migration to Wildfly ______________________________________________________ 1391
7.8 WildFly 8 Cluster Howto _______________________________________________________ 1391
7.9 References _________________________________________________________________ 1391
7.10 All WildFly 8 documentation ____________________________________________________ 1391
7.11 Introduction To High Availability Services __________________________________________ 1391
7.11.1 What are High Availability services? ________________________________________ 1392
7.11.2 High Availability through fail-over ___________________________________________ 1393
7.11.3 High Availability through load balancing _____________________________________ 1393
7.11.4 Aims of the guide _______________________________________________________ 1393
7.11.5 Organization of the guide _________________________________________________ 1394
7.12 HTTP Services ______________________________________________________________ 1394
7.12.1 Subsystem Support _____________________________________________________ 1394
7.12.2 Clustered Web Sessions _________________________________________________ 1412
7.12.3 Clustered SSO _________________________________________________________ 1412
7.12.4 Load Balancing ________________________________________________________ 1412
7.12.5 Load balancing with Apache + mod_jk ______________________________________ 1412
Page 11 of 1804
WildFly 9
7.12.6 Load balancing with Apache + mod_cluster __________________________________ 1412
7.12.7 Subsystem Support _____________________________________________________ 1419
7.12.8 Clustered Web Sessions _________________________________________________ 1454
7.12.9 Clustered SSO _________________________________________________________ 1454
7.12.10Load Balancing ________________________________________________________ 1454
7.13 EJB Services ________________________________________________________________ 1469
7.13.1 EJB Subsystem ________________________________________________________ 1469
7.13.2 EJB Timer ____________________________________________________________ 1469
7.13.3 EJB Timer ____________________________________________________________ 1474
7.14 Hibernate ___________________________________________________________________ 1474
7.15 Related Issues _______________________________________________________________ 1475
7.15.1 Modularity And Class Loading _____________________________________________ 1475
7.15.2 Monitoring ____________________________________________________________ 1475
7.16 Changes From Previous Versions ________________________________________________ 1475
7.16.1 Key changes __________________________________________________________ 1475
7.16.2 Migration to Wildfly ______________________________________________________ 1475
7.17 WildFly 9 Cluster Howto _______________________________________________________ 1475
7.17.1 Preparation & Scenario __________________________________________________ 1475
7.17.2 Download WildFly 9 _____________________________________________________ 1478
7.17.3 Domain Configuration ___________________________________________________ 1478
7.17.4 Deployment ___________________________________________________________ 1483
7.17.5 Cluster Configuration ____________________________________________________ 1489
7.17.6 Testing _______________________________________________________________ 1492
7.17.7 Special Thanks _________________________________________________________ 1494
8 Getting Started Developing Applications Guide _________________________________________ 1495
8.1 Introduction _________________________________________________________________ 1495
8.2 Getting started with WildFly _____________________________________________________ 1495
8.3 Helloworld quickstart __________________________________________________________ 1495
8.3.1 Deploying the Helloworld example using Eclipse _______________________________ 1495
8.3.2 The helloworld example in depth ___________________________________________ 1498
8.4 Numberguess quickstart _______________________________________________________ 1498
8.4.1 Deploying the Numberguess example using Eclipse ____________________________ 1498
8.4.2 The numberguess example in depth ________________________________________ 1498
8.5 Login quickstart ______________________________________________________________ 1498
8.5.1 Deploying the Login example using Eclipse ___________________________________ 1498
8.5.2 The login example in depth _______________________________________________ 1498
8.6 Kitchensink quickstart _________________________________________________________ 1499
8.6.1 Deploying the Kitchensink example using Eclipse ______________________________ 1499
8.6.2 The kitchensink example in depth __________________________________________ 1499
8.7 Creating your own application ___________________________________________________ 1499
8.7.1 Creating your own application using Eclipse __________________________________ 1499
8.8 More Resources _____________________________________________________________ 1499
8.8.1 Developing JSF Project Using JBoss AS7, Maven and IntelliJ ____________________ 1499
8.8.2 Getting Started Developing Applications Presentation & Demo ___________________ 1528
9 Getting Started Guide _____________________________________________________________ 1543
9.1 Getting Started with WildFly 8 ___________________________________________________ 1543
Page 12 of 1804
WildFly 9
9.1.1 Download _____________________________________________________________ 1545
9.1.2 Requirements __________________________________________________________ 1545
9.1.3 Installation ____________________________________________________________ 1545
9.1.4 WildFly - A Quick Tour ___________________________________________________ 1545
9.2 All WildFly 8 documentation ____________________________________________________ 1556
9.3 JavaEE 6 Tutorial ____________________________________________________________ 1556
9.3.1 Standard JavaEE 6 Technologies __________________________________________ 1557
9.3.2 JBoss AS7 Extension Technologies ________________________________________ 1557
9.3.3 Standard JavaEE 6 Technologies __________________________________________ 1557
9.3.4 JBoss AS7 Extension Technologies ________________________________________ 1592
10 Glossary _______________________________________________________________________ 1593
10.1 Module _____________________________________________________________________ 1593
10.2 Module _____________________________________________________________________ 1593
11 Extending WildFly ________________________________________________________________ 1594
11.1 Target Audience _____________________________________________________________ 1595
11.1.1 Prerequisites __________________________________________________________ 1595
11.1.2 Examples in this guide ___________________________________________________ 1595
11.2 Overview ___________________________________________________________________ 1595
11.3 Example subsystem __________________________________________________________ 1595
11.3.1 Create the skeleton project _______________________________________________ 1595
11.3.2 Create the schema ______________________________________________________ 1598
11.3.3 Design and define the model structure ______________________________________ 1598
11.3.4 Parsing and marshalling of the subsystem xml ________________________________ 1610
11.3.5 Add the deployers ______________________________________________________ 1621
11.3.6 Integrate with JBoss AS 7 ________________________________________________ 1625
11.3.7 Expressions ___________________________________________________________ 1625
11.4 Key Interfaces and Classes Relevant to Extension Developers _________________________ 1627
11.4.1 Extension Interface _____________________________________________________ 1628
11.4.2 WildFly 8 Managed Resources ____________________________________________ 1629
11.4.3 ManagementResourceRegistration Interface __________________________________ 1629
11.4.4 ResourceDefinition Interface ______________________________________________ 1629
11.4.5 AttributeDefinition Interface _______________________________________________ 1630
11.4.6 OperationDefinition and OperationStepHandler Interfaces _______________________ 1630
11.4.7 Operation Execution and the OperationContext _______________________________ 1630
11.4.8 Resource Interface ______________________________________________________ 1630
11.4.9 DeploymentUnitProcessor Interface ________________________________________ 1630
11.4.10Useful classes for implementing OperationStepHandler _________________________ 1630
11.5 All WildFly 9 documentation ____________________________________________________ 1631
11.6 Domain Mode Subsystem Transformers ___________________________________________ 1631
11.6.1 "Abstract" _____________________________________________________________ 1633
11.6.2 Background ___________________________________________________________ 1633
11.6.3 Versions and backward compatibility ________________________________________ 1636
11.6.4 The role of transformers __________________________________________________ 1638
11.6.5 How do I know what needs to be transformed? ________________________________ 1645
11.6.6 How do I write a transformer? _____________________________________________ 1648
11.6.7 Evolving transformers with subsystem ModelVersions __________________________ 1667
Page 13 of 1804
WildFly 9
11.6.8 Common transformation use-cases _________________________________________ 1674
11.7 Example subsystem __________________________________________________________ 1681
11.7.1 Create the skeleton project _______________________________________________ 1681
11.7.2 Create the schema ______________________________________________________ 1684
11.7.3 Design and define the model structure ______________________________________ 1684
11.7.4 Parsing and marshalling of the subsystem xml ________________________________ 1696
11.7.5 Add the deployers ______________________________________________________ 1707
11.7.6 Integrate with JBoss AS 7 ________________________________________________ 1711
11.7.7 Expressions ___________________________________________________________ 1711
11.7.8 Add the deployers ______________________________________________________ 1713
11.7.9 Create the schema ______________________________________________________ 1717
11.7.10Create the skeleton project _______________________________________________ 1717
11.7.11Design and define the model structure ______________________________________ 1719
11.7.12Expressions ___________________________________________________________ 1731
11.7.13Integrate with WildFly 8 __________________________________________________ 1734
11.7.14Parsing and marshalling of the subsystem xml ________________________________ 1739
11.8 Key Interfaces and Classes Relevant to Extension Developers _________________________ 1749
11.8.1 Extension Interface _____________________________________________________ 1751
11.8.2 WildFly 8 Managed Resources ____________________________________________ 1752
11.8.3 ManagementResourceRegistration Interface __________________________________ 1752
11.8.4 ResourceDefinition Interface ______________________________________________ 1752
11.8.5 AttributeDefinition Interface _______________________________________________ 1753
11.8.6 OperationDefinition and OperationStepHandler Interfaces _______________________ 1753
11.8.7 Operation Execution and the OperationContext _______________________________ 1753
11.8.8 Resource Interface ______________________________________________________ 1753
11.8.9 DeploymentUnitProcessor Interface ________________________________________ 1753
11.8.10Useful classes for implementing OperationStepHandler _________________________ 1753
11.9 Transformers ________________________________________________________________ 1753
11.9.1 What are transformers ___________________________________________________ 1754
11.10WildFly 9 JNDI Implementation _________________________________________________ 1754
11.10.1Introduction ___________________________________________________________ 1755
11.10.2Architecture ___________________________________________________________ 1755
11.10.3Binding APIs __________________________________________________________ 1755
11.10.4Resource Ref Processing ________________________________________________ 1762
12 Common _______________________________________________________________________ 1763
12.1 All WildFly 9 documentation ____________________________________________________ 1763
13 Testsuite _______________________________________________________________________ 1764
13.1 JBoss AS 7 Testsuite _________________________________________________________ 1764
13.2 WildFly Testsuite Overview _____________________________________________________ 1764
13.2.1 Test Suite Organization __________________________________________________ 1765
13.2.2 Profiles _______________________________________________________________ 1766
13.2.3 Integration tests ________________________________________________________ 1767
13.3 WildFly Integration Testsuite User Guide __________________________________________ 1767
13.3.1 Running the testsuite ____________________________________________________ 1767
13.3.2 Examples _____________________________________________________________ 1769
13.3.3 Troubleshooting Common Issues __________________________________________ 1779
Page 14 of 1804
WildFly 9
13.4 WildFly Testsuite Harness Developer Guide ________________________________________ 1779
13.4.1 Testsuite requirements ___________________________________________________ 1779
13.4.2 Adding a new maven plugin _______________________________________________ 1779
13.4.3 Shortened Maven run overview ____________________________________________ 1779
13.4.4 How the AS instance is built _______________________________________________ 1780
13.4.5 Properties and their propagation ___________________________________________ 1781
13.4.6 Debug parameters propagation ____________________________________________ 1782
13.4.7 How the JBoss AS instance is built and configured for testsuite modules. ___________ 1782
13.4.8 Plugin executions matrix _________________________________________________ 1783
13.4.9 Shortened Maven Run Overview ___________________________________________ 1785
13.5 WildFly Testsuite Test Developer Guide ___________________________________________ 1792
13.5.1 Pre-requisites __________________________________________________________ 1793
13.5.2 Arquillian container configuration ___________________________________________ 1793
13.5.3 ManagementClient and ModelNode usage example ____________________________ 1793
13.5.4 Arquillian features available in tests _________________________________________ 1793
13.5.5 Properties available in tests _______________________________________________ 1795
13.5.6 Negative tests _________________________________________________________ 1796
13.5.7 Clustering tests (WFLY-616) ______________________________________________ 1796
13.5.8 How to get the tests to master _____________________________________________ 1797
13.5.9 How to Add a Test Case _________________________________________________ 1798
13.5.10Before you add a test ___________________________________________________ 1798
13.5.11Shared Test Classes and Resources _______________________________________ 1802
14 Quickstarts _____________________________________________________________________ 1803
14.1 Getting Started ______________________________________________________________ 1803
14.2 Contributing _________________________________________________________________ 1803
14.3 Contributing a Quickstart _______________________________________________________ 1803
14.3.1 Maven POM Versions Checklist ____________________________________________ 1804
14.3.2 Writing a quickstart ______________________________________________________ 1804
Page 15 of 1804
WildFly 9
Welcome to the WildFly 9 Documentation. The documentation for WildFly is split into two categories:
Administrator Guides for those wanting to understand how to install and configure the server
Developer Guides for those wanting to understand how to develop applications for the server
There is also the WildFly Model Reference that provides information about all subsystem configuration
options generated directly from the management model.
Page 16 of 1804
WildFly 9
1 Administrator Guides
The Getting Started Guide shows you how to install and start the server, how to configure logging,
how to deploy an application, how to deploy a datasource, and how to get started using the command
line interface and web management interface
The Admin Guide provides detailed information on using the CLI and Web Management interface,
how to use the domain configuration, and shows you how to configure key subsystems
The High Availability Guide shows you how to create a cluster, how configure the web container and
EJB container for clustering, and shows you how to configure load balancing and failover
Page 17 of 1804
WildFly 9
2 Developer Guides
The Getting Started Developing Applications Guide shows you how to build Java EE applications and
deploy them to WildFly. The guide starts by showing you the simplest helloworld application using just
Servlet and CDI, and then adds in JSF, persistence and transactions, EJB, Bean Validation, RESTful
web services and more. You'll also discover how to deploy an OSGi bundle to WildFly. Finally, you'll
get the opportunity to create your own skeleton project. Each tutorial is accompanied by a quickstart,
which contains the source code, deployment descriptors and a Maven based build.
The Developer Guide (in progress) takes you through every deployment descriptor and every
annotation offered by WildFly.
The JavaEE 6 Tutorial (in progress) builds on what you learnt in the Getting Started Developing
Applications Guide, and shows you how to build a complex application using Java EE and portable
extensions.
The Extending WildFly guide walks you through creating a new WildFly subsystem extension, in order
to add more functionality to WildFly, and shows how to test it before plugging it into WildFly.
Page 18 of 1804
WildFly 9
3 Quickstarts
WildFly comes with a number of quickstarts, examples which introduce to a particular technology or feature
of the application server. The Contributing a Quickstart section of the documentation details the available
quickstarts
Page 19 of 1804
WildFly 9
4 More Resources
Glossary
WildFly project page
WildFly issue tracker
WildFly user forum
WildFly wiki
WildFly source
Page 20 of 1804
WildFly 9
5 Admin Guide
Target audience
Prerequisites
Examples in this guide
Management clients
Web Management Interface
HTTP Management Endpoint
Accessing the web console
Default HTTP Management Interface Security
Command Line Interface
Native Management Endpoint
Running the CLI
Non-interactive Mode
Operation Requests
Addressing resources
Available Operation Types and Descriptions
Command History
Batch Processing
Default Native Management Interface Security
Configuration Files
Page 21 of 1804
WildFly 9
Core management concepts
Operating modes
Standalone Server
Managed Domain
Host
Host Controller
Domain Controller
Server Group
Server
Deciding between running standalone servers or a managed domain
General configuration concepts
Extensions
Profiles and Subsystems
Paths
Interfaces
Socket Bindings and Socket Binding Groups
System Properties
Management resources
Address
Operations
Attributes
Children
Descriptions
Comparison to JMX MBeans
Basic structure of the management resource trees
Standalone server
Managed domain
Configuring interfaces and ports
Interface declarations
The -b command line argument
Socket Binding Groups
IPv4 versus IPv6
Stack and address preference
IP address literals
Administrative security
Security realms
General Structure
Using a Realm
Inbound Connections
Management Interfaces
Remoting Subsystem
Outbound Connections
Remoting Subsystem
Slave Host Controller
Authentication
Authorization
Page 22 of 1804
WildFly 9
Out Of The Box Configuration
Management Realm
Application Realm
Authentication
Authorization
other security domain
add-user.sh
Adding a User
A Management User
Interactive Mode
Non-Interactive Mode
An Application User
Interactive Mode
Non-Interactive Mode
Updating a User
A Management User
Interactive Mode
Non-Interactive Mode
An Application User
Interactive Mode
Non-Interactive Mode
Community Contributions
JMX Security
Detailed Configuration
<server-identities />
<ssl />
<secret />
<authentication />
<truststore />
<local />
<jaas />
<ldap />
<username-filter />
<advanced-filter />
<properties />
<users />
<authorization />
<properties />
<outbound-connection />
<ldap />
Page 23 of 1804
WildFly 9
Plug Ins
AuthenticationPlugIn
PasswordCredential
DigestCredential
ValidatePasswordCredential
AuthorizationPlugIn
PlugInConfigurationSupport
Installing and Configuring a Plug-In
PlugInProvider
Package as a Module
The AuthenticationPlugIn
The AuthorizationPlugIn
Forcing Plain Text Authentication
Example Configurations
LDAP Authentication
Enable SSL
Add Client-Cert to SSL
Page 24 of 1804
WildFly 9
Authorizing management actions with Role Based Access Control
Access Control Providers
RBAC provider overview
RBAC roles
Access control constraints
Addressing a resource
Switching to the "rbac" provider
Mapping users and groups to roles
Mapping individual users
User groups
Mapping groups to roles
Including all authenticated users in a role
Excluding users and groups
Users who map to multiple roles
Adding custom roles in a managed domain
Server group scoped roles
Host scoped roles
Using the admin console to create scoped roles
Configuring constraints
Configuring sensitivity
Sensitive resources, attributes and operations
Classifications with broad use
Values with security vault expressions
Configuring "Deployer" role access
Application classifications shipped with WildFly
RBAC effect on administrator user experience
Admin console
CLI
Description of access control constraints in the management model metadata
Learning about your own role mappings
"Run-as" capability for SuperUsers
CLI run-as
Admin console run-as
Using run-as roles with the "simple" access control provider
Subsystem configuration
Page 25 of 1804
WildFly 9
EE Subsystem Configuration
Overview
Java EE Application Deployment
Global Modules
EAR Subdeployments Isolation
Property Replacement
Spec Descriptor Property Replacement
JBoss Descriptor Property Replacement
Annotation Property Replacement
EE Concurrency Utilities
Context Services
Managed Thread Factories
Managed Executor Services
Managed Scheduled Executor Services
Default EE Bindings
Naming
Overview
Global Bindings Configuration
Simple Bindings
Object Factories
External Context Federation
Remote JNDI Configuration
Data sources
JDBC Driver Installation
Datasource Definitions
Using security domains
Deployment of -ds.xml files
Component Reference
Messaging
Connectors
JMS Connection Factories
JMS Queues and Topics
Dead Letter & Redelivery
Security Settings for HornetQ addresses and JMS destinations
Security Domain for Users
Cluster Authentication
Deployment of -jms.xml files
JMS Bridge
Modules for other messaging brokers
Configuration
Management commands
Component Reference
Page 26 of 1804
WildFly 9
Web (Undertow)
Buffer cache configuration
Server configuration
Connector configuration
Common settings
HTTP Connector
HTTPS listener
AJP listener
Host configuration
Servlet container configuration
JSP configuration
Session Cookie Configuration
Persistent Session Configuration
Web services
Structure of the webservices subsystem
Published endpoint address
Predefined endpoint configurations
Endpoint configs
Handler chains
Handlers
Runtime information
Component Reference
Logging
Overview
Attributes
add-logging-api-dependencies
use-deployment-logging-config
Per-deployment Logging
Logging Profiles
Default Log File Locations
Managed Domain
Standalone Server
Filter Expressions
List Log Files and Reading Log Files
List Log Files
Read Log File
FAQ
Why is there a logging.properties file?
Page 27 of 1804
WildFly 9
Security
Structure of the Security Subsystem
Authentication Manager
Authorization Manager
Audit Manager
Mapping Manager
Security Subsystem Configuration
security-management
subject-factory
security-domains
authentication
authentication-jaspi
authorization
mapping
audit
jsse
security-properties
JMX
Audit logging
JSON Formatter
Resource adapters
Resource Adapter Definitions
Using security domains
Automatic activation of resource adapter archives
Component Reference
Deployment Scanner
Simple configuration subsystems
Domain setup
Domain Controller Configuration
Host Controller Configuration
Server groups
Servers
JVM
Other management tasks
Page 28 of 1804
WildFly 9
Controlling operation via command line parameters
System properties
Controlling filesystem locations with system properties
Standalone
Managed Domain
Other command line parameters
Standalone
Managed Domain
Common parameters
Controlling the Bind Address with -b
Controlling the Default Multicast Address with -u
Application deployment
Managed Domain
Deployment Commands
Content Repository
Standalone Server
Deployment Commands
File System Deployments
Deployment Modes
Marker Files
Deployment overlays
Creating a deployment overlay
Starting & stopping Servers in a Managed Domain
Controlling JVM settings
Managed Domain
Standalone Server
Administrative audit logging
JSON Formatter
Handlers
File handler
Syslog handler
UDP
TCP
TLS
TLS with Client certificate authentication.
Logger configuration
Domain Mode (host specific configuration)
Canceling management operations
The cancel-non-progressing-operation operation
The find-non-progressing-operation operation
Examining the status of an active operation
Canceling a specific operation
Controlling operation blocking time
Configuration file history
Snapshots
Subsequent Starts
Page 29 of 1804
WildFly 9
Management API reference
Global operations
The read-resource operation
The read-attribute operation
The write-attribute operation
The unset-attribute operation
The read-resource-description operation
The read-operation-names operation
The read-operation-description operation
The read-children-types operation
The read-children-names operation
The read-children-resources operation
The read-attribute-group operation
The read-attribute-group-names operation
Standard Operations
The add operation
The remove operation
Detyped management and the jboss-dmr library
ModelNode and ModelType
Basic ModelNode manipulation
Lists
Properties
ModelType.OBJECT
ModelType.EXPRESSION
ModelType.TYPE
Full list of ModelNode types
Text representation of a ModelNode
JSON representation of a ModelNode
Description of the Management Model
Description of the WildFly Managed Resources
Description of an Attribute
Description of an Operation
Description of an Operation Parameter or Return Value
Arbitrary Descriptors
Description of Parent/Child Relationships
Applying Updates to Runtime Services
Page 30 of 1804
WildFly 9
The native management API
Native Management Client Dependencies
Working with a ModelControllerClient
Creating the ModelControllerClient
Creating an operation request object
Execute the operation and manipulate the result:
Close the ModelControllerClient
Format of a Detyped Operation Request
Simple Operations
Operation Headers
Composite Operations
Operations with a Rollout Plan
Default Rollout Plan
Creating and reusing a Rollout Plan
Format of a Detyped Operation Response
Simple Responses
Response Headers
Basic Composite Operation Responses
Multi-Server Responses
CLI Recipes
Properties
Adding, reading and removing system property using CLI
Overview of all system properties
Configuration
List Subsystems
List description of available attributes and childs
View configuration as XML for domain model or host model
Take a snapshot of what the current domain is
Take the latest snapshot of the host.xml for a particular host
How to get interface address
Runtime
Get all configuration and runtime details from CLI
Scripting
Windows and "Press any key to continue ..." issue
Statistics
Read statistics of active datasources
All WildFly 9 documentation
Page 31 of 1804
WildFly 9
5.1.1 Prerequisites
Before continuing, you should know how to download, install and run WildFly 9. For more information on
these steps, refer here: Getting Started Guide.
Page 32 of 1804
WildFly 9
<management-interfaces>
[...]
<http-interface security-realm="ManagementRealm">
<socket-binding http="management-http"/>
</http-interface>
<management-interfaces>
The HTTP API Endpoint serves two different contexts. One for executing management operations and
another one that allows you to access the web interface:
Domain API: http://<host>:9990/management
Web Console: http://<host>:9990/console
Default URL
By default the web interface can be accessed here: http://localhost:9990/console.
Page 33 of 1804
WildFly 9
The user are stored in a properties file called mgmt-users.properties under standalone/configuration and
domain/configuration depending on the running mode of the server, these files contain the users username
along with a pre-prepared hash of the username along with the name of the realm and the users password.
Although the properties files do not contain the plain text passwords they should still be guarded as
the pre-prepared hashes could be used to gain access to any server with the same realm if the
same user has used the same password.
Page 34 of 1804
WildFly 9
To manipulate the files and add users we provide a utility add-user.sh and add-user.bat to add the users and
generate the hashes, to add a user you should execute the script and follow the guided process.
The full details of the add-user utility are described later but for the purpose of accessing the management
interface you need to enter the following values: Type of user - This will be a 'Management User' to selection option a.
Realm - This MUST match the realm name used in the configuration so unless you have changed the
configuration to use a different realm name leave this set as 'ManagementRealm'.
Username - The username of the user you are adding.
Password - The users password.
Provided the validation passes you will then be asked to confirm you want to add the user and the properties
files will be updated.
For the final question, as this is a user that is going to be accessing the admin console just answer 'n' - this
option will be described later for adding slave host controllers that authenticate against a master domain
controller but that is a later topic.
Updates to the properties file are picked up in real time so either click 'Try Again' on the error page that was
displayed in the browser or navigate to the console again and you should then be prompted to enter the
username and password to connect to the server.
Page 35 of 1804
WildFly 9
<management-interfaces>
<native-interface security-realm="ManagementRealm">
<socket-binding native="management-native"/>
</native-interface>
</native-interf [...]
<management-interfaces>
./bin/jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server
or 'help' for the list of supported commands.
[disconnected /]
[disconnected /] connect
[domain@localhost:9999 /]
[domain@localhost:9999 /] quit
Closed connection to localhost:9999
localhost:9999 is the default host and port combination for the WildFly 9 domain controller client.
Page 36 of 1804
WildFly 9
The host and the port of the server can be provided as an optional parameter, if the server is not listening on
localhost:9999.
./bin/jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server
[disconnected /] connect 192.168.0.10:9999
Connected to standalone controller at 192.168.0.1:9999
The :9999 is not required as the CLI will use port 9999 by default. The port needs to be provided if the server
is listening on some other port.
To terminate the session type quit.
[domain@localhost:9999 /] help
Supported commands:
cn (or cd)
connect
deploy
help (or h)
history
ls
pwn (or pwd)
quit (or q)
undeploy
version
add-jms-queue
remove-jms-queue
add-jms-topic
remove-jms-topic
add-jms-cf
remove-jms-cf
creates
removes
creates
removes
creates
removes
data-source
xa-data-source
Page 37 of 1804
WildFly 9
interactive Mode
The CLI can also be run in non-interactive mode to support scripts and other types of command line or batch
processing. The --command and --commands arguments can be used to pass a command or a list of
commands to execute. Additionally a --file argument is supported which enables CLI commands to be
provided from a text file.
For example the following command can be used to list all the current deployments
The output can be combined with other shell commands for further processing, for example to find out what
.war files are deployed:
Operation Requests
Operation requests allow for low level interaction with the management model. They are different from the
high level commands (i.e. create-jms-queue) in that they allow you to read and modify the server
configuration as if you were editing the XML configuration files directly. The configuration is represented as a
tree of addressable resources, where each node in the tree (aka resource) offers a set of operations to
execute.
An operation request basically consists of three parts: The address, an operation name and an optional set
of parameters.
The formal specification for an operation request is:
For example:
/profile=production/subsystem=threads/bounded-queue-thread-pool=pool1:write-core-threads
(count=0, per-cpu=20)
Page 38 of 1804
WildFly 9
Tab Completion
Tab-completion is supported for all commands and options, i.e. node-types and node-names,
operation names and parameter names. We are also considering adding aliases that are less
verbose for the user, and will translate into the corresponding operation requests in the
background.
Whitespaces between the separators in the operation request strings are not significant.
Addressing resources
Operation requests might not always have the address part or the parameters. E.g.
:read-resource
which will list all the node types for the current node.
To syntactically disambiguate between the commands and operations, operations require one of the
following prefixes:
To execute an operation against the current node, e.g.
cd subsystem=web
:read-resource(recursive="true")
cd subsystem=web
./connector=http:read-resource
/subsystem=threads:read-resource
Page 39 of 1804
WildFly 9
add
read-attribute
read-children-names
read-children-resources
read-children-types
read-operation-description
read-operation-names
read-resource
read-resource-description
remove
validate-address
write-attribute
For a list of specific operations (e.g. operations that relate to the logging subsystem) you can always query
the model itself. For example, to read the operations supported by the logging subsystem resource on a
standalone server:
[[standalone@localhost:9999 /] /subsystem=logging:read-operation-names
{
"outcome" => "success",
"result" => [
"add",
"change-root-log-level",
"read-attribute",
"read-children-names",
"read-children-resources",
"read-children-types",
"read-operation-description",
"read-operation-names",
"read-resource",
"read-resource-description",
"remove-root-logger",
"root-logger-assign-handler",
"root-logger-unassign-handler",
"set-root-logger",
"validate-address",
"write-attribute"
]
}
As you can see, the logging resource offers four additional operations, namely root-logger-assign-handler,
root-logger-unassign-handler , set-root-logger and remove-root-logger.
Further documentation about a resource or operation can be retrieved through the description:
Page 40 of 1804
WildFly 9
[standalone@localhost:9999 /]
/subsystem=logging:read-operation-description(name=change-root-log-level)
{
"outcome" => "success",
"result" => {
"operation-name" => "change-root-log-level",
"description" => "Change the root logger level.",
"request-properties" => {"level" => {
"type" => STRING,
"description" => "The log level specifying which message levels will be logged by
this logger.
Message levels lower than this value will be discarded.",
"required" => true
}}
}
}
Full model
To see the full model enter :read-resource(recursive=true).
Command History
Command (and operation request) history is enabled by default. The history is kept both in-memory and in a
file on the disk, i.e. it is preserved between the command line sessions. The history file name is
.jboss-cli-history and is automatically created in the user's home directory. When the command line interface
is launched this file is read and the in-memory history is initialized with its content.
While in the command line session, you can use the arrow keys to go back and forth in the history
of commands and operations.
To manipulate the history you can use history command. If executed without any arguments, it will print all
the recorded commands and operations (up to the configured maximum, which defaults to 500) from the
in-memory history.
history supports three optional arguments:
disable - will disable history expansion (but will not clear the previously recorded history);
enabled - will re-enable history expansion (starting from the last recorded command before the history
expansion was disabled);
clear - will clear the in-memory history (but not the file one).
Page 41 of 1804
WildFly 9
Batch Processing
The batch mode allows one to group commands and operations and execute them together as an atomic
unit. If at least one of the commands or operations fails, all the other successfully executed commands and
operations in the batch are rolled back.
Not all of the commands are allowed in the batch. For example, commands like cd, ls, help, etc. are not
allowed in the batch since they don't translate into operation requests. Only the commands that translate into
operation requests are allowed in the batch. The batch, actually, is executed as a composite operation
request.
The batch mode is entered by executing command batch.
[standalone@localhost:9999 /] batch
[standalone@localhost:9999 / #] /subsystem=datasources/data-source="java\:\/H2DS":enable
[standalone@localhost:9999 / #] /subsystem=messaging/jms-queue="newQueue":add
[standalone@localhost:9999 / #] run-batch
The batch executed successfully.
[standalone@localhost:9999 / #] holdback-batch
[standalone@localhost:9999 /]
[standalone@localhost:9999 /] batch
Re-activated batch
#1 /subsystem=datasources/data-source=java:/H2DS:\/H2DS:enable
There are several other notable batch commands available as well (tab complete to see the list):
clear-batch
edit-batch-line (e.g. edit-batch line 3 create-jms-topic name=mytopic)
remove-batch-line (e.g. remove-batch-line 3)
move-batch-line (e.g. move-batch-line 3 1)
discard-batch
Page 42 of 1804
WildFly 9
The XML configuration files act as a central, authoritative source of configuration. Any configuration
changes made via the web interface or the CLI are persisted back to the XML configuration files. If
a domain or standalone server is offline, the XML configuration files can be hand edited as well,
and any changes will be picked up when the domain or standalone server is next started. However,
users are encouraged to use the web interface or the CLI in preference to making offline edits to
the configuration files. External changes made to the configuration files while processes are
running will not be detected, and may be overwritten.
Page 43 of 1804
WildFly 9
Standalone Server
For many use cases, the centralized management capability available via a managed domain is not
necessary. For these use cases, a WildFly 8 instance can be run as a "standalone server". A standalone
server instance is an independent process, much like an JBoss Application Server 3, 4, 5, or 6 instance is.
Standalone instances can be launched via the standalone.sh or standalone.bat launch scripts.
If more than one standalone instance is launched and multi-server management is desired, it is the user's
responsibility to coordinate management across the servers. For example, to deploy an application across all
of the standalone servers, the user would need to individually deploy the application on each server.
It is perfectly possible to launch multiple standalone server instances and have them form an HA cluster, just
like it was possible with JBoss Application Server 3, 4, 5 and 6.
Managed Domain
One of the primary new features of WildFly 8 is the ability to manage multiple WildFly instances from a single
control point. A collection of such servers is referred to as the members of a "domain" with a single Domain
Controller process acting as the central management control point. All of the WildFly 8 instances in the
domain share a common management policy, with the Domain Controller acting to ensure that each server
is configured according to that policy. Domains can span multiple physical (or virtual) machines, with all
WildFly 8 instances on a given host under the control of a special Host Controller process. One Host
Controller instance is configured to act as the central Domain Controller. The Host Controller on each host
interacts with the Domain Controller to control the lifecycle of the application server instances running on its
host and to assist the Domain Controller in managing them.
When you launch a WildFly 8 managed domain on a host (via the domain.sh or domain.bat launch
scripts) your intent is to launch a Host Controller and usually at least one WildFly instance. On one of the
hosts the Host Controller should be configured to act as the Domain Controller. See [WLFY8:Domain Setup]
for details.
The following is an example managed domain topology:
Page 44 of 1804
WildFly 9
Host
Each "Host" box in the above diagram represents a physical or virtual host. A physical host can contain zero,
one or more server instances.
Page 45 of 1804
WildFly 9
Host Controller
When the domain.sh or domain.bat script is run on a host, a process known as a Host Controller is
launched. The Host Controller is solely concerned with server management; it does not itself handle
application server workloads. The Host Controller is responsible for starting and stopping the individual
application server processes that run on its host, and interacts with the Domain Controller to help manage
them.
Each Host Controller by default reads its configuration from the domain/configuration/host.xml file
located in the unzipped WildFly 8 installation on its host's filesystem. The host.xml file contains
configuration information that is specific to the particular host. Primarily:
the listing of the names of the actual WildFly 8 instances that are meant to run off of this installation.
configuration of how the Host Controller is to contact the Domain Controller to register itself and
access the domain configuration. This may either be configuration of how to find and contact a remote
Domain Controller, or a configuration telling the Host Controller to itself act as the Domain Controller.
configuration of items that are specific to the local physical installation. For example, named interface
definitions declared in domain.xml (see below) can be mapped to an actual machine-specific IP
address in host.xml. Abstract path names in domain.xml can be mapped to actual filesystem
paths in host.xml.
Domain Controller
One Host Controller instance is configured to act as the central management point for the entire domain, i.e.
to be the Domain Controller. The primary responsibility of the Domain Controller is to maintain the domain's
central management policy, to ensure all Host Controllers are aware of its current contents, and to assist the
Host Controllers in ensuring any running application server instances are configured in accordance with this
policy. This central management policy is stored by default in the domain/configuration/domain.xml
file in the unzipped WildFly 8 installation on Domain Controller's host's filesystem.
A domain.xml file must be located in the domain/configuration directory of an installation that's
meant to run the Domain Controller. It does not need to be present in installations that are not meant to run a
Domain Controller; i.e. those whose Host Controller is configured to contact a remote Domain Controller.
The presence of a domain.xml file on such a server does no harm.
The domain.xml file includes, among other things, the configuration of the various "profiles" that WildFly 8
instances in the domain can be configured to run. A profile configuration includes the detailed configuration
of the various subsystems that comprise that profile (e.g. an embedded JBoss Web instance is a subsystem;
a JBoss TS transaction manager is a subsystem, etc). The domain configuration also includes the definition
of groups of sockets that those subsystems may open. The domain configuration also includes the definition
of "server groups":
Page 46 of 1804
WildFly 9
Server Group
A server group is set of server instances that will be managed and configured as one. In a managed domain
each application server instance is a member of a server group. (Even if the group only has a single server,
the server is still a member of a group.) It is the responsibility of the Domain Controller and the Host
Controllers to ensure that all servers in a server group have a consistent configuration. They should all be
configured with the same profile and they should have the same deployment content deployed.
The domain can have multiple server groups. The above diagram shows two server groups, "ServerGroupA"
and "ServerGroupB". Different server groups can be configured with different profiles and deployments; for
example in a domain with different tiers of servers providing different services. Different server groups can
also run the same profile and have the same deployments; for example to support rolling application
upgrade scenarios where a complete service outage is avoided by first upgrading the application on one
server group and then upgrading a second server group.
An example server group definition is as follows:
Page 47 of 1804
WildFly 9
Server
Each "Server" in the above diagram represents an actual application server instance. The server runs in a
separate JVM process from the Host Controller. The Host Controller is responsible for launching that
process. (In a managed domain the end user cannot directly launch a server process from the command
line.)
The Host Controller synthesizes the server's configuration by combining elements from the domain wide
configuration (from domain.xml ) and the host-specific configuration (from host.xml ).
Page 48 of 1804
WildFly 9
Extensions
An extension is a module that extends the core capabilities of the server. The WildFly 8 core is very simple
and lightweight; most of the capabilities people associate with an application server are provided via
extensions. An extension is packaged as a module in the modules folder. The user indicates that they want
a particular extension to be available by including an <extension/> element naming its module in the
domain.xml or standalone.xml file.
<extensions>
[...]
<extension
<extension
<extension
<extension
</extensions>
module="org.jboss.as.transactions"/>
module="org.jboss.as.web" />
module="org.jboss.as.webservices" />
module="org.jboss.as.weld" />
Paths
A logical name for a filesystem path. The domain.xml, host.xml and standalone.xml configurations
all include a section where paths can be declared. Other sections of the configuration can then reference
those paths by their logical name, rather than having to include the full details of the path (which may vary on
different machines). For example, the logging subsystem configuration includes a reference to the "
jboss.server.log.dir" path that points to the server's "log" directory.
Page 49 of 1804
WildFly 9
WildFly 8 automatically provides a number of standard paths without any need for the user to configure them
in a configuration file:
jboss.home - the root directory of the WildFly distribution
user.home - user's home directory
user.dir - user's current working directory
java.home - java installation directory
jboss.server.base.dir - root directory for an individual server instance
jboss.server.data.dir - directory the server will use for persistent data file storage
jboss.server.log.dir - directory the server will use for log file storage
jboss.server.tmp.dir - directory the server will use for temporary file storage
jboss.domain.servers.dir - directory under which a host controller will create the working area
for individual server instances (managed domain mode only)
Users can add their own paths or override all except the first 5 of the above by adding a <path/> element
to their configuration file.
<path name="x"/>
Such a configuration simply says, "There is a path named 'x' that other parts of the domain.xml
configuration can reference. The actual filesystem location pointed to by 'x' is host-specific and will be
specified in each machine's host.xml file." If this approach is used, there must be a path element in each
machine's host.xml that specifies what the actual filesystem path is:
A <path/> element in a standalone.xml must include the specification of the actual filesystem path.
Page 50 of 1804
WildFly 9
Interfaces
A logical name for a network interface/IP address/host name to which sockets can be bound. The
domain.xml, host.xml and standalone.xml configurations all include a section where interfaces can
be declared. Other sections of the configuration can then reference those interfaces by their logical name,
rather than having to include the full details of the interface (which may vary on different machines). An
interface configuration includes the logical name of the interface as well as information specifying the criteria
to use for resolving the actual physical address to use. See Interfaces and ports for further details.
An <interface/> element in a domain.xml need not include anything more than the name attribute; i.e. it
need not include any information indicating what the actual IP address associated with the name is:
<interface name="internal"/>
Such a configuration simply says, "There is an interface named 'internal' that other parts of the domain.xml
configuration can reference. The actual IP address pointed to by 'internal' is host-specific and will be
specified in each machine's host.xml file." If this approach is used, there must be an interface element in
each machine's host.xml that specifies the criteria for determining the IP address:
<interface name="internal">
<nic name="eth1"/>
</interface>
An <interface/> element in a standalone.xml must include the criteria for determining the IP address.
Page 51 of 1804
WildFly 9
System Properties
System property values can be set in a number of places in domain.xml, host.xml and
standalone.xml. The values in standalone.xml are set as part of the server boot process. Values in
domain.xml and host.xml are applied to servers when they are launched.
When a system property is configured in domain.xml or host.xml, the servers it ends up being applied to
depends on where it is set. Setting a system property in a child element directly under the domain.xml root
results in the property being set on all servers. Setting it in a <system-property/> element inside a
<server-group/> element in domain.xml results in the property being set on all servers in the group.
Setting it in a child element directly under the host.xml root results in the property being set on all servers
controlled by that host's Host Controller. Finally, setting it in a <system-property/> element inside a
<server/> element in host.xml result in the property being set on that server. The same property can be
configured in multiple locations, with a value in a <server/> element taking precedence over a value
specified directly under the host.xml root element, the value in a host.xml taking precedence over
anything from domain.xml, and a value in a <server-group/> element taking precedence over a value
specified directly under the domain.xml root element.
Page 52 of 1804
WildFly 9
Address
All WildFly management resources are organized in a tree. The path to the node in the tree for a particular
resource is its address. Each segment in a resource's address is a key/value pair:
The key is the resource's type, in the context of its parent. So, for example, the root resource for a
standalone server has children of type subsystem, interface, socket-binding, etc. The
resource for the subsystem that provides the AS's webserver capability has children of type
connector and virtual-server. The resource for the subsystem that provides the AS's
messaging server capability has, among others, children of type jms-queue and jms-topic.
The value is the name of a particular resource of the given type, e.g web or messaging for
subsystems or http or https for web subsystem connectors.
The full address for a resource is the ordered list of key/value pairs that lead from the root of the tree to the
resource. Typical notation is to separate the elements in the address with a '/' and to separate the key and
the value with an '=':
/subsystem=web/connector=http
/subsystem=messaging/jms-queue=testQueue
/interface=public
When using the HTTP API, a '/' is used to separate the key and the value instead of an '=':
http://localhost:9990/management/subsystem/web/connector/http
http://localhost:9990/management/subsystem/messaging/jms-queue/testQueue
http://localhost:9990/management/interface/public
Operations
Querying or modifying the state of a resource is done via an operation. An operation has the following
characteristics:
A string name
Zero or more named parameters. Each parameter has a string name, and a value of type
org.jboss.dmr.ModelNode (or, when invoked via the CLI, the text representation of a
ModelNode; when invoked via the HTTP API, the JSON representation of a ModelNode.)
Parameters may be optional.
A return value, which will be of type org.jboss.dmr.ModelNode (or, when invoked via the CLI, the
text representation of a ModelNode; when invoked via the HTTP API, the JSON representation of a
ModelNode.)
Every resource except the root resource will have an add operation and should have a remove operation
("should" because in WildFly 8 many do not). The parameters for the add operation vary depending on the
resource. The remove operation has no parameters.
Page 53 of 1804
WildFly 9
There are also a number of "global" operations that apply to all resources. See Global operations for full
details.
The operations a resource supports can themselves be determined by invoking an operation: the
read-operation-names operation. Once the name of an operation is known, details about its parameters
and return value can be determined by invoking the read-operation-description operation. For
example, to learn the names of the operations exposed by the root resource for a standalone server, and
then learn the full details of one of them, via the CLI one would:
Page 54 of 1804
WildFly 9
[standalone@localhost:9999 /] :read-operation-names
{
"outcome" => "success",
"result" => [
"add-namespace",
"add-schema-location",
"delete-snapshot",
"full-replace-deployment",
"list-snapshots",
"read-attribute",
"read-children-names",
"read-children-resources",
"read-children-types",
"read-config-as-xml",
"read-operation-description",
"read-operation-names",
"read-resource",
"read-resource-description",
"reload",
"remove-namespace",
"remove-schema-location",
"replace-deployment",
"shutdown",
"take-snapshot",
"upload-deployment-bytes",
"upload-deployment-stream",
"upload-deployment-url",
"validate-address",
"write-attribute"
]
}
[standalone@localhost:9999 /] :read-operation-description(name=upload-deployment-url)
{
"outcome" => "success",
"result" => {
"operation-name" => "upload-deployment-url",
"description" => "Indicates that the deployment content available at the included URL
should be added to the deployment content repository. Note that this operation does not indicate
the content should be deployed into the runtime.",
"request-properties" => {"url" => {
"type" => STRING,
"description" => "The URL at which the deployment content is available for upload to
the domain's or standalone server's deployment content repository.. Note that the URL must be
accessible from the target of the operation (i.e. the Domain Controller or standalone server).",
"required" => true,
"min-length" => 1,
"nillable" => false
}},
"reply-properties" => {
"type" => BYTES,
"description" => "The hash of managed deployment content that has been uploaded to
the domain's or standalone server's deployment content repository.",
"min-length" => 20,
"max-length" => 20,
"nillable" => false
}
}
}
Page 55 of 1804
WildFly 9
See Descriptions below for more on how to learn about the operations a resource exposes.
Attributes
Management resources expose information about their state as attributes. Attributes have string name, and
a value of type org.jboss.dmr.ModelNode (or: for the CLI, the text representation of a ModelNode; for
HTTP API, the JSON representation of a ModelNode.)
Attributes can either be read-only or read-write. Reading and writing attribute values is done via the global
read-attribute and write-attribute operations.
The read-attribute operation takes a single parameter "name" whose value is a the name of the
attribute. For example, to read the "port" attribute of a socket-binding resource via the CLI:
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets/socket-binding=https:read-attribute(name=port)
{
"outcome" => "success",
"result" => 8443
}
If an attribute is writable, the write-attribute operation is used to mutate its state. The operation takes
two parameters:
name the name of the attribute
value the value of the attribute
For example, to read the "port" attribute of a socket-binding resource via the CLI:
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets/socket-binding=https:write-attribute(name=port,value=8444){"outcome"
=> "success"}
Page 56 of 1804
WildFly 9
[standalone@localhost:9999 /] /subsystem=web/connector=http:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"bytesReceived" => "0",
"bytesSent" => "0",
"errorCount" => "0",
"maxTime" => "0",
"processingTime" => "0",
"protocol" => "HTTP/1.1",
"requestCount" => "0",
"scheme" => "http",
"socket-binding" => "http",
"ssl" => undefined,
"virtual-server" => undefined
}
}
Omit the "include-runtime" parameter (or set it to "false") to limit output to those attributes whose values are
stored in the persistent configuration:
[standalone@localhost:9999 /] /subsystem=web/connector=http:read-resource
{
"outcome" => "success",
"result" => {
"protocol" => "HTTP/1.1",
"scheme" => "http",
"socket-binding" => "http",
"ssl" => undefined,
"virtual-server" => undefined
}
}
See Descriptions below for how to learn more about the attributes a particular resource exposes.
Page 57 of 1804
WildFly 9
Children
Management resources may support child resources. The types of children a resource supports (e.g.
connector for the web subsystem resource) can be obtained by querying the resource's description (see
Descriptions below) or by invoking the read-children-types operation. Once you know the legal child
types, you can query the names of all children of a given type by using the global read-children-types
operation. The operation takes a single parameter "child-type" whose value is the type. For example, a
resource representing a socket binding group has children. To find the type of those children and the names
of resources of that type via the CLI one could:
[standalone@localhost:9999 /] /socket-binding-group=standard-sockets:read-children-types
{
"outcome" => "success",
"result" => ["socket-binding"]
}
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets:read-children-names(child-type=socket-binding)
{
"outcome" => "success",
"result" => [
"http",
"https",
"jmx-connector-registry",
"jmx-connector-server",
"jndi",
"osgi-http",
"remoting",
"txn-recovery-environment",
"txn-status-manager"
]
}
Descriptions
All resources expose metadata that describes their attributes, operations and child types. This metadata is
itself obtained by invoking one or more of the global operations each resource supports. We showed
examples of the read-operation-names, read-operation-description, read-children-types
and read-children-names operations above.
The read-resource-description operation can be used to find the details of the attributes and child
types associated with a resource. For example, using the CLI:
Page 58 of 1804
WildFly 9
[standalone@localhost:9999 /] /socket-binding-group=standard-sockets:read-resource-description
{
"outcome" => "success",
"result" => {
"description" => "Contains a list of socket configurations.",
"head-comment-allowed" => true,
"tail-comment-allowed" => false,
"attributes" => {
"name" => {
"type" => STRING,
"description" => "The name of the socket binding group.",
"required" => true,
"head-comment-allowed" => false,
"tail-comment-allowed" => false,
"access-type" => "read-only",
"storage" => "configuration"
},
"default-interface" => {
"type" => STRING,
"description" => "Name of an interface that should be used as the interface for
any sockets that do not explicitly declare one.",
"required" => true,
"head-comment-allowed" => false,
"tail-comment-allowed" => false,
"access-type" => "read-write",
"storage" => "configuration"
},
"port-offset" => {
"type" => INT,
"description" => "Increment to apply to the base port values defined in the
socket bindings to derive the runtime values to use on this server.",
"required" => false,
"head-comment-allowed" => true,
"tail-comment-allowed" => false,
"access-type" => "read-write",
"storage" => "configuration"
}
},
"operations" => {},
"children" => {"socket-binding" => {
"description" => "The individual socket configurtions.",
"min-occurs" => 0,
"model-description" => undefined
}}
}
}
Note the "operations" => }} in the output above. If the command had included the
{{operations parameter (i.e.
/socket-binding-group=standard-sockets:read-resource-description(operations=true)
) the output would have included the description of each operation supported by the resource.
Page 59 of 1804
WildFly 9
See the Global operations section for details on other parameters supported by the
read-resource-description operation and all the other globally available operations.
Standalone server
The structure of the managed resource tree is quite close to the structure of the standalone.xml
configuration file.
The root resource
extension extensions installed in the server
path paths available on the server
system-property system properties set as part of the configuration (i.e. not on the
command line)
core-service=management the server's core management services
core-service=service-container resource for the JBoss MSC ServiceContainer
that's at the heart of the AS
subsystem the subsystems installed on the server. The bulk of the management model will
be children of type subsystem
interface interface configurations
socket-binding-group the central resource for the server's socket bindings
socket-binding individual socket binding configurations
deployment available deployments on the server
Page 60 of 1804
WildFly 9
Managed domain
In a managed domain, the structure of the managed resource tree spans the entire domain, covering both
the domain wide configuration (e.g. what's in domain.xml, the host specific configuration for each host (e.g.
what's in host.xml, and the resources exposed by each running application server. The Host Controller
processes in a managed domain provide access to all or part of the overall resource tree. How much is
available depends on whether the management client is interacting with the Host Controller that is acting as
the master Domain Controller. If the Host Controller is the master Domain Controller, then the section of the
tree for each host is available. If the Host Controller is a slave to a remote Domain Controller, then only the
portion of the tree associated with that host is available.
Page 61 of 1804
WildFly 9
The root resource for the entire domain. The persistent configuration associated with this resource
and its children, except for those of type host, is persisted in the domain.xml file on the Domain
Controller.
extension extensions available in the domain
path paths available on across the domain
system-property system properties set as part of the configuration (i.e. not on the
command line) and available across the domain
profile sets of subsystem configurations that can be assigned to server groups
subsystem configuration of subsystems that are part of the profile
interface interface configurations
socket-binding-group sets of socket bindings configurations that can be applied to
server groups
socket-binding individual socket binding configurations
deployment deployments available for assignment to server groups
server-group server group configurations
host the individual Host Controllers. Each child of this type represents the root resource for a
particular host. The persistent configuration associated with one of these resources or its
children is persisted in the host's host.xml file.
path paths available on each server on the host
system-property system properties to set on each server on the host
core-service=management the Host Controller's core management services
interface interface configurations that apply to the Host Controller or servers on the
host
jvm JVM configurations that can be applied when launching servers
server-config configuration describing how the Host Controller should launch a
server; what server group configuration to use, and any server-specific overrides of
items specified in other resources
server the root resource for a running server. Resources from here and below are
not directly persisted; the domain-wide and host level resources contain the persistent
configuration that drives a server
extension extensions installed in the server
path paths available on the server
system-property system properties set as part of the configuration (i.e. not
on the command line)
core-service=management the server's core management services
core-service=service-container resource for the JBoss MSC
ServiceContainer that's at the heart of the AS
subsystem the subsystems installed on the server. The bulk of the
management model will be children of type subsystem
interface interface configurations
socket-binding-group the central resource for the server's socket bindings
socket-binding individual socket binding configurations
deployment available deployments on the server
Page 62 of 1804
WildFly 9
[standalone@localhost:9999 /] :read-children-names(child-type=interface)
{
"outcome" => "success",
"result" => [
"management",
"public"
]
}
This means the server in question declares two interfaces: One is referred to as " management"; the other
one "public". The "management" interface is used for all components and services that are required by the
management layer (i.e. the HTTP Management Endpoint). The "public" interface binding is used for any
application related network communication (i.e. Web, Messaging, etc). There is nothing special about these
names; interfaces can be declared with any name. Other sections of the configuration can then reference
those interfaces by their logical name, rather than having to include the full details of the interface (which, on
servers in a management domain, may vary on different machines).
The domain.xml, host.xml and standalone.xml configuration files all include a section where
interfaces can be declared. If we take a look at the XML declaration it reveals the selection criteria. The
criteria is one of two types: either a single element indicating that the interface should be bound to a wildcard
address, or a set of one or more characteristics that an interface or address must have in order to be a valid
match. The selection criteria in this example are specific IP addresses for each interface:
<interfaces>
<interface name="management">
<inet-address value="127.0.0.1"/>
</interface>
<interface name="public">
<inet-address value="127.0.0.1"/>
</interface>
</interfaces>
Page 63 of 1804
WildFly 9
<interface name="global">
<!-- Use the wildcard address -->
<any-address/>
</interface>
<interface name="external">
<nic name="eth0"/>
</interface>
<interface name="default">
<!-- Match any interface/address on the right subnet if it's
up, supports multicast and isn't point-to-point -->
<subnet-match value="192.168.0.0/16"/>
<up/>
<multicast/>
<not>
<point-to-point/>
</not>
</interface>
Page 64 of 1804
WildFly 9
Page 65 of 1804
WildFly 9
Page 66 of 1804
WildFly 9
IP address literals
To change the IP address literals referenced in standalone.xml (or domain.xml), first visit the interface
declarations and ensure that valid IPv6 addresses are being used as interface values. For example, to
change the default configuration in which the loopback interface is used as the primary interface, change
from the IPv4 loopback address:
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:[::1]}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:[::1]}"/>
</interface>
</interfaces>
Note that when embedding IPv6 address literals in the substitution expression, square brackets surrounding
the IP address literal are used to avoid ambiguity. This follows the convention for the use of IPv6 literals in
URLs.
Over and above making such changes for the interface definitions, you should also check the rest of your
configuration file and adjust IP address literals from IPv4 to IPv6 as required.
Page 67 of 1804
WildFly 9
General Structure
The general structure of a management realm definition is: -
<security-realm name="ManagementRealm">
<plug-ins></plug-ins>
<server-identities></server-identities>
<authentication></authentication>
<authorization></authorization>
</security-realm>
plug-ins - This is an optional element that is used to define modules what will be searched for
security realm PlugInProviders to extend the capabilities of the security realms.
server-identities - An optional element to define the identity of the server as visible to the
outside world, this applies to both inbound connection to a resource secured by the realm and to
outbound connections also associated with the realm.
One example is the SSL identity of the server, for inbound connections this will control the identity of the
server as the SSL connection is established, for outbound connections this same identity can be used where
CLIENT-CERT style authentication is being performed.
A second example is where the server is establishing an outbound connection that requires username /
password authentication - this element can be used to define that password.
authentication - This is probably the most important element that will be used within a security
realm definition and mostly applies to inbound connections to the server, this element defines which
backing stores will be used to provide the verification of the inbound connection.
This element is optional as there are some scenarios where it will not be required such as if a realm is being
defined for an outbound connection using a username and password.
authorization - This is the final optional element and is used to define how roles are loaded for an
authenticated identity. At the moment this is more applicable for realms used for access to EE
deployments such as web applications or EJBs but this will also become relevant as we add role
based authorization checks to the management model.
Using a Realm
After a realm has been defined it needs to be associated with an inbound or outbound connection for it to be
used, the following are some examples where these associations are used within the WildFly
8 configuration.
Page 68 of 1804
WildFly 9
Inbound Connections
Management Interfaces
Either within the standalone.xml or host.xml configurations the security realms can be associated with
the management interfaces as follows: -
<native-interface security-realm="ManagementRealm">...</native-interface>
<http-interface security-realm="ManagementRealm">...</http-interface>
If the security-realm attribute is omitted or removed from the interface definition it means that access to
that interface will be unsecured
By default we do bind these interfaces to the loopback address so that the interfaces are not
accessible remotely out of the box, however do be aware that if these interfaces are then
unsecured any other local user will be able to control and administer the WildFly 8 installation.
Also do note that the security-realm attribute is defined on each interface independently, this
means that you could define a different security realm for each - this may be applicable if say you
want the administrators to only access over the HTTP interface and leave only local users to
access the native interface.
Remoting Subsystem
The Remoting subsystem exposes a connector to allow for inbound comunications with JNDI and the EJB
subsystem by default we associate the ApplicationRealm with this connection.
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<connector name="remoting-connector" socket-binding="remoting"
security-realm="ApplicationRealm"/>
</subsystem>
Page 69 of 1804
WildFly 9
Outbound Connections
Remoting Subsystem
Outbound connections can also be defined within the Remoting subsystem, these are typically used for
remote EJB invocations from one AS server to another, in this scenario the security realm is used to obtain
the server identity either it's password for X.509 certificate and possibly a trust store to verify the certificate of
the remote host.
Even if the referenced realm contains username and password authentication configuration the
client side of the connection will NOT use this to verify the remote server.
<remote-outbound-connection name="remote-ejb-connection"
outbound-socket-binding-ref="binding-remote-ejb-connection"
username="user1"
security-realm="PasswordRealm">
The security realm is only used to obtain the password for this example, as you can see here the
username is specified separately.
<domain-controller>
<remote host="${jboss.domain.master.address}" port="${jboss.domain.master.port:9999}"
security-realm="ManagementRealm"/>
</domain-controller>
By default when a slave host controller authenticates against the master domain controller it uses
its configured name as its username. If you want to override the username used for authentication
a username attribute can be added to the <remote /> element.
Page 70 of 1804
WildFly 9
Authentication
One of the primary functions of the security realms is to define the user stores that will be used to verify the
identity of inbound connections, the actual approach taken at the transport level is based on the capabilities
of these backing store definitions. The security realms are used to secure inbound connections for both the
http management interface and for inbound remoting connections for both the native management interface
and to access other services exposed over remoting - because of this there are some small differences
between how the realm is used for each of these.
At the transport level we support the following authentication mechanisms.
HTTP
Remoting (SASL)
None
Anonymous
N/A
Digest
Digest
Basic
Plain
Page 71 of 1804
WildFly 9
The final mechanism Client-Cert allows X.509 certificates to be used to verify the identity of the remote
client.
One point bearing in mind is that it is possible that an association with a realm can mean that a
single incoming connection has the ability to choose between one or more authentication
mechanisms. As an example it is possible that an incoming remoting connection could choose
between 'Client Cert', A username password mechanism or 'JBoss Local User' for authentication this would allow say a local user to use the local mechanism, a remote user to supply their
username and password whilst a remote script could make a call and authenticate using a
certificate.
Authorization
The actual security realms are not involved in any authorization decisions however they can be configured to
load a users roles which will subsequently be used to make authorization decisions - when references to
authorization are seen in the context of security realms it is this loading of roles that is being referred to.
For the loading of roles the process is split out to occur after the authentication step so after a user has been
authenticated a second step will occur to load the roles based on the username they used to authenticate
with.
The examples here are taken from the standalone configuration however the descriptions are
equally applicable to domain mode, one point worth noting is that all security realms defined in the
host.xml are available to be referenced within the domain configuration for the servers running
on that host controller.
Page 72 of 1804
WildFly 9
Management Realm
<security-realm name="ManagementRealm">
<authentication>
<local default-user="$local"/>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
</security-realm>
The realm ManagementRealm is the simplest realm within the default configuration, this realm simply
enables two authentication mechanisms, the local mechanism and username/password authentication which
will be using Digest authentication.
local
When using the local mechanism it is optional for remote clients to send a username to the server, this
configuration specifies that where clients do not send a username it will be assumed that the clients
username is $local - the <local /> element can also be configured to allow other usernames to be
specified by remote clients however for the default configuration this is not enabled so is not supported.
properties
For username / password authentication the users details will be loaded from the file
mgmt-users.properties which is located in {jboss.home}/standalone/configuration or {
jboss.home}/domain/configuration depending on the running mode of the server.
Each user is represented on their own line and the format of each line is username=HASH where HASH is a
pre-prepared hash of the users password along with their username and the name of the realm which in this
case is ManagementRealm.
You do not need to worry about generating the entries within the properties file as we provide a
utility add-user.sh or add-user.bat to add the users, this utility is described in more detail
below.
By pre-hashing the passwords in the properties file it does mean that if the user has used the same
password on different realms then the contents of the file falling into the wrong hands does not
nescesarily mean all accounts are compromised. HOWEVER the contents of the files do still need
to be protected as they can be used to access any server where the realm name is the same and
the user has the same username and password pair.
Page 73 of 1804
WildFly 9
Application Realm
<security-realm name="ApplicationRealm">
<authentication>
<local default-user="$local" allowed-users="*"/>
<properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization>
<properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
The realm ApplicationRealm is a slightly more complex realm as this is used for both
Authentication
The authentication configuration is very similar to the ManagementRealm in that it enabled both the local
mechanism and a username/password based Digest mechanism.
local
The local configuration is similar to the ManagementRealm in that where the remote user does not supply a
username it will be assumed that the username is $local, however in addition to this there is now an
allowed-users attribute with a value of '*' - this means that the remote user can specify any username
and it will be accepted over the local mechanism provided that the local verification is a success.
To restrict the usernames that can be specified by the remote user a comma separated list of
usernames can be specified instead within the allowed-users attribute.
properties
The properties definition works in exactly the same way as the definition for ManagementRealm except now
the properties file is called application-users.properties.
Page 74 of 1804
WildFly 9
Authorization
The contents of the Authorization element are specific to the ApplicationRealm, in this case a
properties file is used to load a users roles.
The properties file is called application-roles.properties and is located in {
jboss.home}/standalone/configuration or {jboss.home}/domain/configuration depending
on the running mode of the server. The format of this file is username=ROLES where ROLES is a comma
separated list of the users roles.
As the loading of a users roles is a second step this is where it may be desirable to restrict which
users can use the local mechanism so that some users still require username and password
authentication for their roles to be loaded.
Page 75 of 1804
WildFly 9
When applications are deployed to the application server they are associated with a security domain within
the security subsystem, the other security domain is provided to work with the ApplicationRealm, this
domain is defined with a pair of login modules Remoting and RealmDirect.
Remoting
The Remoting login module is used to check if the request currently being authenticated is a request
received over a Remoting connection, if so the identity that was created during the authentication process is
used and associated with the current request.
If the request did not arrive over a Remoting connection this module does nothing and allows the JAAS
based login to continue to the next module.
RealmDirect
The RealmDirect login module makes use of a security realm to authenticate the current request if that did
not occur in the Remoting login module and then use the realm to load the users roles, by default this login
module assumes the realm to use is called ApplicationRealm although other names can be overridden
using the "realm" module-option.
The advantage of this approach is that all of the backing store configuration can be left within the realm with
the security domain just delegating to the realm.
user.sh
For use with the default configuration we supply a utility add-user which can be used to manage the
properties files for the default realms used to store the users and their roles.
The add-user utility can be used to manage both the users in the ManagementRealm and the users in the
ApplicationRealm, changes made apply to the properties file used both for domain mode and standalone
mode.
Page 76 of 1804
WildFly 9
After you have installed your application server and decided if you are going to run in standalone
mode or domain mode you can delete the parent folder for the mode you are not using, the
add-user utility will then only be managing the properties file for the mode in use.
The add-user utility is a command line utility however it can be run in both interactive and non-interactive
mode. Depending on your platform the script to run the add-user utility is either add-user.sh or
add-user.bat which can be found in {jboss.home}/bin.
This guide now contains a couple of examples of this utility in use to accomplish the most common tasks.
Adding a User
Adding users to the properties files is the primary purpose of this utility.
The server caches the contents of the properties files in memory, however the server does check
the modified time of the properties files on each authentication request and re-load if the time has
been updated - this means all changes made by this utility are immediately applied to any running
server.
A Management User
The default name of the realm for management users is ManagementRealm, when the utility
prompts for the realm name just accept the default unless you have switched to a different realm.
Page 77 of 1804
WildFly 9
Interactive Mode
Here we have added a new Management User called adminUser, as you can see some of the questions
offer default responses so you can just press enter without repeating the default value.
For now just answer n or no to the final question, adding users to be used by processes is described in more
detail in the domain management chapter.
Interactive Mode
To add a user in non-interactive mode the command ./add-user.sh {username} {password} can be
used.
If you add users using this approach there is a risk that any other user that can view the list of
running process may see the arguments including the password of the user being added, there is
also the risk that the username / password combination will be cached in the history file of the shell
you are currently using.
Page 78 of 1804
WildFly 9
An Application User
When adding application users in addition to adding the user with their pre-hashed password it is also now
possible to define the roles of the user.
Interactive Mode
Here a new user called appUser has been added, in this case a comma separated list of roles has also
been specified.
As with adding a management user just answer n or no to the final question until you know you are adding a
user that will be establishing a connection from one server to another.
Page 79 of 1804
WildFly 9
Interactive Mode
To add an application user non-interactively use the command ./add-user.sh -a {username}
{password}.
Non-interactive mode does not support defining a list of users, to associate a user with a set of
roles you will need to manually edit the application-roles.properties file by hand.
Updating a User
Within the add-user utility it is also possible to update existing users, in interactive mode you will be
prompted to confirm if this is your intention.
A Management User
Interactive Mode
Interactive Mode
In non-interactive mode if a user already exists the update is automatic with no confirmation prompt.
Page 80 of 1804
WildFly 9
An Application User
Interactive Mode
On updating a user with roles you will need to re-enter the list of roles assigned to the user.
Interactive Mode
In non-interactive mode if a user already exists the update is automatic with no confirmation prompt.
Community Contributions
There are still a few features to add to the add-user utility such as removing users or adding application
users with roles in non-interactive mode, if you are interested in contributing to WildFly development the
add-user utility is a good place to start as it is a stand alone utility, however it is a part of the AS build so you
can become familiar with the AS development processes without needing to delve straight into the internals
of the application server.
Page 81 of 1804
WildFly 9
JMX Security
When configuring the security realms remote access to the server's MBeanServer needs a special mention.
When running in standalone mode the following is the default configuration: -
<native-interface security-realm="ManagementRealm">...</native-interface>
<subsystem xmlns="urn:jboss:domain:jmx:1.1">
...
<remoting-connector/>
</subsystem>
With this configuration remote access to JMX is provided over the native management interface, this is
secured using the realm ManagementRealm, this means that any user that can connect to the native
interface can also use this interface to access the MBeanServer - to disable this just remove the
<remoting-connector /> element.
In domain mode it is slightly more complicates as the native interface is exposed by the host controller
process however each application server is running in it's own process so by default remote access to JMX
is disabled.
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<connector name="remoting-connector" socket-binding="remoting"
security-realm="ApplicationRealm"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jmx:1.1">
...
<!--<remoting-connector use-management-endpoint="false"/>-->
</subsystem>
To enable remote access to JMX uncomment the <remoting-connector /> element however be aware
that this will make the MBeanServer accessible over the same Remoting connector used for remote JNDI
and EJB access - this means that any user that can authenticate against the realm ApplicationRealm will
be able to access the MBeanServer.
The following Jira issue is currently outstanding to allow access to the individual MBeanServers by
proxying through the host controllers native interface AS7-4009, if this is a feature you would use
please add your vote to the issue.
Page 82 of 1804
WildFly 9
Detailed Configuration
This section of the documentation describes the various configuration options when defining realms, plug-ins
are a slightly special case so the configuration options for plug-ins is within it's own section.
Within a security realm definition there are four optional elements <plug-ins />, <server-identities
/>, <authentication />, and <authorization />, as mentioned above plug-ins is defined within it's
own section below so we will begin by looking at the <server-identities /> element.
<server-identities />
The server identities section of a realm definition is used to define how a server appears to the outside
world, currently this element can be used to configure a password to be used when establishing a remote
outbound connection and also how to load a X.509 key which can be used for both inbound and outbound
SSL connections.
<ssl />
<server-identities>
<ssl protocol="...">
<keystore path="..." relative-to="..." keystore-password="..." alias="..."
key-password="..." />
</ssl>
</server-identities>
protocol - By default this is set to TLS and in general does not need to be set.
The SSL element then contains the nested <keystore /> element, this is used to define how to load the
key from the file based (JKS) keystore.
path (mandatory) - This is the path to the keystore, this can be an absolute path or relative to the next
attribute.
relative-to (optional) - The name of a service representing a path the keystore is relative to.
keystore-password (mandatory) - The password required to open the keystore.
alias (optional) - The alias of the entry to use from the keystore - for a keystore with multiple entries in
practice the first usable entry is used but this should not be relied on and the alias should be set to
guarantee which entry is used.
key-password (optional) - The password to load the key entry, if omitted the keystore-password will
be used instead.
If you see the error UnrecoverableKeyException: Cannot recover key the most likely
cause that you need to specify a key-password and possible even an alias as well to ensure
only one key is loaded.
Page 83 of 1804
WildFly 9
<secret />
<server-identities>
<secret value="..." />
</server-identities>
value (mandatory) - The password to use for outbound connections encoded as Base64, this field
also supports a vault expression should stronger protection be required.
The username for the outbound connection is specified at the point the outbound connection is
defined.
<authentication />
The authentication element is predominantly used to configure the authentication that is performed on an
inbound connection, however there is one exception and that is if a trust store is defined - on negotiating an
outbound SSL connection the trust store will be used to verify the remote server.
<authentication>
<truststore />
<local />
<jaas />
<ldap />
<properties />
<users />
<plug-in />
</authentication>
An authentication definition can have zero or one <truststore />, it can also have zero or one <local
/> and it can also have one of <jaas />, <ldap />, <properties />, <users />, and <plug-in />
i.e. the local mechanism and a truststore for certificate verification can be independent switched on and off
and a single username / password store can be defined.
Page 84 of 1804
WildFly 9
<truststore />
<authentication>
<truststore path="..." relative-to="..." keystore-password="..."/>
</authentication>
This element is used to define how to load a key store file that can be used as the trust store within the
SSLContext we create internally, the store is then used to verify the certificates of the remote side of the
connection be that inbound or outbound.
path (mandatory) - This is the path to the keystore, this can be an absolute path or relative to the next
attribute.
relative-to (optional) - The name of a service representing a path the keystore is relative to.
keystore-password (mandatory) - The password required to open the keystore.
Although this is a definition of a trust store the attribute for the password is keystore-password,
this is because the underlying file being opened is still a key store.
<local />
<authentication>
<local default-user="..." allowed-users="..." />
</authentication>
This element switches on the local authentication mechanism that allows clients to the server to verify that
they are local to the server, at the protocol level it is optional for the remote client to send a user name in the
authentication response.
default-user (optional) - If the client does not pass in a username this is the assumed username, this
value is also automatically added to the list of allowed-users.
allowed-users (optional) - This attribute is used to specify a comma separated list of users allowed to
authenticate using the local mechanism, alternatively '*' can be specified to allow any username to be
specified.
Page 85 of 1804
WildFly 9
<jaas />
<authentication>
<jaas name="..." />
</authentication>
The jaas element is used to enable username and password based authentication where the supplied
username and password are verified by making use of a configured jaas domain.
name (mandatory) - The name of the jaas domain to use to verify the supplied username and
password.
As JAAS authentication works by taking a username and password and verifying these the use of
this element means that at the transport level authentication will be forced to send the password in
plain text, any interception of the messages exchanged between the client and server without SSL
enabled will reveal the users password.
Page 86 of 1804
WildFly 9
<ldap />
<authentication>
<ldap connection="..." base-dn="..." recursive="..." user-dn="...">
<username-filter attribute="..." />
<advanced-filter filter="..." />
</ldap>
</authentication>
The ldap element is used to define how LDAP searches will be used to authenticate a user, this works by
first connecting to LDAP and performing a search using the supplied user name to identity the distinguished
name of the user and then a subsequent connection is made to the server using the password supplied by
the user - if this second connection is a success then authentication succeeds.
Due to the verification approach used this configuration causes the authentication mechanisms
selected for the protocol to cause the password to be sent from the client in plain text, the following
Jira issue is to investigating proxying a Digest authentication with the LDAP server so no plain text
password is needed AS7-4195.
Page 87 of 1804
WildFly 9
<properties />
<authentication>
<properties path="..." relative-to="..." plain-text="..." />
</authentication>
The properties element is used to reference a properties file to load to read a users password or
pre-prepared digest for the authentication process.
path (mandatory) - The path to the properties file, either absolute or relative to the path referenced by
the relative-to attribute.
relative-to (optional) - The name of a path service that the defined path will be relative to.
plain-text (optional) - Setting to specify if the passwords are stored as plain text within the properties
file, defaults to false.
By default the properties files are expected to store a pre-prepared hash of the users password in
the form HEX( MD5( username ':' realm ':' password))
<users />
<authentication>
<users>
<user username="...">
<password>...</password>
</user>
</users>
</authentication>
This is a very simple store of a username and password that stores both of these within the domain model,
this is only really provided for the provision of simple examples.
username (mandatory) - A users username.
The <password/> element is then used to define the password for the user.
Page 88 of 1804
WildFly 9
<authorization />
The authorization element is used to define how a users roles can be loaded after the authentication process
completes, these roles may then be used for subsequent authorization decisions based on the service being
accessed. At the moment only a properties file approach or a custom plug-in are supported - support for
loading roles from LDAP or from a database are planned for a subsequent release.
<authorization>
<properties />
<plug-in />
</authorization>
<properties />
<authorization>
<properties path="..." relative-to="..." />
</authorization>
The format of the properties file is username={ROLES} where {ROLES} is a comma separated list of the
users roles.
path (mandatory) - The path to the properties file, either absolute or relative to the path referenced by
the relative-to attribute.
relative-to (optional) - The name of a path service that the defined path will be relative to.
Page 89 of 1804
WildFly 9
<outbound-connection />
Strictly speaking these are not a part of the security realm definition, however at the moment they are only
used by security realms so the definition of outbound connection is described here.
<management>
<security-realms />
<outbound-connections>
<ldap />
</outbound-connections>
</management>
<ldap />
At the moment we only support outbound connections to ldap servers for the authentication process - this
will later be expanded when we add support for database based authentication.
<outbound-connections>
<ldap name="..." url="..." search-dn="..." search-credential="..."
initial-context-factory="..." />
</outbound-connections>
The outbound connections are defined in this section and then referenced by name from the configuration
that makes use of them.
name (mandatory) - The unique name used to reference this connection.
url (mandatory) - The URL use to establish the LDAP connection.
search-dn (mandatory) - The distinguished name of the user to authenticate as to perform the
searches.
search-credential (mandatory) - The password required to connect to LDAP as the search-dn.
initial-context-factory (optional) - Allows overriding the initial context factory, defaults to '
com.sun.jndi.ldap.LdapCtxFactory'
Plug Ins
Within WildFly 8 for communication with the management interfaces and for other services exposed using
Remoting where username / password authentication is used the use of Digest authentication is preferred
over the use of HTTP Basic or SASL Plain so that we can avoid the sending of password in the clear over
the network. For validation of the digests to work on the server we either need to be able to retrieve a users
plain text password or we need to be able to obtain a ready prepared hash of their password along with the
username and realm.
Page 90 of 1804
WildFly 9
Previously to allow the addition of custom user stores we have added an option to the realms to call out to a
JAAS domain to validate a users username and password, the problem with this approach is that to call
JAAS we need the remote user to send in their plain text username and password so that a JAAS
LoginModule can perform the validation, this forces us down to use either the HTTP Basic authentication
mechanism or the SASL Plain mechanism depending on the transport used which is undesirable as we can
not longer use Digest.
To overcome this we now support plugging in custom user stores to support loading a users password, hash
and roles from a custom store to allow different stores to be implemented without forcing the authentication
back to plain text variant, this article describes the requirements for a plug in and shows a simple example
plug-in for use with WildFly 8.
When implementing a plug in there are two steps to the authentication process, the first step is to load the
users identity and credential from the relevant store - this is then used to verify the user attempting to
connect is valid. After the remote user is validated we then load the users roles in a second step. For this
reason the support for plug-ins is split into the two stages, when providing a plug-in either of these two steps
can be implemented but there is no requirement to implement the other side.
When implementing a plug-in the following interfaces are the bare minimum that need to be implemented so
depending on if a plug-in to load a users identity or a plug-in to load a users roles is being implemented you
will be implementing one of these interfaces.
Note - All classes and interfaces of the SPI to be implemented are in the
'org.jboss.as.domain.management.plugin' package which is a part of the 'org.jboss.as.domain-management'
module but for simplicity for the rest of this section only the short names will be shown.
AuthenticationPlugIn
To implement an AuthenticationPlugIn the following interface needs to be implemened: -
During the authentication process this method will be called with the user name supplied by the remote user
and the name of the realm they are authenticating against, this method call represents that an authentication
attempt is occurring but it is the Identity instance that is returned that will be used for the actual
authentication to verify the remote user.
The Identity interface is also an interface you will implement: -
Page 91 of 1804
WildFly 9
Additional information can be contained within the Identity implementation although it will not currently be
used, the key piece of information here is the Credential that will be returned - this needs to be one of the
following: -
PasswordCredential
public final class PasswordCredential implements Credential {
public PasswordCredential(final char[] password);
public char[] getPassword();
void clear();
}
The PasswordCredential is already implemented so use this class if you have the plain text password of
the remote user, by using this the secured interfaces will be able to continue using the Digest mechanism for
authentication.
DigestCredential
public final class DigestCredential implements Credential {
public DigestCredential(final String hash);
public String getHash();
}
This class is also already implemented and should be returned if instead of the plain text password you
already have a pre-prepared hash of the username, realm and password.
ValidatePasswordCredential
public interface ValidatePasswordCredential extends Credential {
boolean validatePassword(final char[] password);
}
This is a special Credential type to use when it is not possible to obtain either a plain text representation of
the password or a pre-prepared hash - this is an interface as you will need to provide an implementation to
verify a supplied password. The down side of using this type of Credential is that the authentication
mechanism used at the transport level will need to drop down from Digest to either HTTP Basic or SASL
Plain which will now mean that the remote client is sending their credential across the network in the clear.
If you use this type of credential be sure to force the mechanism choice to Plain as described in the
configuration section below.
Page 92 of 1804
WildFly 9
AuthorizationPlugIn
If you are implementing a custom mechanism to load a users roles you need to implement the
AuthorizationPlugIn
As with the AuthenticationPlugIn this has a single method that takes a users userName and realm the return type is an array of Strings with each entry representing a role the user is a member of.
PlugInConfigurationSupport
In addition to the specific interfaces above there is an additional interface that a plug-in can implement to
receive configuration information before the plug-in is used and also to receive a Map instance that can be
used to share state between the plug-in instance used for the authentication step of the call and the plug-in
instance used for the authorization step.
<security-realm name="PlugInRealm">
<plug-ins>
<plug-in module="org.jboss.as.sample.plugin"/>
</plug-ins>
<authentication>
<plug-in name="Sample">
<properties>
<property name="darranl.password" value="dpd"/>
<property name="darranl.roles" value="Admin,Banker,User"/>
</properties>
</plug-in>
</authentication>
<authorization>
<plug-in name="Delegate" />
</authorization>
</security-realm>
Page 93 of 1804
WildFly 9
Before looking closely at the packaging and configuration there is one more interface to implement and that
is the PlugInProvider interface, that interface is responsible for making PlugIn instances available at
runtime to handle the requests.
PlugInProvider
public interface PlugInProvider {
AuthenticationPlugIn<Credential> loadAuthenticationPlugIn(final String name);
AuthorizationPlugIn loadAuthorizationPlugIn(final String name);
}
These methods are called with the name that is supplied in the plug-in elements that are contained within the
authentication and authorization elements of the configuration, based on the sample configuration above the
loadAuthenticationPlugIn method will be called with a parameter of 'Sample' and the loadAuthorizationPlugIn
method will be called with a parameter of 'Delegate'.
Multiple plug-in providers may be available to the application server so if a PlugInProvider
implementation does not recognise a name then it should just return null and the server will continue
searching the other providers. If a PlugInProvider does recognise a name but fails to instantiate the
PlugIn then a RuntimeException can be thrown to indicate the failure.
As a server could have many providers registered it is recommended that a naming convention including
some form of hierarchy is used e.g. use package style names to avoid conflicts.
For the example the implementation is as follows: -
The load methods are called for each authentication attempt but it will be an implementation detail of the
provider if it decides to return a new instance of the provider each time - in this scenario as we also use
configuration and shared state then new instances of the implementations make sense.
Page 94 of 1804
WildFly 9
To load the provider use a ServiceLoader so within the META-INF/services folder of the jar this project adds
a file called 'org.jboss.as.domain.management.plugin.PlugInProvider' - this contains a single
entry which is the fully qualified class name of the PlugInProvider implementation class.
org.jboss.as.sample.SamplePluginProvider
Package as a Module
To make the PlugInProvider available to the application it is bundled as a module and added to the
modules already shipped with WildFly 8.
To add as a module we first need a module.xml: -
<plug-ins>
<plug-in module="org.jboss.as.sample.plugin"/>
</plug-ins>
This element is used to list the modules that should be searched for plug-ins. As plug-ins are loaded during
the server start up this search is a lazy search so don't expect a definition to a non existant module or to a
module that does not contain a plug-in to report an error.
The AuthenticationPlugIn
The example AuthenticationPlugIn is implemented as: -
Page 95 of 1804
WildFly 9
Page 96 of 1804
WildFly 9
As you can see from this implementation there is also an additional class being extended AbstractPlugIn
- that is simply an abstract class that implements the AuthenticationPlugIn, AuthorizationPlugIn,
and PlugInConfigurationSupport interfaces already. The properties that were defined in the
configuration are passed in as a Map and importantly for this sample the plug-in adds itself to the shared
state map.
The AuthorizationPlugIn
The example implementation of the authentication plug in is as follows: -
This plug-in illustrates how two plug-ins can work together, by the AuthenticationPlugIn placing itself in
the shared state map it is possible for the authorization plug-in to make use of it for the loadRoles
implementation.
Another option to consider to achieve similar behaviour could be to provide an Identity implementation that
also contains the roles and place this in the shared state map - the AuthorizationPlugIn can retrieve
this and return the roles.
<authentication>
<plug-in name="Sample" mechanism="PLAIN">
Page 97 of 1804
WildFly 9
Example Configurations
This section of the document contains a couple of examples for the most common scenarios likely to be
used with the security realms, please feel free to raise Jira issues requesting additional scenarios or if you
have configured something not covered here please feel free to add your own examples - this document is
editable after all
At the moment these examples are making use of the 'ManagementRealm' however the same can apply to
the 'ApplicationRealm' or any custom realm you create for yourselves.
LDAP Authentication
The following example demonstrates an example configuration making use of Active Directory to verify the
users username and password.
<management>
<security-realms>
<security-realm name="ManagementRealm">
<authentication>
<ldap connection="EC2" base-dn="CN=Users,DC=darranl,DC=jboss,DC=org">
<username-filter attribute="sAMAccountName" />
</ldap>
</authentication>
</security-realm>
</security-realms>
<outbound-connections>
<ldap name="EC2" url="ldap://127.0.0.1:9797"
search-dn="CN=wf8,CN=Users,DC=darranl,DC=jboss,DC=org" search-credential="password"/>
</outbound-connections>
...
</management>
For simplicity the <local/> configuration has been removed from this example, however there it
is fine to leave that in place for local authentication to remain possible.
Page 98 of 1804
WildFly 9
Enable SSL
The first step is the creation of the key, by default this is going to be used for both the native management
interface and the http management interface - to create the key we can use the keyTool, the following
example will create a key valid for one year.
Open a terminal window in the folder {jboss.home}/standalone/configuration and enter the
following command: keytool -genkey -alias server -keyalg RSA -keystore server.keystore -validity
365
Of all of the questions asked this is the most important and should match the host name that will be
entered into the web browser to connect to the admin console.
Answer the remaining questions as you see fit and at the end for the purpose of this example I set the key
password to 'key_password'.
The following example shows how this newly created keystore will be referenced to enable SSL.
<security-realm name="ManagementRealm">
<server-identities>
<ssl>
<keystore path="server.keystore" relative-to="jboss.server.config.dir"
keystore-password="keystore_password" alias="server" key-password="key_password" />
</ssl>
</server-identities>
<authentication>
...
</authentication>
</security-realm>
The contents of the <authentication /> have not been changed in this example so authentication still
occurs using either the local mechanism or username/password authentication using Digest.
Page 99 of 1804
WildFly 9
<security-realm name="ManagementRealm">
<server-identities>
<ssl>
<keystore path="server.keystore" relative-to="jboss.server.config.dir"
keystore-password="keystore_password" alias="server" key-password="key_password" />
</ssl>
</server-identities>
<authentication>
<truststore path="server.truststore" relative-to="jboss.server.config.dir"
keystore-password="truststore_password" />
<local default-user="$local"/>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
</security-realm>
In this scenario if Client-Cert authentication does not occur clients can fall back to use either the local
mechanism or username/password authentication. To make Client-Cert based authentication mandatory just
remove the <local /> and <properties /> elements.
WildFly 9
<management>
. . .
<access-control provider="simple">
<role-mapping>
<role name="SuperUser">
<include>
<user name="$local"/>
</include>
</role>
</role-mapping>
</access-control>
</management>
As you can see, the provider is set to "simple" by default. With the "simple" provider, the nested
"role-mapping" section is not actually relevant. It's there to help ensure that if the provider attribute is
switched to "rbac" there will be at least one user mapped to a role that can continue to administer the
system. This default mapping assigns the "$local" user name to the RBAC role that provides all permissions,
the "SuperUser" role. The "$local" user name is the name an administrator will be assigned if he or she uses
the CLI on the same system as the WildFly instance and the "local" authentication scheme is enabled.
WildFly 9
RBAC roles
The seven standard roles are divided into two broad categories, based on whether the role can deal with
items that are considered to be "security sensitive". Resources, attributes and operations that may affect
administrative security (e.g. security realm resources and attributes that contain passwords) are "security
sensitive".
Four roles are not given permissions for "security sensitive" items:
Monitor a read-only role. Cannot modify any resource.
Operator Monitor permissions, plus can modify runtime state, but cannot modify anything that ends
up in the persistent configuration. Could, for example, restart a server.
Maintainer Operator permissions, plus can modify the persistent configuration.
Deployer like a Maintainer, but with permission to modify persistent configuration constrained to
resources that are considered to be "application resources". A deployment is an application resource.
The messaging server is not. Items like datasources and JMS destinations are not considered to be
application resources by default, but this is configurable.
Three roles are granted permissions for security sensitive items:
SuperUser has all permissions. Equivalent to a JBoss AS 7 administrator.
Administrator has all permissions except cannot read or write resources related to the administrative
audit logging system.
Auditor can read anything. Can only modify the resources related to the administrative audit logging
system.
The Auditor and Administrator roles are meant for organizations that want a separation of responsibilities
between those who audit normal administrative actions and those who perform them, with those who
perform most actions (Administrator role) not being able to read or alter the auditing configuration.
WildFly 9
Addressing a resource
As mentioned above, permissions are granted to perform one of three actions, addressing a resource,
reading it, and modifying. The latter two actions are fairly self-explanatory. But what is meant by
"addressing" a resource?
"Addressing" a resource refers to taking an action that allows the user to determine whether a resource at a
given address actually exists. For example, the "read-children-names" operation lets a user determine valid
addresses. Trying to read a resource and getting a "Permission denied" error also gives the user a clue that
there actually is a resource at the requested address.
Some resources may include sensitive information as part of their address. For example, security realm
resources include the realm name as the last element in the address. That realm name is potentially security
sensitive; for example it is part of the data used when creating a hash of a user password. Because some
addresses may contain security sensitive data, a user needs permission to even "address" a resource. If a
user attempts to address a resource and does not have permission, they will not receive a "permission
denied" type error. Rather, the system will respond as if the resource does not even exist, e.g. excluding the
resource from the result of the "read-children-names" operation or responding with a "No such resource"
error instead of "Permission denied" if the user is attempting to read or write the resource.
Another term for "addressing" a resource is "looking up" the resource.
Before changing the provider to "rbac", be sure your configuration has a user who will be mapped
to one of the RBAC roles, preferably with at least one in the Administrator or SuperUser role.
Otherwise your installation will not be manageable except by shutting it down and editing the xml
configuration. If you have started with one of the standard xml configurations shipped with WildFly,
the "$local" user will be mapped to the "SuperUser" role and the "local" authentication scheme will
be enabled. This will allow a user running the CLI on the same system as the WildFly process to
have full administrative permissions. Remote CLI users and web-based admin console users will
have no permissions.
We recommend mapping at least one user besides "$local" before switching the provider to "rbac".
You can do all of the configuration associated with the "rbac" provider even when the provider is
set to "simple"
WildFly 9
[standalone@localhost:9990 /] cd core-service=management/access=authorization
[standalone@localhost:9990 access=authorization] :write-attribute(name=provider,value=rbac)
{
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}
[standalone@localhost:9990 access=authorization] reload
In a managed domain, the access control configuration is part of the domain wide configuration, so the
resource address is the same as above:
[domain@localhost:9990 /] cd core-service=management/access=authorization
[domain@localhost:9990 access=authorization] :write-attribute(name=provider,value=rbac)
{
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
},
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}},
"server-two" => {"response" => {
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}}
}}}}
}
[domain@localhost:9990 access=authorization] reload --host=master
As with a standalone server, a reload is required for the change to take effect. In this case, all hosts and
servers in the domain will need to be restarted, so be sure to plan well before making this change.
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator:add
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
Once this is done, map a user to the role:
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=user-jsmith:add(name=jsmith,t
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Now if user jsmith authenticates to any security realm associated with the management interface they are
using, he will be mapped to the Administrator role.
To restrict the mapping to a particular security realm, change the realm attribute to the realm name. This
might be useful if different realms are associated with different management interfaces, and the goal is to
limit a user to a particular interface.
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=user-mjones:add(name=mjones,t
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
User groups
A "group" is an arbitrary collection of users that may exist in the end user environment. They can be named
whatever the end user organization wants and can contain whatever users the end user organization wants.
Some of the authentication store types supported by WildFly security realms include the ability to access
information about what groups a user is a member of and associate this information with the Subject
produced when the user is authenticated. This is currently supported for the following authentication store
types:
properties file (via the <realm_name>-groups.properties file)
LDAP (via directory-server-specific configuration)
Groups are convenient when it comes to associating a user with a role, since entire groups can be
associated with a role in a single mapping.
WildFly 9
The CLI can also be used to map groups to roles. The only difference to individual user mapping is the value
of the type attribute should be GROUP instead of USER.
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=group-SeniorAdmins:add(name=S
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
As with individual user mappings, the mapping can be restricted to users authenticating via a particular
security realm:
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=group-PowerAdmins:add(name=Po
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
A user who can authenticate to the management security realm but who does not map to a role will
not be able to perform any administrative functions, not even reads.
In the web based admin console, navigate to the "Administration" tab, "Roles" subtab, highlight the relevant
role, click the "Edit" button and click on the "Include All" checkbox:
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Monitor:write-attribute(name=include-all,value=true
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
In the CLI, excludes are identical to includes, except the resource address has exclude instead of
include as the key for the last address element:
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Monitor/exclude=group-Temps:add(name=Temps,type=GRO
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
[standalone@localhost:9990 /] cd core-service=management/access=authorization
[standalone@localhost:9990 access=authorization]
:write-attribute(name=permission-combination-policy,value=rejecting)
{"outcome" => "success"}
[standalone@localhost:9990 /] cd core-service=management/access=authorization
[standalone@localhost:9990 access=authorization]
:write-attribute(name=permission-combination-policy,value=permissive)
{"outcome" => "success"}
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/server-group-scoped-role=MainGroupAdmins:add(base-role=Administr
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Once the role is created, users or groups can be mapped to it the same as with the seven standard roles.
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/host-scoped-role=MasterOperators:add(base-role=Operator,hosts=[m
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Once the role is created, users or groups can be mapped to it the same as with the seven standard roles.
WildFly 9
When adding a new scoped role, use the dialogue's "Type" pull down to choose between a host scoped role
and a server-group scoped role. Then place the names of the relevant hosts or server groups in the "Scope"
text are.
WildFly 9
Configuring constraints
The following factors are used to determine whether a given role is granted a permission:
What the requested action is (address, read, write)
Whether the resource, attribute or operation affects the persistent configuration
Whether the resource, attribute or operation is related to the administrative audit logging function
Whether the resource, attribute or operation is configured as security sensitive
Whether an attribute or operation parameter value has a security vault expression
Whether a resource is considered to be associated with applications, as opposed to being part of a
general container configuration
The first three of these factors are non-configurable; the latter three allow some customization.
WildFly 9
Configuring sensitivity
"Sensitivity" constraints are about restricting access to security-sensitive data. Different organizations may
have different opinions about what is security sensitive, so WildFly provides configuration options to allow
users to tailor these constraints.
[domain@localhost:9990 /] cd
core-service=management/access=authorization/constraint=sensitivity-classification/type=core/classification=so
classification=socket-config] ls -l
ATTRIBUTE
VALUE
TYPE
configured-requires-addressable undefined BOOLEAN
configured-requires-read
undefined BOOLEAN
configured-requires-write
undefined BOOLEAN
default-requires-addressable
false
BOOLEAN
default-requires-read
false
BOOLEAN
default-requires-write
true
BOOLEAN
CHILD
MIN-OCCURS MAX-OCCURS
applies-to n/a
n/a
The various default-requires-... attributes indicate whether a user must be in a role that allows
security sensitive actions in order to perform the action. In the socket-config example above,
default-requires-write is true, while the others are false. So, by default modifying a setting involving
socket configuration is considered sensitive, while addressing those resources or doing reads is not
sensitive.
The default-requires-... attributes are read-only. The configured-requires-... attributes
however can be modified to override the default settings with ones appropriate for your organization. For
example, if your organization doesn't regard modifying socket configuration settings to be security sensitive,
you can change that setting:
WildFly 9
[domain@localhost:9990 classification=socket-config]
:write-attribute(name=configured-requires-write,value=false)
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Administrators can also read the management model to see to which resources, attributes and operations a
particular sensitivity classification applies:
[domain@localhost:9990 classification=socket-config]
:read-children-resources(child-type=applies-to)
{
"outcome" => "success",
"result" => {
"/host=master" => {
"address" => "/host=master",
"attributes" => [],
"entire-resource" => false,
"operations" => ["resolve-internet-address"]
},
"/host=master/core-service=host-environment" => {
"address" => "/host=master/core-service=host-environment",
"attributes" => [
"host-controller-port",
"host-controller-address",
"process-controller-port",
"process-controller-address"
],
"entire-resource" => false,
"operations" => []
},
"/host=master/core-service=management/management-interface=http-interface" => {
"address" =>
"/host=master/core-service=management/management-interface=http-interface",
"attributes" => [
"port",
"secure-interface",
"secure-port",
"interface"
],
"entire-resource" => false,
"operations" => []
},
"/host=master/core-service=management/management-interface=native-interface" => {
"address" =>
"/host=master/core-service=management/management-interface=native-interface",
"attributes" => [
"port",
"interface"
WildFly 9
],
"entire-resource" => false,
"operations" => []
},
"/host=master/interface=*" => {
"address" => "/host=master/interface=*",
"attributes" => [],
"entire-resource" => true,
"operations" => ["resolve-internet-address"]
},
"/host=master/server-config=*/interface=*" => {
"address" => "/host=master/server-config=*/interface=*",
"attributes" => [],
"entire-resource" => true,
"operations" => []
},
"/interface=*" => {
"address" => "/interface=*",
"attributes" => [],
"entire-resource" => true,
"operations" => []
},
"/profile=*/subsystem=messaging/hornetq-server=*/broadcast-group=*" => {
"address" => "/profile=*/subsystem=messaging/hornetq-server=*/broadcast-group=*",
"attributes" => [
"group-address",
"group-port",
"local-bind-address",
"local-bind-port"
],
"entire-resource" => false,
"operations" => []
},
"/profile=*/subsystem=messaging/hornetq-server=*/discovery-group=*" => {
"address" => "/profile=*/subsystem=messaging/hornetq-server=*/discovery-group=*",
"attributes" => [
"group-address",
"group-port",
"local-bind-address"
],
"entire-resource" => false,
"operations" => []
},
"/profile=*/subsystem=transactions" => {
"address" => "/profile=*/subsystem=transactions",
"attributes" => ["process-id-socket-max-ports"],
"entire-resource" => false,
"operations" => []
},
"/server-group=*" => {
"address" => "/server-group=*",
"attributes" => ["socket-binding-port-offset"],
"entire-resource" => false,
"operations" => []
},
"/socket-binding-group=*" => {
"address" => "/socket-binding-group=*",
"attributes" => [],
WildFly 9
"entire-resource" => true,
"operations" => []
}
}
}
There will be a separate child for each address to which the classification applies. The entire-resource
attribute will be true if the classification applies to the entire resource. Otherwise, the attributes and
operations attributes will include the names of attributes or operations to which the classification applies.
Classifications with broad use
Several of the core sensitivity classifications are commonly used across the management model and
deserve special mention.
Name
Description
credential
security-domain-ref An attribute whose value is the name of a security domain. By default sensitive for
both reads and writes
security-realm-ref
An attribute whose value is the name of a security realm. By default sensitive for both
reads and writes
socket-binding-ref
An attribute whose value is the name of a socket binding. By default not sensitive for
any action
socket-config
[domain@localhost:9990 /] cd
core-service=management/access=authorization/constraint=vault-expression
[domain@localhost:9990 constraint=vault-expression] ls -l
ATTRIBUTE
VALUE
TYPE
configured-requires-read undefined BOOLEAN
configured-requires-write undefined BOOLEAN
default-requires-read
true
BOOLEAN
default-requires-write
true
BOOLEAN
WildFly 9
The various default-requires-... attributes indicate whether a user must be in a role that allows
security sensitive actions in order to perform the action. So, by default both reading and writing attributes
whose values include vault expressions requires a user to be in one of the roles with sensitive data
permissions.
The default-requires-... attributes are read-only. The configured-requires-... attributes
however can be modified to override the default settings with settings appropriate for your organization. For
example, if your organization doesn't regard reading vault expressions to be security sensitive, you can
change that setting:
[domain@localhost:9990 constraint=vault-expression]
:write-attribute(name=configured-requires-read,value=false)
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
This vault-expression constraint overlaps somewhat with the core "credential" sensitivity
classification in that the most typical uses of a vault expression are in attributes that contain a user
name or password, and those will typically be annotated with the "credential" sensitivity
classification. So, if you change the settings for the "credential" sensitivity classification you may
also need to make a corresponding change to the vault-expression constraint settings, or your
change will not have full effect.
Be aware though, that vault expressions can be used in any attribute that supports expressions,
not just in credential-type attributes. So it is important to be familiar with where and how your
organization uses vault expressions before changing these settings.
WildFly 9
[domain@localhost:9990 /] cd
/core-service=management/access=authorization/constraint=application-classification/type=mail/classification=m
classification=mail-session] ls -l
ATTRIBUTE
VALUE
TYPE
configured-application undefined BOOLEAN
default-application
false
BOOLEAN
CHILD
MIN-OCCURS MAX-OCCURS
applies-to n/a
n/a
[domain@localhost:9990 classification=mail-session]
:read-children-resources(child-type=applies-to)
{
"outcome" => "success",
"result" => {"/profile=*/subsystem=mail/mail-session=*" => {
"address" => "/profile=*/subsystem=mail/mail-session=*",
"attributes" => [],
"entire-resource" => true,
"operations" => []
}}
}
This indicates that this classification, intuitively enough, only applies to mail subsystem mail-session
resources.
To make resources with this classification writeable by users in the Deployer role, set the
configured-application attribute to true.
[domain@localhost:9990 classification=mail-session]
:write-attribute(name=configured-application,value=true)
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
Classification
datasources
data-source
datasources
jdbc-driver
datasources
xa-data-source
logging
logger
logging
logging-profile
mail-session
messaging
jms-queue
messaging
jms-topic
messaging
queue
messaging
security-setting
naming
binding
resource-adapters resource-adapter
security
security-domain
In each case the classification applies to the resources you would expect, given its name.
Admin console
The admin console takes great pains to provide a good user experience even when the user has reduced
permissions. Resources the user is not permitted to see will simply not be shown, or if appropriate will be
replaced in the UI with an indication that the user is not authorized. Interaction units like "Add" and "Remove"
buttons and "Edit" links will be suppressed if the user has no write permissions.
CLI
The CLI is a much more unconstrained tool than the admin console is, allowing users to try to execute
whatever operations they wish, so it's more likely that users who attempt to do things for which they lack
necessary permissions will receive failure messages. For example, a user in the Monitor role cannot read
passwords:
WildFly 9
[domain@localhost:9990 /]
/profile=default/subsystem=datasources/data-source=ExampleDS:read-attribute(name=password)
{
"outcome" => "failed",
"result" => undefined,
"failure-description" => "WFLYCTL0313: Unauthorized to execute operation 'read-attribute'
for resource '[
(\"profile\" => \"default\"),
(\"subsystem\" => \"datasources\"),
(\"data-source\" => \"ExampleDS\")
]' -- \"WFLYCTL0332: Permission denied\"",
"rolled-back" => true
}
If the user isn't even allowed to address the resource then the response would be as if the resource doesn't
exist, even though it actually does:
[domain@localhost:9990 /]
/profile=default/subsystem=security/security-domain=other:read-resource
{
"outcome" => "failed",
"failure-description" => "WFLYCTL0216: Management resource '[
(\"profile\" => \"default\"),
(\"subsystem\" => \"security\"),
(\"security-domain\" => \"other\")
]' not found",
"rolled-back" => true
}
This prevents unauthorized users fishing for sensitive data in resource addresses by checking for
"Permission denied" type failures.
Users who use the read-resource operation may ask for data, some of which they are allowed to see and
some of which they are not. If this happens, the request will not fail, but inaccessible data will be elided and
a response header will be included advising on what was not included. Here we show the effect of a Monitor
trying to recursively read the security subsystem configuration:
WildFly 9
[domain@localhost:9990 /] /profile=default/subsystem=security:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"deep-copy-subject-mode" => undefined,
"security-domain" => undefined,
"vault" => undefined
},
"response-headers" => {"access-control" => [{
"absolute-address" => [
("profile" => "default"),
("subsystem" => "security")
],
"relative-address" => [],
"filtered-attributes" => ["deep-copy-subject-mode"],
"filtered-children-types" => ["security-domain"]
}]}
}
The response-headers section includes access control data in a list with one element per relevant
resource. (In this case there's just one.) The absolute and relative address of the resource is shown, along
with the fact that the value of the deep-copy-subject-mode attribute has been filtered (i.e. undefined is
shown as the value, which may not be the real value) as well as the fact that child resources of type
security-domain have been filtered.
WildFly 9
[domain@localhost:9990 /] cd /profile=default/subsystem=mail/mail-session=default/server=smtp
[domain@localhost:9990 server=smtp] :read-resource-description(access-control=trim-descriptions)
{
"outcome" => "success",
"result" => {
"description" => undefined,
"access-constraints" => {"application" => {"mail-session" => {"type" => "mail"}}},
"attributes" => undefined,
"operations" => undefined,
"children" => {},
"access-control" => {
"default" => {
"read" => true,
"write" => false,
"attributes" => {
"outbound-socket-binding-ref" => {
"read" => true,
"write" => false
},
"username" => {
"read" => false,
"write" => false
},
"tls" => {
"read" => true,
"write" => false
},
"ssl" => {
"read" => true,
"write" => false
},
"password" => {
"read" => false,
"write" => false
}
}
},
"exceptions" => {}
}
}
}
Because trim-descriptions was used as the value for the access-control parameter, the typical
"description", "attributes", "operations" and "children" data is largely suppressed. (For more on this, see
below.) The access-constraints field indicates that this resource is annotated with an application
constraint. The access-control field includes information about the permissions the current caller has for
this resource. The default section shows the default settings for resources of this type. The read and
write fields directly under default show that the caller can, in general, read this resource but cannot write
it. The attributes section shows the individual attribute settings. Note that Monitor cannot read the
username and password attributes.
WildFly 9
There are three valid values for the access-control parameter to read-resource-description and
read-operation-description:
none do not include access control information in the response. This is the default behavior if no
parameter is included.
trim-descriptions remove the normal description details, as shown in the example above
combined-descriptions include both the normal output and the access control data
CLI users should use the whoami operation with the verbose attribute set:
[domain@localhost:9990 /] :whoami(verbose=true)
{
"outcome" => "success",
"result" => {
"identity" => {
"username" => "aadams",
"realm" => "ManagementRealm"
},
"mapped-roles" => [
"Maintainer"
]
}
}
WildFly 9
CLI run-as
With the CLI, run-as capability is on a per-request basis. It is done by using the "roles" operation header, the
value of which can be the name of a single role or a bracket-enclosed, comma-delimited list of role names.
Example with a low level operation:
[standalone@localhost:9990 /] :whoami(verbose=true){roles=[Operator,Auditor]}
{
"outcome" => "success",
"result" => {
"identity" => {
"username" => "$local",
"realm" => "ManagementRealm"
},
"mapped-roles" => [
"Auditor",
"Operator"
]
}
}
Here we show the effect of switching to a role that isn't granted the necessary permission.
WildFly 9
The console will need to be restarted in order for the change to take effect.
WildFly 9
Schema Location
The configuration schemas can found in $JBOSS_HOME/docs/schema.
WildFly 9
<global-modules>
<module name="org.jboss.logging"
slot="main"/>
<module name="org.apache.log4j"
annotations="true"
meta-inf="true"
services="false" />
</global-modules>
<ear-subdeployments-isolated>true</ear-subdeployments-isolated>
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>false</jboss-descriptor-property-replacement>
<annotation-property-replacement>false</annotation-property-replacement>
<concurrent>
<context-services>
<context-service
name="default"
jndi-name="java:jboss/ee/concurrency/context/default"
use-transaction-setup-provider="true" />
</context-services>
<managed-thread-factories>
<managed-thread-factory
name="default"
jndi-name="java:jboss/ee/concurrency/factory/default"
context-service="default"
priority="1" />
</managed-thread-factories>
<managed-executor-services>
<managed-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
max-threads="25"
keepalive-time="5000"
queue-length="1000000"
reject-policy="RETRY_ABORT" />
</managed-executor-services>
<managed-scheduled-executor-services>
<managed-scheduled-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/scheduler/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
keepalive-time="5000"
reject-policy="RETRY_ABORT" />
</managed-scheduled-executor-services>
</concurrent>
<default-bindings
context-service="java:jboss/ee/concurrency/context/default"
datasource="java:jboss/datasources/ExampleDS"
jms-connection-factory="java:jboss/DefaultJMSConnectionFactory"
managed-executor-service="java:jboss/ee/concurrency/executor/default"
managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default"
managed-thread-factory="java:jboss/ee/concurrency/factory/default" />
WildFly 9
</subsystem>
Global Modules
Global modules is a set of JBoss Modules that will be added as dependencies to the JBoss Module of every
Java EE deployment. Such dependencies allows Java EE deployments to see the classes exported by the
global modules.
Each global module is defined through the module resource, an example of its XML configuration:
<global-modules>
<module name="org.jboss.logging" slot="main"/>
<module name="org.apache.log4j" annotations="true" meta-inf="true" services="false" />
</global-modules>
The only mandatory attribute is the JBoss Module name, the slot attribute defaults to main, and both
define the JBoss Module ID to reference.
The optional annotations attribute, which defaults to false, indicates if a pre-computed annotation index
should be imported from META-INF/jandex.idx
The optional services attribute indicates if any services exposed in META-INF/services should be made
available to the deployments class loader, and defaults to false.
The optional meta-inf attribute, which defaults to true, indicates if the Module's META-INF path should
be available to the deployment's class loader.
WildFly 9
<ear-subdeployments-isolated>true</ear-subdeployments-isolated>
For example:
myapp.ear
|
|--- web.war
|
|--- ejb1.jar
|
|--- ejb2.jar
If the ear-subdeployments-isolated is set to false, then the classes in web.war can access classes
belonging to ejb1.jar and ejb2.jar. Similarly, classes from ejb1.jar can access classes from
ejb2.jar (and vice-versa).
This flag has no effect on the isolated classloader of the .war file(s), i.e. irrespective of whether
this flag is set to true or false, the .war within a .ear will have a isolated classloader, and
other subdeployments within that .ear will not be able to access classes from that .war. This is
as per spec.
WildFly 9
Property Replacement
The EE subsystem configuration includes flags to configure whether system property replacement will be
done on XML descriptors and Java Annotations, included in Java EE deployments.
System properties etc are resolved in the security context of the application server itself, not the
deployment that contains the file. This means that if you are running with a security manager and
enable this property, a deployment can potentially access system properties or environment entries
that the security manager would have otherwise prevented.
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>false</jboss-descriptor-property-replacement>
<annotation-property-replacement>false</annotation-property-replacement>
EE Concurrency Utilities
EE Concurrency Utilities (JSR 236) were introduced with Java EE 7, to ease the task of writing multithreaded
Java EE applications. Instances of these utilities are managed by WildFly, and the related configuration
provided by the EE subsystem.
WildFly 9
Context Services
The Context Service is a concurrency utility which creates contextual proxies from existent objects. WildFly
Context Services are also used to propagate the context from a Java EE application invocation thread, to the
threads internally used by the other EE Concurrency Utilities. Context Service instances may be created
using the subsystem XML configuration:
<context-services>
<context-service
name="default"
jndi-name="java:jboss/ee/concurrency/context/default"
use-transaction-setup-provider="true" />
</context-services>
The name attribute is mandatory, and it's value should be a unique name within all Context Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Context Service should be
placed.
The optional use-trasaction-setup-provider attribute indicates if the contextual proxies built by the
Context Service should suspend transactions in context, when invoking the proxy objects, and its value
defaults to true.
Management clients, such as the WildFly CLI, may also be used to configure Context Service instances. An
example to add and remove one named other:
/subsystem=ee/context-service=other:add(jndi-name=java\:jboss\/ee\/concurrency\/other)
/subsystem=ee/context-service=other:remove
WildFly 9
<managed-thread-factories>
<managed-thread-factory
name="default"
jndi-name="java:jboss/ee/concurrency/factory/default"
context-service="default"
priority="1" />
</managed-thread-factories>
The name attribute is mandatory, and it's value should be a unique name within all Managed Thread
Factories.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Thread Factory
should be placed.
The optional context-service references an existent Context Service by its name. If specified then
thread created by the factory will propagate the invocation context, present when creating the thread.
The optional priority indicates the priority for new threads created by the factory, and defaults to 5.
Management clients, such as the WildFly CLI, may also be used to configure Managed Thread Factory
instances. An example to add and remove one named other:
/subsystem=ee/managed-thread-factory=other:add(jndi-name=java\:jboss\/ee\/factory\/other)
/subsystem=ee/managed-thread-factory=other:remove
WildFly 9
<managed-executor-services>
<managed-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
max-threads="25"
keepalive-time="5000"
queue-length="1000000"
reject-policy="RETRY_ABORT" />
</managed-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Executor
Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Executor Service
should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional queue-length indicates the number of tasks that can be stored in the input queue. The
default value is 0, which means the queue capacity is unlimited.
The executors task queue is based on the values of the attributes core-threads and queue-length:
If queue-length is 0, or queue-length is Integer.MAX_VALUE (2147483647) and
core-threads is 0, direct handoff queuing strategy will be used and a synchronous queue will be
created.
If queue-length is Integer.MAX_VALUE but core-threads is not 0, an unbounded queue will
be used.
For any other valid value for queue-length, a bounded queue wil be created.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
WildFly 9
The optional max-threads defines the the maximum number of threads used by the executor, which
defaults to Integer.MAX_VALUE (2147483647).
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, or RETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Executor Service
instances. An example to add and remove one named other:
/subsystem=ee/managed-executor-service=other:add(jndi-name=java\:jboss\/ee\/executor\/other,
core-threads=2)
/subsystem=ee/managed-executor-service=other:remove
<managed-scheduled-executor-services>
<managed-scheduled-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/scheduler/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
keepalive-time="5000"
reject-policy="RETRY_ABORT" />
</managed-scheduled-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Scheduled
Executor Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Scheduled
Executor Service should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
WildFly 9
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, orRETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Scheduled Executor
Service instances. An example to add and remove one named other:
/subsystem=ee/managed-scheduled-executor-service=other:add(jndi-name=java\:jboss\/ee\/scheduler\/other,
core-threads=2)
/subsystem=ee/managed-scheduled-executor-service=other:remove
WildFly 9
Default EE Bindings
The Java EE Specification mandates the existence of a default instance for each of the following resources:
Context Service
Datasource
JMS Connection Factory
Managed Executor Service
Managed Scheduled Executor Service
Managed Thread Factory
The EE subsystem looks up the default instances from JNDI, using the names in the default bindings
configuration, before placing those in the standard JNDI names, such as
java:comp/DefaultManagedExecutorService:
<default-bindings
context-service="java:jboss/ee/concurrency/context/default"
datasource="java:jboss/datasources/ExampleDS"
jms-connection-factory="java:jboss/DefaultJMSConnectionFactory"
managed-executor-service="java:jboss/ee/concurrency/executor/default"
managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default"
managed-thread-factory="java:jboss/ee/concurrency/factory/default" />
The default bindings are optional, if the jndi name for a default binding is not configured then the
related resource will not be available to Java EE applications.
WildFly 9
5.6.2 Naming
Overview
The Naming subsystem provides the JNDI implementation on WildFly, and its configuration allows to:
bind entries in global JNDI namespaces
turn off/on the remote JNDI interface
The subsystem name is naming and this document covers Naming subsystem version 2.0, which XML
namespace within WildFly XML configurations is urn:jboss:domain:naming:2.0. The path for the
subsystem's XML schema, within WildFly's distribution, is docs/schema/jboss-as-naming_2_0.xsd.
Subsystem XML configuration example with all elements and attributes specified:
<subsystem xmlns="urn:jboss:domain:naming:2.0">
<bindings>
<simple name="java:global/a" value="100" type="int" />
<simple name="java:global/jboss.org/docs/url" value="https://docs.jboss.org"
type="java.net.URL" />
<object-factory name="java:global/foo/bar/factory" module="org.foo.bar"
class="org.foo.bar.ObjectFactory" />
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
<lookup name="java:global/c" lookup="java:global/b" />
</bindings>
<remote-naming/>
</subsystem>
WildFly 9
If WildFly is to be used as a Java EE application server, then it's recommended to opt for
java:global, since it is a standard (i.e. portable) namespace.
<bindings>
<simple name="java:global/a" value="100" type="int" />
<object-factory name="java:global/foo/bar/factory" module="org.foo.bar"
class="org.foo.bar.ObjectFactory" />
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
<lookup name="java:global/c" lookup="java:global/b" />
</bindings>
WildFly 9
Simple Bindings
A simple binding is a primitive or java.net.URL entry, and it is defined through the simple XML element. An
example of its XML configuration:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The value attribute is mandatory and defines the entry's value.
The optional type attribute, which defaults to java.lang.String, specifies the type of the entry's value.
Besides java.lang.String, allowed types are all the primitive types and their corresponding object wrapper
classes, such as int or java.lang.Integer, and java.net.URL.
Management clients, such as the WildFly CLI, may be used to configure simple bindings. An example to add
and remove the one in the XML example above:
WildFly 9
Object Factories
The Naming subsystem configuration allows the binding of javax.naming.spi.ObjectFactory entries,
through the object-factory XML element, for instance:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The class attribute is mandatory and defines the object factory's Java type.
The module attribute is mandatory and specifies the JBoss Module ID where the object factory Java class
may be loaded from.
The optional environment child element may be used to provide a custom environment to the object
factory.
Management clients, such as the WildFly CLI, may be used to configure object factory bindings. An example
to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:add(binding-type=object-factory,
module=org.foo.bar, class=org.foo.bar.ObjectFactory, environment=[p1=v1, p2=v2])
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:remove
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
The name attribute is mandatory and specifies the target JNDI name for the entry.
WildFly 9
The class attribute is mandatory and indicates the Java initial naming context type used to create the
federated context. Note that such type must have a constructor with a single environment map argument.
The optional module attribute specifies the JBoss Module ID where any classes required by the external
JNDI context may be loaded from.
The optional cache attribute, which value defaults to false, indicates if the external context instance
should be cached.
The optional environment child element may be used to provide the custom environment needed to
lookup the external context.
Management clients, such as the WildFly CLI, may be used to configure external context bindings. An
example to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:add(binding-type=external-context,
cache=true, class=javax.naming.directory.InitialDirContext,
environment=[java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory,
java.naming.provider.url=ldap\:\/\/ldap.example.com\:389,
java.naming.security.authentication=simple,
java.naming.security.principal=uid\=admin\,ou\=system, java.naming.security.credentials=
secret])
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:remove
Some JNDI providers may fail when their resources are looked up if they do not implement properly the
lookup(Name) method. Their errors would look like:
11:31:49,047 ERROR org.jboss.resource.adapter.jms.inflow.JmsActivation (default-threads
-1) javax.naming.InvalidNameException: Only support CompoundName names
at com.tibco.tibjms.naming.TibjmsContext.lookup(TibjmsContext.java:504)
at javax.naming.InitialContext.lookup(InitialContext.java:421)
To work around their shortcomings, the org.jboss.as.naming.lookup.by.string property can be
specified in the external-context's environment to use instead the lookup(String) method (with a performance
degradation):
Binding Aliases
The Naming subsystem configuration allows the binding of existent entries into additional names, i.e.
aliases. Binding aliases are specified through the lookup XML element. An example of its XML
configuration:
WildFly 9
The name attribute is mandatory and specifies the target JNDI name for the entry.
The lookup attribute is mandatory and indicates the source JNDI name.
Management clients, such as the WildFly CLI, may be used to configure binding aliases. An example to add
and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/c:add(binding-type=lookup, lookup=java\:global\/b)
/subsystem=naming/binding=java\:global\/c:remove
Only entries within the java:jboss/exported context are accessible over remote JNDI.
In the subsystem's XML configuration, remote JNDI access bindings are configured through the
<remote-naming /> XML element:
<remote-naming />
Management clients, such as the WildFly CLI, may be used to add/remove the remote JNDI interface. An
example to add and remove the one in the XML example above:
/subsystem=naming/service=remote-naming:add
/subsystem=naming/service=remote-naming:remove
WildFly 9
For a detailed explanation how to deploy JDBC 4 compliant driver jar, please refer to the chapter "
Application Deployment".
Datasource Definitions
The datasource itself is defined within the subsystem datasources:
WildFly 9
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
<driver>h2</driver>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<xa-datasource jndi-name="java:jboss/datasources/ExampleXADS" pool-name="ExampleXADS">
<driver>h2</driver>
<xa-datasource-property name="URL">jdbc:h2:mem:test</xa-datasource-property>
<xa-pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</xa-pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</xa-datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
(See
standalone/configuration/standalone.xml)
As you can see the datasource references a driver by it's logical name.
You can easily query the same information through the CLI:
WildFly 9
[standalone@localhost:9999 /] /subsystem=datasources:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"data-source" => {"java:/H2DS" => {
"connection-url" => "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1",
"jndi-name" => "java:/H2DS",
"driver-name" => "h2",
"pool-name" => "H2DS",
"use-java-context" => true,
"enabled" => true,
"jta" => true,
"pool-prefill" => true,
"pool-use-strict-min" => false,
"user-name" => "sa",
"password" => "sa",
"flush-strategy" => "FailingConnectionOnly",
"background-validation" => false,
"use-fast-fail" => false,
"validate-on-match" => false,
"use-ccm" => true
}},
"xa-data-source" => undefined,
"jdbc-driver" => {"h2" => {
"driver-name" => "h2",
"driver-module-name" => "com.h2database.h2",
"driver-xa-datasource-class-name" => "org.h2.jdbcx.JdbcDataSource"
}}
}
}
[standalone@localhost:9999 /] /subsystem=datasources:installed-drivers-list
{
"outcome" => "success",
"result" => [{
"driver-name" => "h2",
"deployment-name" => undefined,
"driver-module-name" => "com.h2database.h2",
"module-slot" => "main",
"driver-xa-datasource-class-name" => "org.h2.jdbcx.JdbcDataSource",
"driver-class-name" => "org.h2.Driver",
"driver-major-version" => 1,
"driver-minor-version" => 2,
"jdbc-compliant" => true
}]
}
Using the web console or the CLI greatly simplifies the deployment of JDBC drivers and the
creation of datasources.
WildFly 9
[standalone@localhost:9999 /] help
Supported commands:
[...]
data-source
xa-data-source
This feature is primarily intended for development, and thus has a few limitations to be aware
of. It can not be altered in any of the management interfaces (consle, CLI, etc). Only limited runtime
information is available. Also, password vaults and security domains are not deployable, so these
can not be bundled with a datasource deployment.
Component Reference
The datasource subsystem is provided by the IronJacamar project. For a detailed description of the available
configuration properties, please consult the project documentation.
WildFly 9
5.6.4 Messaging
The JMS server configuration is done through the messaging subsystem. In this chapter we are going
outline the frequently used configuration options. For a more detailed explanation please consult the
HornetQ user guide (See "Component Reference").
Connectors
There are three kind of connectors that can be used to connect to WildFly JMS Server
invm-connector can be used by a local client (i.e. one running in the same JVM as the server)
netty-connector can be used by a remote client (and uses Netty over TCP for the
communication)
http-connector can be used by a remote client (and uses Undertow Web Server to upgrade from
a HTTP connection)
WildFly 9
A netty-connector is associated with a socket-binding which tells the client using the
connection-factory where to connect.
A connection-factory referencing a netty-connector is suitable to be used by a remote client
to send messages to or receive messages from the server (assuming the connection-factory has an
appropriately exported entry).
A pooled-connection-factory looked up in JNDI or injected which is referencing a
netty-connector is suitable to be used by a local client to send messages to a remote server
granted the socket-binding references an outbound-socket-binding pointing to the remote
server in question.
A pooled-connection-factory used by an MDB which is referencing a netty-connector is
suitable to consume messages from a remote server granted the socket-binding references an
outbound-socket-binding pointing to the remote server in question.
An in-vm-connector is associated with a server-id which tells the client using the
connection-factory where to connect (since multiple HornetQ servers can run in a single JVM).
A connection-factory referencing an in-vm-connector is suitable to be used by a local client
to either send messages to or receive messages from a local server.
A pooled-connection-factory looked up in JNDI or injected which is referencing an
in-vm-connector is suitable to be used by a local client only to send messages to a local server.
A pooled-connection-factory used by an MDB which is referencing an in-vm-connector is
suitable only to consume messages from a local server.
A http-connector is associated with the socket-binding that represents the HTTP socket (by default,
named http).
A connection-factory referencing a http-connector is suitable to be used by a remote client
to send messages to or receive messages from the server by connecting to its HTTP port before
upgrading to the messaging protocol.
A pooled-connection-factory referencing a http-connector is suitable to be used by a local
client to send messages to a remote server granted the socket-binding references an
outbound-socket-binding pointing to the remote server in question.
A pooled-connection-factory used by an MDB which is referencing a http-connector is
suitable only to consume messages from a remote server granted the socket-binding references
an outbound-socket-binding pointing to the remote server in question.
WildFly 9
The entry declaration of a connection-factory or a pooled-connection-factory specifies the
JNDI name under which the factory will be exposed. Only JNDI names bound in the
"java:jboss/exported" namespace are available to remote clients. If a connection-factory has
an entry bound in the "java:jboss/exported" namespace a remote client would look-up the
connection-factory using the text after "java:jboss/exported". For example, the "
RemoteConnectionFactory" is bound by default to
"java:jboss/exported/jms/RemoteConnectionFactory" which means a remote client would
look-up this connection-factory using "jms/RemoteConnectionFactory". A
pooled-connection-factory should not have any entry bound in the "java:jboss/exported"
namespace because a pooled-connection-factory is not suitable for remote clients.
Since JMS 2.0, a default JMS connection factory is accessible to EE application under the JNDI name
java:comp/DefaultJMSConnectionFactory. WildFly messaging subsystem defines a
pooled-connection-factory that is used to provide this default connection factory. Any parameter
change on this pooled-connection-factory will be take into account by any EE application looking the
default JMS provider under the JNDI name java:comp/DefaultJMSConnectionFactory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<connectors>
<http-connector name="http-connector" socket-binding="http">
<param key="http-upgrade-endpoint" value="http-acceptor"/>
</http-connector>
<http-connector name="http-connector-throughput" socket-binding="http">
<param key="http-upgrade-endpoint" value="http-acceptor-throughput"/>
<param key="batch-delay" value="50"/>
</http-connector>
<in-vm-connector name="in-vm" server-id="0"/>
</connectors>
[...]
<jms-connection-factories>
<connection-factory name="InVmConnectionFactory">
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/ConnectionFactory"/>
</entries>
</connection-factory>
<connection-factory name="RemoteConnectionFactory">
<connectors>
<connector-ref connector-name="http-connector"/>
</connectors>
<entries>
<entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
</entries>
</connection-factory>
<pooled-connection-factory name="hornetq-ra">
<transaction mode="xa"/>
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/JmsXA"/>
<!-- Global JNDI entry used to provide a default JMS Connection factory to EE
application -->
<entry name="java:jboss/DefaultJMSConnectionFactory"/>
</entries>
</pooled-connection-factory>
</jms-connection-factories>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<jms-destinations>
<jms-queue name="testQueue">
<entry name="jms/queue/test"/>
<entry name="java:jboss/exported/jms/queue/test"/>
</jms-queue>
<jms-topic name="testTopic">
<entry name="jms/topic/test"/>
<entry name="java:jboss/exported/jms/topic/test"/>
</jms-topic>
</jms-destinations>
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
[standalone@localhost:9990 /]
/subsystem=messaging/hornetq-server=default/jms-queue=myQueue:read-resource
{
"outcome" => "success",
"result" => {
"durable" => true,
"entries" => ["queues/myQueue"],
"selector" => undefined
}
}
WildFly 9
A number of additional commands to maintain the JMS subsystem are available as well:
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<address-settings>
<address-setting match="#">
<dead-letter-address>jms.queue.DLQ</dead-letter-address>
<expiry-address>jms.queue.ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
[...]
</address-setting>
</address-settings>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<security-settings>
<security-setting match="#">
<permission type="send" roles="guest"/>
<permission type="consume" roles="guest"/>
<permission type="createNonDurableQueue" roles="role1"/>
<permission type="deleteNonDurableQueue" roles="role1 role2"/>
</security-setting>
</security-settings>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<security-domain>mySecurityDomain</security-domain>
[...]
</hornetq-server>
</subsystem>
WildFly 9
Cluster Authentication
If the HornetQ server is configured to be clustered ( <clustered>true</clustered> ), it will use the
<cluster-user> and <cluster-password> attributes to connect to other HornetQ nodes in the cluster.
If you do not change the default value of <cluster-password>, HornetQ will fail to authenticate with the error:
To prevent this error, you must specify a value for <cluster-password>. It is possible to encrypt this
value by following this guide.
Alternatively, you can use the system property jboss.messaging.cluster.password to specify the cluster
password from the command line.
This feature is primarily intended for development as destinations deployed this way can not be
managed with any of the provided management tools (e.g. console, CLI, etc).
JMS Bridge
The function of a JMS bridge is to consume messages from a source JMS destination, and send them to a
target JMS destination. Typically either the source or the target destinations are on different servers.
The bridge can also be used to bridge messages from other non HornetQ JMS servers, as long as they are
JMS 1.1 compliant.
The JMS Bridge is provided by the HornetQ project. For a detailed description of the available configuration
properties, please consult the project documentation.
WildFly 9
modules/
`-- org
`-- acmemq
`-- main
|-- acmemq-1.2.3.jar
|-- mylogapi-0.0.1.jar
`-- module.xml
WildFly 9
<resources>
<!-- insert resources required to connect to the source or target
<!-- messaging brokers if it not another WildFly instance
<resource-root path="acmemq-1.2.3.jar" />
<resource-root path="mylogapi-0.0.1.jar" />
</resources>
<dependencies>
<!-- add the dependencies required by JMS Bridge code
<module name="javax.api" />
<module name="javax.jms.api" />
<module name="javax.transaction.api"/>
<module name="org.jboss.remote-naming"/>
<!-- we depend on org.hornetq module since we will send messages to
<!-- the HornetQ server embedded in the local WildFly instance
<module name="org.hornetq" />
</dependencies>
</module>
-->
-->
-->
-->
-->
WildFly 9
Configuration
A JMS bridge is defined inside a jms-bridge section of the `messaging` subsystem in the XML
configuration files.
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<jms-bridge name="myBridge" module="org.acmemq">
<source>
<connection-factory name="ConnectionFactory"/>
<destination name="sourceQ"/>
<user>user1</user>
<password>pwd1</password>
<context>
<property key="java.naming.factory.initial"
value="org.acmemq.jndi.AcmeMQInitialContextFactory"/>
<property key="java.naming.provider.url"
value="tcp://127.0.0.1:9292"/>
</context>
</source>
<target>
<connection-factory name="/jms/invmTargetCF"/>
<destination name="/jms/targetQ"/>
</target>
<quality-of-service>AT_MOST_ONCE</quality-of-service>
<failure-retry-interval>500</failure-retry-interval>
<max-retries>1</max-retries>
<max-batch-size>500</max-batch-size>
<max-batch-time>500</max-batch-time>
<add-messageID-in-header>true</add-messageID-in-header>
</jms-bridge>
</subsystem>
The source and target sections contain the name of the JMS resource (connection-factory and
destination) that will be looked up in JNDI.
It optionally defines the user and password credentials. If they are set, they will be passed as arguments
when creating the JMS connection from the looked up ConnectionFactory.
It is also possible to define JNDI context properties in the context section. If the context section is
absent, the JMS resources will be looked up in the local WildFly instance (as it is the case in the target
section in the example above).
WildFly 9
Management commands
A JMS Bridge can also be managed using the WildFly command line interface:
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=myBridge/:add(module="org.acmemq",
\
source-destination="sourceQ",
\
source-connection-factory="ConnectionFactory",
\
source-user="user1",
\
source-password="pwd1",
\
source-context={"java.naming.factory.initial" =>
"org.acmemq.jndi.AcmeMQInitialContextFactory", \
"java.naming.provider.url" => "tcp://127.0.0.1:9292"},
\
target-destination="/jms/targetQ",
\
target-connection-factory="/jms/invmTargetCF",
\
quality-of-service=AT_MOST_ONCE,
\
failure-retry-interval=500,
\
max-retries=1,
\
max-batch-size=500,
\
max-batch-time=500,
\
add-messageID-in-header=true)
{"outcome" => "success"}
You can also see the complete JMS Bridge resource description from the CLI:
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=*/:read-resource-description
{
"outcome" => "success",
"result" => [{
"address" => [
("subsystem" => "messaging"),
("jms-bridge" => "*")
],
"outcome" => "success",
"result" => {
"description" => "A JMS bridge instance.",
"attributes" => {
...
}
}]
}
WildFly 9
Component Reference
The messaging subsystem is provided by the HornetQ project. For a detailed description of the available
configuration properties, please consult the project documentation.
There are two main parts to the undertow subsystem, which are server and Servlet container configuration,
as well as some ancillary items. Advanced topics like load balancing and failover are covered on the "High
Availability Guide". The default configuration does is suitable for most use cases and provides reasonable
performance settings.
Required extension:
WildFly 9
<subsystem xmlns="urn:jboss:domain:undertow:1.0">
<buffer-caches>
<buffer-cache name="default" buffer-size="1024" buffers-per-region="1024"
max-regions="10"/>
</buffer-caches>
<server name="default-server">
<http-listener name="default" socket-binding="http" />
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content" />
</host>
</server>
<servlet-container name="default" default-buffer-cache="default"
stack-trace-on-error="local-only" >
<jsp-config/>
<persistent-sessions/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"
directory-listing="true"/>
</handlers>
</subsystem>
<buffer-caches>
<buffer-cache name="default" buffer-size="1024" buffers-per-region="1024" max-regions="10"/>
</buffer-caches>
Attribute
Description
buffer-size
The size of the buffers. Smaller buffers allow space to be utilised more effectively
The maximum number of regions. This controls the maximum amount of memory that
can be used for caching
WildFly 9
Server configuration
A server represents an instance of Undertow. Basically this consists of a set of connectors and some
configured handlers.
Attribute
Description
default-host
the virtual host that will be used if an incoming request as no Host: header
servlet-container the servlet container that will be used by this server, unless is is explicitly overriden by
the deployment
Connector configuration
Undertow provides HTTP, HTTPS and AJP connectors, which are configured per server.
WildFly 9
Common settings
The following settings are common to all connectors:
Attribute
Description
socket-binding
The socket binding to use. This determines the address and port the listener listens
on.
worker
buffer-pool
enabled
max-post-size
buffer-pipelined-data
max-header-size
The maximum size of a HTTP header block that is allowed. Responses with to
much data in their header block will have the request terminated and a bad request
response send.
max-parameters
The maximum number of query or path parameters that are allowed. This limit
exists to prevent hash collision based DOS attacks.
max-headers
The maximum number of headers that are allowed. This limit exists to prevent
hash collision based DOS attacks.
max-cookies
The maximum number of cookies that are allowed. This limit exists to prevent hash
collision based DOS attacks.
allow-encoded-slash
Set this to true if you want the server to decode percent encoded slash characters.
This is probably a bad idea, as it can have security implications, due to different
servers interpreting the slash differently. Only enable this if you have a legacy
application that requires it.
decode-url
If the URL should be decoded. If this is not set to true then percent encoded
characters in the URL will be left as is.
url-charset
always-set-keep-alive If the 'Connection: keep-alive' header should be added to all responses, even if not
required by spec.
WildFly 9
HTTP Connector
<http-listener name="default" socket-binding="http"
/>
Attribute
Description
certificate-forwarding
If this is set to true then the HTTP listener will read a client certificate from the
SSL_CLIENT_CERT header. This allows client cert authentication to be used,
even if the server does not have a direct SSL connection to the end user. This
should only be enabled for servers behind a proxy that has been configured to
always set these headers.
redirect-socket
HTTPS listener
Https listener provides secure access to the server. The most important configuration option is security realm
which defines SSL secure context.
Attribute
Description
security-realm
The security realm to use for the SSL configuration. See Security realm examples
for how to configure it: Examples
verify-client
AJP listener
<ajp-listener name="default" socket-binding="ajp" />
WildFly 9
Host configuration
The host element corresponds to a virtual host.
Attribute
Description
name
alias
default-web-module The name of a deployment that should be used to serve up requests that do not
match anything.
Description
The buffer cache that is used to cache static resources in the default
Servlet.
stack-trace-on-error
Can be either all, none, or local-only. When set to none Undertow will never
display stack traces. When set to All Undertow will always display them (not
recommended for production use). When set to local-only Undertow will
only display them for requests from local addresses, where there are no
headers to indicate that the request has been proxied. Note that this feature
means that the Undertow error page will be displayed instead of the default
error page specified in web.xml.
default-encoding
use-listener-encoding
If this is true then the default encoding will be the same as that used by the
listener that received the request.
JSP configuration
WildFly 9
domain
secure
max-age
Description
path
WildFly 9
Name
Type
Description
modify-wsdl-address
boolean This boolean enables and disables the address rewrite functionality.
When modify-wsdl-address is set to true and the content of
<soap:address> is a valid URL, JBossWS will rewrite the URL using the
values of wsdl-host and wsdl-port or wsdl-secure-port.
When modify-wsdl-address is set to false and the content of
<soap:address> is a valid URL, JBossWS will not rewrite the URL. The
<soap:address> URL will be used.
When the content of <soap:address> is not a valid URL, JBossWS will
rewrite it no matter what the setting of modify-wsdl-address.
If modify-wsdl-address is set to true and wsdl-host is not defined or
explicitly set to 'jbossws.undefined.host' the content of
<soap:address> URL is use. JBossWS uses the requester's host when
rewriting the <soap:address>
When modify-wsdl-address is not defined JBossWS uses a default value
of true.
wsdl-host
string
wsdl-port
int
Set this property to explicitly define the HTTP port that will be used for
rewriting the SOAP address.
Otherwise the HTTP port will be identified by querying the list of installed
HTTP connectors.
wsdl-secure-port
int
Set this property to explicitly define the HTTPS port that will be used for
rewriting the SOAP address.
Otherwise the HTTPS port will be identified by querying the list of
installed HTTPS connectors.
wsdl-uri-scheme
string
This property explicitly sets the URI scheme to use for rewriting
<soap:address> . Valid values are http and https. This
configuration overrides scheme computed by processing the endpoint
(even if a transport guarantee
is specified). The provided values for wsdl-port and
wsdl-secure-port (or their default values) are used depending on
specified scheme.
WildFly 9
wsdl-path-rewrite-rule string
[standalone@localhost:9999 /] /subsystem=webservices:read-resource
{
"outcome" => "success",
"result" => {
"endpoint" => {},
"modify-wsdl-address" => true,
"wsdl-host" => expression "${jboss.bind.address:127.0.0.1}",
"endpoint-config" => {
"Standard-Endpoint-Config" => undefined,
"Recording-Endpoint-Config" => undefined
}
}
}
WildFly 9
Endpoint configs
Endpoint configs are defined using the endpoint-config element. Each endpoint configuration may
include properties and handlers set to the endpoints associated to the configuration.
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config:read-resource
{
"outcome" => "success",
"result" => {
"post-handler-chain" => undefined,
"property" => undefined,
"pre-handler-chain" => {"recording-handlers" => undefined}
}
}
[standalone@localhost:9999 /] /subsystem=webservices/endpoint-config=My-Endpoint-Config:add
{
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
WildFly 9
Handler chains
Each endpoint configuration may be associated with zero or more PRE and POST handler chains. Each
handler chain may include JAXWS handlers. For outbound messages the PRE handler chains are executed
before any handler that is attached to the endpoint using the standard means, such as with annotation
@HandlerChain, and POST handler chains are executed after those objects have executed. For inbound
messages the POST handler chains are executed before any handler that is attached to the endpoint using
the standard means and the PRE handler chains are executed after those objects have executed.
The protocol-binding attribute must be used to set the protocols for which the chain will be triggered.
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers:read-res
"outcome" => "success",
"result" => {
"protocol-bindings" => "##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP
##SOAP12_HTTP_MTOM",
"handler" => {"RecordingHandler" => undefined}
},
"response-headers" => {"process-state" => "restart-required"}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers:add(protocol-bindings
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers:read-resource{
"outcome" => "success",
"result" => {
"handler" => undefined,
"protocol-bindings" => "##SOAP11_HTTP"
},
"response-headers" => {"process-state" => "restart-required"}
}
WildFly 9
Handlers
JAXWS handler can be added in handler chains:
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers/handler=
"outcome" => "success",
"result" => {"class" => "org.jboss.ws.common.invocation.RecordingServerHandler"},
"response-headers" => {"process-state" => "restart-required"}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers/handler=foo-handler:a
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
WildFly 9
Runtime information
Each web service endpoint is exposed through the deployment that provides the endpoint implementation.
Each endpoint can be queried as a deployment resource. For further information please consult the chapter
"Application Deployment". Each web service endpoint specifies a web context and a WSDL Url:
[standalone@localhost:9999 /] /deployment="*"/subsystem=webservices/endpoint="*":read-resource
{
"outcome" => "success",
"result" => [{
"address" => [
("deployment" => "jaxws-samples-handlerchain.war"),
("subsystem" => "webservices"),
("endpoint" => "jaxws-samples-handlerchain:TestService")
],
"outcome" => "success",
"result" => {
"class" => "org.jboss.test.ws.jaxws.samples.handlerchain.EndpointImpl",
"context" => "jaxws-samples-handlerchain",
"name" => "TestService",
"type" => "JAXWS_JSE",
"wsdl-url" => "http://localhost:8080/jaxws-samples-handlerchain?wsdl"
}
}]
}
Component Reference
The web service subsystem is provided by the JBossWS project. For a detailed description of the available
configuration properties, please consult the project documentation.
WildFly 9
5.6.7 Logging
Overview
Attributes
add-logging-api-dependencies
use-deployment-logging-config
Per-deployment Logging
Logging Profiles
Default Log File Locations
Managed Domain
Standalone Server
Filter Expressions
List Log Files and Reading Log Files
List Log Files
Read Log File
FAQ
Why is there a logging.properties file?
WildFly 9
Overview
The overall server logging configuration is represented by the logging subsystem. It consists of four notable
parts: handler configurations, logger, the root logger declarations (aka log categories) and logging
profiles. Each logger does reference a handler (or set of handlers). Each handler declares the log format and
output:
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE" autoflush="true">
<level name="DEBUG"/>
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
</console-handler>
<periodic-rotating-file-handler name="FILE" autoflush="true">
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN"/>
</logger>
[...]
<root-logger>
<level name="DEBUG"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
</subsystem>
Attributes
The root resource contains two notable attributes add-logging-api-dependencies and
use-deployment-logging-config.
logging-api-dependencies
The add-logging-api-dependencies controls whether or not the container adds implicit logging API
dependencies to your deployments. If set to true, the default, all the implicit logging API dependencies are
added. If set to false the dependencies are not added to your deployments.
deployment-logging-config
The use-deployment-logging-config controls whether or not your deployment is scanned for
per-deployment logging. If set to true, the default, per-deployment logging is enabled. Set to false to
disable this feature.
WildFly 9
deployment Logging
Per-deployment logging allows you to add a logging configuration file to your deployment and have the
logging for that deployment configured according to the configuration file. In an EAR the configuration should
be in the META-INF directory. In a WAR or JAR deployment the configuration file can be in either the
META-INF or WEB-INF directories.
The following configuration files are allowed:
logging.properties
jboss-logging.properties
log4j.properties
log4j.xml
jboss-log4j.xml
You can also disable this functionality by changing the use-deployment-logging-config attribute to
false.
Logging Profiles
Logging profiles are like additional logging subsystems. Each logging profile constists of three of the four
notable parts listed above: handler configurations, logger and the root logger declarations.
You can assign a logging profile to a deployment via the deployments manifest. Add a Logging-Profile
entry to the MANIFEST.MF file with a value of the logging profile id. For example a logging profile defined on
/subsystem=logging/logging-profile=ejbs the MANIFEST.MF would look like:
Manifest-Version: 1.0
Logging-Profile: ejbs
A logging profile can be assigned to any number of deployments. Using a logging profile also allows for
runtime changes to the configuration. This is an advantage over the per-deployment logging configuration as
the redeploy is not required for logging changes to take affect.
WildFly 9
Log File
Host Controller
./domain/log/host-controller.log
./domain/servers/server-one/log/server.log
"Server Two"
./domain/servers/server-two/log/server.log
"Server Three"
./domain/servers/server-three/log/server.log
Standalone Server
The default log files for a standalone server can be found in the log subdirectory of the distribution:
Process Log File
Server
./standalone/log/server.log
Filter Expressions
Filter Type
Expression
Description
Parameter(s)
Examples
accept
accept
None
accept
None
deny
Accepts a filter as
The expression
not(match("JBAS"))
an argument and
takes a single
inverts the
returned value.
argument.
messages.
deny
deny
not
not(filterExpression)
WildFly 9
all
all(filterExpressions)
A filter consisting
The expression
all(match("JBAS"),
of several filters in
takes a comma
match("WELD"))
a chain. If any
delimited list of
message to be
argument.
unloggable, the
message will not
be logged and
subsequent filters
will not be
checked.
any
any(filterExpressions)
A filter consisting
The expression
any(match("JBAS"),
of several filters in
takes a comma
match("WELD"))
a chain. If any
delimited list of
message to be
argument.
loggable, the
message will be
logged and the
subsequent filters
will not be
checked.
levelChange levelChange(level)
levels
levels(levels)
A filter which
The expression
levelChange("WARN")
takes a single
level.
A filter which
The expression
levels("DEBUG", "INFO",
includes log
takes a comma
"WARN", "ERROR")
messages with a
delimited list of
string based
WildFly 9
levelRange
The filter
expression uses
a "[" to indicate a
range.
minimum
inclusive level
and a "]" to
than DEBUG
indicate a
maximum
levelRange("ERROR",
inclusive level.
"DEBUG")
or ")" respectively
indicate
exclusive. The
be greater than
the expression is
DEBUG
the minimum
level allowed, the
levelRange["ERROR",
second argument
"DEBUG")
is the maximum
level allowed.
match
match("pattern")
The expression
raw unformatted
argument.
message is used
match("JBAS\d+")
against the
pattern.
substitute
substitute("pattern",
A filter which
The first
"replacement value")
match to the
expression is the
pattern the
replacement
second argument
value.
is the
substitute("JBAS", "EAP")
replacement text.
WildFly 9
substituteAll substituteAll("pattern",
"replacement value")
A filter which
The first
replaces all
matches of the
expression is the
pattern the
replacement
second argument
value.
is the
substituteAll("JBAS", "EAP")
replacement text.
WildFly 9
Description
the number of lines from the file. A value of -1 indicates all lines should be read.
skip
tail
true to read from the end of the file up or false to read top down.
WildFly 9
FAQ
Why is there a logging.properties file?
You may have noticed that there is a logging.properties file in the configuration directory. This is
logging configuration is used when the server boots up until the logging subsystem kicks in. If the logging
subsystem is not included in your configuration, then this would act as the logging configuration for the entire
server.
The logging.properties file is overwritten at boot and with each change to the logging
subsystem. Any changes made to the file are not persisted. Any changes made to the XML
configuration or via management operations will be persisted to the logging.properties file
and used on the next boot.
5.6.8 Security
The security subsystem is the subsystem that brings the security services provided by PicketBox to the
WildFly 8 server instances.
If you are looking to secure the management interfaces for the management of the domain then you should
read the Securing the Management Interfaces chapter as the management interfaces themselves are not
run within a WildFly process so use a custom configuration.
WildFly 9
Authentication Manager
The authentication manager is the component that performs the actual authentication taking the declared
users identity and their credential so that the login context for the security domain can be used to 'login' the
user using the configured login module or modules.
Authorization Manager
The authorization manager is a component which can be obtained by the container from the current security
context to either obtain information about a users roles or to perform an authorization check against a
resource for the currently authenticated user.
Audit Manager
The audit manager from the security context is the component that can be used to log audit events in
relation to the security domain.
Mapping Manager
The mapping manager can be used to assign additional principals, credentials, roles or attributes to the
authenticated subject.
WildFly 9
security-management
subject-factory
security-domains
security-properties
security-management
This element is used to override some of the high level implementation details of the PicketBox
implementation if you have a need to change some of this behaviour.
The element can have any or the following attributes set, all of which are optional.
authentication-manager-class-name Specifies the AuthenticationManager implementation class name to
use.
deep-copy-subject-mode
audit-manager-class-name
identity-trust-manager-class-name
mapping-manager-class-name
subject-factory
The subject factory is responsible for creating subject instances, this also makes use of the authentication
manager to actually verify the caller. It is used mainly by JCA components to establish a subject. It is not
likely this would need to be overridden but if it is required the "subject-factory-class-name" attribute can be
specified on the subject-factory element.
security-domains
This portion of the configuration is where the bulk of the security subsystem configuration will actually take
place for most administrators, the security domains contain the configuration which is specific to a
deployment.
WildFly 9
The security-domains element can contain numerous <security-domain> definitions, a security-domain can
have the following attributes set:
name
extends
cache-type The type of authentication cache to use with this domain. If this attribute is removed no cache
will be used. Allowed values are "default" or "infinispan"
The following elements can then be set within the security-domain to configure the domain behaviour.
authentication
The authentication element is used to hold the list of login modules that will be used for authentication when
this domain is used, the structure of the login-module element is:
The code attribute is used to specify the implementing class of the login module which can either be the full
class name or one of the abbreviated names from the following list:
WildFly 9
Code
Classname
Client
org.jboss.security.ClientLoginModule
Certificate
org.jboss.security.auth.spi.BaseCertLoginModule
CertificateUsers
org.jboss.security.auth.spi.BaseCertLoginModule
CertificateRoles
org.jboss.security.auth.spi.CertRolesLoginModule
Database
org.jboss.security.auth.spi.DatabaseServerLoginModule
DatabaseCertificate org.jboss.security.auth.spi.DatabaseCertLoginModule
DatabaseUsers
org.jboss.security.auth.spi.DatabaseServerLoginModule
Identity
org.jboss.security.auth.spi.IdentityLoginModule
Ldap
org.jboss.security.auth.spi.LdapLoginModule
LdapExtended
org.jboss.security.auth.spi.LdapExtLoginModule
RoleMapping
org.jboss.security.auth.spi.RoleMappingLoginModule
RunAs
org.jboss.security.auth.spi.RunAsLoginModule
Simple
org.jboss.security.auth.spi.SimpleServerLoginModule
ConfiguredIdentity
org.picketbox.datasource.security.ConfiguredIdentityLoginModule
SecureIdentity
org.picketbox.datasource.security.SecureIdentityLoginModule
PropertiesUsers
org.jboss.security.auth.spi.PropertiesUsersLoginModule
SimpleUsers
org.jboss.security.auth.spi.SimpleUsersLoginModule
LdapUsers
org.jboss.security.auth.spi.LdapUsersLoginModule
Kerberos
com.sun.security.auth.module.Krb5LoginModule
SPNEGOUsers
org.jboss.security.negotiation.spnego.SPNEGOLoginModule
AdvancedLdap
org.jboss.security.negotiation.AdvancedLdapLoginModule
AdvancedADLdap
org.jboss.security.negotiation.AdvancedADLoginModule
UsersRoles
org.jboss.security.auth.spi.UsersRolesLoginModule
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The flag attribute is used to specify the JAAS flag for this module and should be one of required, requisite,
sufficient, or optional.
WildFly 9
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
See Authentication Modules for further details on the various modules listed above.
authentication-jaspi
The authentication-jaspi is used to configure a Java Authentication SPI (JASPI) provider as the
authentication mechanism. A security domain can have either a <authentication> or a <authentication-jaspi>
element, but not both. We set up JASPI by configuring one or more login modules inside the
login-module-stack element and setting up an authentication module. Here is the structure of the
authentication-jaspi element:
<login-module-stack name="...">
<login-module code="..." flag="..." module="...">
<module-option name="..." value="..."/>
</login-module>
</login-module-stack>
<auth-module code="..." login-module-stack-ref="...">
<module-option name="..." value="..."/>
</auth-module>
The login-module-stack-ref attribute value must be the name of the login-module-stack element to be used.
The sub-element login-module is configured just like in the authentication part
WildFly 9
authorization
Authorization in the AS container is normally done with RBAC (role based access control) but there are
situations where a more fine grained authorization policy is required. The authorization element allows
definition of different authorization modules to used, such that authorization can be checked with JACC
(Java Authorization Contract for Containers) or XACML (eXtensible Access Control Markup Language). The
structure of the authorization element is:
The code attribute is used to specify the implementing class of the policy module which can either be the full
class name or one of the abbreviated names from the following list:
Code
Classname
DenyAll
org.jboss.security.authorization.modules.AllDenyAuthorizationModule
PermitAll
org.jboss.security.authorization.modules.AllPermitAuthorizationModule
Delegating org.jboss.security.authorization.modules.DelegatingAuthorizationModule
Web
org.jboss.security.authorization.modules.WebAuthorizationModule
JACC
org.jboss.security.authorization.modules.JACCAuthorizationModule
XACML
org.jboss.security.authorization.modules.XACMLAuthorizationModule
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The flag attribute is used to specify the JAAS flag for this module and should be one of required, requisite,
sufficient, or optional.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
WildFly 9
mapping
The mapping element defines additional mapping of principals, credentials, roles and attributes for the
subject. The structure of the mapping element is:
The type attribute reflects the type of mapping of the provider and should be one of principal, credential, role
or attribute. By default "role" is the type used if the attribute is not set.
The code attribute is used to specify the implementing class of the login module which can either be the full
class name or one of the abbreviated names from the following list:
Code
Classname
PropertiesRoles
org.jboss.security.mapping.providers.role.PropertiesRolesMappingProvider
SimpleRoles
org.jboss.security.mapping.providers.role.SimpleRolesMappingProvider
DeploymentRoles org.jboss.security.mapping.providers.DeploymentRolesMappingProvider
DatabaseRoles
org.jboss.security.mapping.providers.role.DatabaseRolesMappingProvider
LdapRoles
org.jboss.security.mapping.providers.role.LdapRolesMappingProvider
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
audit
The audit element can be used to define a custom audit provider. The default implementation used is
org.jboss.security.audit.providers.LogAuditProvider. The structure of the audit element is:
The code attribute is used to specify the implementing class of the provider module.
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
WildFly 9
jsse
The jsse element defines configuration for keystores and truststores that can be used for SSL context
configuration or for certificate storing/retrieving.
The set of attributes (all of them optional) of this element are:
WildFly 9
keystore-password
keystore-type
keystore-url
keystore-provider
Provider of the keystore. The default JDK provider for the keystore
type is used if this attribute is null
keystore-provider-argument
key-manager-factory-algorithm
key-manager-factory-provider
truststore-password
truststore-type
truststore-url
truststore-provider
Provider of the truststore. The default JDK provider for the truststore
type is used if this attribute is null
truststore-provider-argument
client-alias
Alias of the keystore to be used when creating client side SSL sockets
server-alias
Alias of the keystore to be used when creating server side SSL sockets
service-auth-token
client-auth
Flag to indicate if the server side SSL socket should require client
authentication. Default is "false"
cipher-suites
protocols
The optional additional-properties element can be used to include other options. The structure of the jsse
element is:
WildFly 9
security-properties
This element is used to specify additional properties as required by the security subsystem, properties are
specified in the following format:
<security-properties>
<property name="..." value="..."/>
</security-properties>
The property element can be repeated as required for as many properties need to be defined.
Each property specified is set on the java.security.Security class.
5.6.9 JMX
The JMX subsystem registers a service with the Remoting endpoint so that remote access to JMX can be
obtained over the exposed Remoting connector.
This is switched on by default in standalone mode and accessible over port 9990 but in domain mode is
switched off so needs to be enabled - in domain mode the port will be the port of the Remoting connector for
the WildFly 8 instance to be monitored.
To use the connector you can access it in the standard way using a service:jmx URL:
WildFly 9
import
import
import
import
javax.management.MBeanServerConnection;
javax.management.remote.JMXConnector;
javax.management.remote.JMXConnectorFactory;
javax.management.remote.JMXServiceURL;
You also need to set your classpath when running the above example. The following script covers Linux. If
your environment is much different, paste your script when you have it working.
!/bin/bash
# specify your WildFly 8 folder
export YOUR_JBOSS_HOME=~/WildFly8
java -classpath $YOUR_JBOSS_HOME/bin/client/jboss-client.jar:./ JMXExample
If using jconsole use the jconsole.sh and jconsole.bat scripts included in the /bin directory
of the WildFly 8 distribution as these set the classpath as required to connect over Remoting.
In addition to the standard JVM MBeans, the WildFly 8 MBean server contains the following MBeans:
WildFly 9
JMX ObjectName
Description
Audit logging
Audit logging for the JMX MBean server managed by the JMX subsystem. The resource is at
/subsystem=jmx/configuration=audit-log and its attributes are similar to the ones mentioned for
/core-service=management/access=audit/logger=audit-log in Audit logging.
Attribute
Description
enabled
log-boot
true to log the JMX operations when booting the server, false otherwise
log-read-only If true all operations will be audit logged, if false only operations that change the
model will be logged
Then which handlers are used to log the management operations are configured as handler=* children of
the logger. These handlers and their formatters are defined in the global
/core-service=management/access=audit section mentioned in Audit logging.
JSON Formatter
The same JSON Formatter is used as described in Audit logging. However the records for MBean Server
invocations have slightly different fields from those logged for the core management layer.
WildFly 9
2013-08-29 18:26:29 - {
"type" : "jmx",
"r/o" : false,
"booting" : false,
"version" : "8.0.0.Beta1-SNAPSHOT",
"user" : "$local",
"domainUUID" : null,
"access" : "JMX",
"remote-address" : "127.0.0.1/127.0.0.1",
"method" : "invoke",
"sig" : [
"javax.management.ObjectName",
"java.lang.String",
"[Ljava.lang.Object;",
"[Ljava.lang.String;"
],
"params" : [
"java.lang:type=Threading",
"getThreadInfo",
"[Ljava.lang.Object;@5e6c33c",
"[Ljava.lang.String;@4b681c69"
]
}
It includes an optional timestamp and then the following information in the json record
WildFly 9
Field name
Description
type
This will have the value jmx meaning it comes from the jmx subsystem
r/o
booting
true if the operation was executed during the bootup process, false if it was
executed once the server is up and running
version
user
domainUUID
access
sig
params
error
If calling the MBeanServer method resulted in an error, this field will be populated with
Throwable.getMessage()
WildFly 9
<subsystem xmlns="urn:jboss:domain:resource-adapters:1.0">
<resource-adapters>
<resource-adapter>
<archive>eis.rar</archive>
<!-- Resource adapter level config-property -->
<config-property name="Server">localhost</config-property>
<config-property name="Port">19000</config-property>
<transaction-support>XATransaction</transaction-support>
<connection-definitions>
<connection-definition class-name="com.acme.eis.ra.EISManagedConnectionFactory"
jndi-name="java:/eis/AcmeConnectionFactory"
pool-name="AcmeConnectionFactory">
<!-- Managed connection factory level config-property -->
<config-property name="Name">Acme Inc</config-property>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
</pool>
<security>
<application/>
</security>
</connection-definition>
</connection-definitions>
<admin-objects>
<admin-object class-name="com.acme.eis.ra.EISAdminObjectImpl"
jndi-name="java:/eis/AcmeAdminObject">
<config-property name="Threshold">10</config-property>
</admin-object>
</admin-objects>
</resource-adapter>
</resource-adapters>
</subsystem>
Note, that only JNDI bindings under java:/ or java:jboss/ are supported.
(See
standalone/configuration/standalone.xml)
WildFly 9
Component Reference
The resource adapter subsystem is provided by the IronJacamar project. For a detailed description of the
available configuration properties, please consult the project documentation.
IronJacamar homepage: http://www.jboss.org/ironjacamar
Project Documentation: http://www.jboss.org/ironjacamar/docs
Schema description:
http://docs.jboss.org/ironjacamar/userguide/1.0/en-US/html/deployment.html#deployingra_descriptor
<subsystem xmlns="urn:jboss:domain:deployment-scanner:1.0">
<deployment-scanner scan-interval="5000"
relative-to="jboss.server.base.dir" path="deployments" />
</subsystem>
You can define more deployment-scanner entries to scan for deployments from more locations. The
configuration showed will scan the JBOSS_HOME/standalone/deployments directory every five
seconds. The runtime model is shown below, and uses default values for attributes not specified in the xml:
[standalone@localhost:9999 /] /subsystem=deployment-scanner:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"scanner" => {"default" => {
"auto-deploy-exploded" => false,
"auto-deploy-zipped" => true,
"deployment-timeout" => 60L,
"name" => "default",
"path" => "deployments",
"relative-to" => "jboss.server.base.dir",
"scan-enabled" => true,
"scan-interval" => 5000
}}}
}
WildFly 9
Name
Type
Description
name
STRING
path
STRING
relative-to
STRING
scan-enabled
scan-interval
INT
auto-deploy-zipped
LONG
Deployment scanners can be added by modifying standalone.xml before starting up the server or they
can be added and removed at runtime using the CLI
[standalone@localhost:9999 /]
/subsystem=deployment-scanner/scanner=new:add(scan-interval=10000,relative-to="jboss.server.base.dir",path="ot
=> "success"}
[standalone@localhost:9999 /] /subsystem=deployment-scanner/scanner=new:remove
{"outcome" => "success"}
You can also change the attributes at runtime, so for example to turn off scanning you can do
WildFly 9
[standalone@localhost:9999 /]
/subsystem=deployment-scanner/scanner=default:write-attribute(name="scan-enabled",value=false)
{"outcome" => "success"}
[standalone@localhost:9999 /] /subsystem=deployment-scanner:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"scanner" => {"default" => {
"auto-deploy-exploded" => false,
"auto-deploy-zipped" => true,
"deployment-timeout" => 60L,
"name" => "default",
"path" => "deployments",
"relative-to" => "jboss.server.base.dir",
"scan-enabled" => false,
"scan-interval" => 5000
}}}
}
<subsystem
<subsystem
<subsystem
<subsystem
xmlns="urn:jboss:domain:jaxrs:1.0"/>
xmlns="urn:jboss:domain:jdr:1.0"/>
xmlns="urn:jboss:domain:pojo:1.0"/>
xmlns="urn:jboss:domain:sar:1.0"/>
Description
Enables the gathering of diagnostic data for use in remote analysis of error conditions. Although
the data is in a simple format and could be useful to anyone, primarily useful for JBoss EAP
subscribers who would provide the data to Red Hat when requesting support
pojo
sar
Enables the deployment of .SAR archives containing MBean services, as supported by previous
versions of JBoss Application Server
WildFly 9
Example IP Adresses
In this example the domain controller uses 192.168.0.101 and the host controller 192.168.0.10
Configuring a host to act as the Domain Controller is done through the domain-controller declaration in
host.xml. If it includes the <local/> element, then this host will become the domain controller:
<domain-controller>
<local/>
</domain-controller>
(See domain/configuration/host.xml)
A host acting as the Domain Controller must expose a management interface on an address accessible to
the other hosts in the domain. Exposing an HTTP(S) management interface is not required, but is
recommended as it allows the Administration Console to work:
<management-interfaces>
<native-interface security-realm="ManagementRealm">
<socket interface="management" port="${jboss.management.native.port:9999}"/>
</native-interface>
<http-interface security-realm="ManagementRealm">
<socket interface="management" port="${jboss.management.http.port:9990}"/>
</http-interface>
</management-interfaces>
The interface attributes above refer to a named interface declaration later in the host.xml file. This interface
declaration will be used to resolve a corresponding network interface.
WildFly 9
<interfaces>
<interface name="management">
<inet-address value="192.168.0.101"/>
</interface>
</interfaces>
(See domain/configuration/host.xml)
Please consult the chapter "Interface Configuration" for a more detailed explanation on how to configure
network interfaces.
Next by default the master domain controller is configured to require authentication so a user needs to be
added that can be used by the slave domain controller to connect.
Make use of the add-user utility to add a new user, for this example I am adding a new user called slave.
add-user MUST be run on the master domain controller and NOT the slave.
When you reach the final question of the interactive flow answer y or yes to indicate that the new user will
be used for a process e.g.
Is this new user going to be used for one AS process to connect to another AS process e.g. slave
domain controller?
yes/no? y
To represent the user add the following to the server-identities definition <secret
value="cE3EBEkE=" />
Make a note of the XML Element output as that is going to be required within the slave configuration.
<host xmlns="urn:jboss:domain:3.0"
name="slave">
[...]
</host>
WildFly 9
(See domain/configuration/host.xml)
If the name attribute is not set, the default name for the host will be the value of the jboss.host.name}
system property. If that is not set, the value of the {{HOSTNAME or COMPUTERNAME
environment variable will be used, one of which will be set on most operating systems. If neither is set the
name will be the value of InetAddress.getLocalHost().getHostName().
A security realm needs to be defined to hold the identity of the slave. Since it is performing a specific
purpose I would suggest a new realm is defined although it is possible to combine this with an existing
realm.
<security-realm name="SlaveRealm">
<server-identities>
<secret value="cE3EBEkE=" />
</server-identities>
</security-realm>
The <secret /> element here is the one output from add-user previously. To create the <secret />
element yourself the value needs to be the password encoded using Base64.
Tell it how to find the domain controller so it can register itself with the domain:
<domain-controller>
<remote protocol="remote" host="192.168.0.101" port="9999" username="slave"
security-realm="SlaveRealm"/>
</domain-controller>
Since we have also exposed the HTTP management interface we could also use :
<domain-controller>
<remote protocol="http-remoting" host="192.168.0.101" port="9990" username="slave"
security-realm="SlaveRealm"/>
</domain-controller>
(See domain/configuration/host.xml)
The username attribute here is optional, if it is omitted then the name of the host will be used instead, in this
example that was already set to name.
The name of each host needs to be unique when registering with the domain controller, however
the username does not - using the username attribute allows the same account to be used by
multiple hosts if this makes sense in your environment.
The <remote /> element is also associated with the security realm SlaveRealm, this is how it picks up
the password from the <secret /> element.
WildFly 9
<server-groups>
<server-group name="main-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
<permgen size="128m" max-size="128m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
<server-group name="other-server-group" profile="bigger">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="bigger-sockets"/>
</server-group>
</server-groups>
(See domain/configuration/domain.xml)
The domain controller also defines the socket binding groups and the profiles. The socket binding groups
define the default socket bindings that are used:
<socket-binding-groups>
<socket-binding-group name="standard-sockets" default-interface="public">
<socket-binding name="http" port="8080"/>
[...]
</socket-binding-group>
<socket-binding-group name="bigger-sockets" include="standard-sockets"
default-interface="public">
<socket-binding name="unique-to-bigger" port="8123"/>
</socket-binding-group>
</socket-binding-groups>
(See domain/configuration/domain.xml)
In this example the bigger-sockets group includes all the socket bindings defined in the
standard-sockets groups and then defines an extra socket binding of its own.
A profile is a collection of subsystems, and these subsystems are what implement the functionality people
expect of an application server.
WildFly 9
<profiles>
<profile name="default">
<subsystem xmlns="urn:jboss:domain:web:1.0">
<connector name="http" scheme="http" protocol="HTTP/1.1" socket-binding="http"/>
[...]
</subsystem>
<\!-\- The rest of the subsystems here \-->
[...]
</profile>
<profile name="bigger">
<subsystem xmlns="urn:jboss:domain:web:1.0">
<connector name="http" scheme="http" protocol="HTTP/1.1" socket-binding="http"/>
[...]
</subsystem>
<\!-\- The same subsystems as defined by 'default' here \-->
[...]
<subsystem xmlns="urn:jboss:domain:fictional-example:1.0">
<socket-to-use name="unique-to-bigger"/>
</subsystem>
</profile>
</profiles>
(See domain/configuration/domain.xml)
Here we have two profiles. The bigger profile contains all the same subsystems as the default profile
(athough the parameters for the various subsystems could be different in each profile), and adds the
fictional-example subsystem which references the unique-to-bigger socket binding.
5.7.4 Servers
The host controller defines one or more servers:
<servers>
<server name="server-one" group="main-server-group">
<\!-\- server-one inherits the default socket-group declared in the server-group \-->
<jvm name="default"/>
</server>
<server name="server-two" group="main-server-group" auto-start="true">
<socket-binding-group ref="standard-sockets" port-offset="150"/>
<jvm name="default">
<heap size="64m" max-size="256m"/>
</jvm>
</server>
<server name="server-three" group="other-server-group" auto-start="false">
<socket-binding-group ref="bigger-sockets" port-offset="250"/>
</server>
</servers>
(See domain/configuration/host.xml)
WildFly 9
server-one and server-two both are associated with main-server-group so that means they both
run the subsystems defined by the default profile, and have the socket bindings defined by the
standard-sockets socket binding group. Since all the servers defined by a host will be run on the same
physical host we would get port conflicts unless we used <socket-binding-group
ref="standard-sockets" port-offset="150"/> for server-two. This means that server-two
will use the socket bindings defined by standard-sockets but it will add 150 to each port number defined,
so the value used for http will be 8230 for server-two.
server-three will not be started due to its auto-start="false". The default value if no auto-start
is given is true so both server-one and server-two will be started when the host controller is started.
server-three belongs to other-server-group, so if its auto-start were changed to true it would
start up using the subsystems from the bigger profile, and it would use the bigger-sockets socket
binding group.
JVM
The host controller contains the main jvm definitions with arguments:
<jvms>
<jvm name="default">
<heap size="64m" max-size="128m"/>
</jvm>
</jvms>
(See domain/configuration/host.xml)
From the preceeding examples we can see that we also had a jvm reference at server group level in the
domain controller. The jvm's name must match one of the definitions in the host controller. The values
supplied at domain controller and host controller level are combined, with the host controller taking
precedence if the same parameter is given in both places.
Finally, as seen, we can also override the jvm at server level. Again, the jvm's name must match one of the
definitions in the host controller. The values are combined with the ones coming in from domain controller
and host controller level, this time the server definition takes precedence if the same parameter is given in all
places.
Following these rules the jvm parameters to start each server would be
Server
JVM parameters
server-one
server-two
WildFly 9
System properties
To set a system property, pass its new value using the standard jvm -Dkey=value options:
$JBOSS_HOME/bin/standalone.sh -Djboss.home.dir=some/location/WildFly/jboss-as \
-Djboss.server.config.dir=some/location/WildFly/jboss-as/custom-standalone
This command starts up a standalone server instance using a non-standard AS home directory and a
custom configuration directory. For specific information about system properties, refer to the definitions
below.
Instead of passing the parameters directly, you can put them into a properties file, and pass the properties
file to the script, as in the two examples below.
$JBOSS_HOME/bin/domain.sh --properties=/some/location/jboss.properties
$JBOSS_HOME/bin/domain.sh -P=/some/location/jboss.properties
Note however, that properties set this way are not processed as part of JVM launch. They are processed
early in the boot process, but this mechanism should not be used for setting properties that control JVM
behavior (e.g. java.net.perferIPv4Stack) or the behavior of the JBoss Modules classloading system.
The syntax for passing in parameters and properties files is the same regardless of whether you are running
the domain.sh, standalone.sh, or the Microsoft Windows scriptsdomain.bat or standalone.bat.
The properties file is a standard Java property file containing key=value pairs:
jboss.home.dir=/some/location/WildFly/jboss-as
jboss.domain.config.dir=/some/location/WildFly/custom-domain
System properties can also be set via the xml configuration files. Note however that for a standalone server
properties set this way will not be set until the xml configuration is parsed and the commands created by the
parser have been executed. So this mechanism should not be used for setting properties whose value needs
to be set before this point.
WildFly 9
Standalone
Property name
Usage
Default value
java.ext.dirs
null
jboss.home.dir
Set by standalone.sh to
installation.
$JBOSS_HOME
jboss.home.dir/standalone
jboss.server.base.dir
jboss.server.base.dir
/configuration
jboss.server.data.dir
jboss.server.log.dir
jboss.server.base.dir
file storage.
/data
jboss.server.base.dir/log
server.log file.
jboss.server.temp.dir
jboss.server.base.dir/tmp
storage.
jboss.server.deploy.dir The directory used to store deployed
content
jboss.server.data.dir
/content
WildFly 9
Managed Domain
Property name
Usage
Default value
jboss.home.dir
Set by domain.sh to
installation.
$JBOSS_HOME
jboss.home.dir/domain
jboss.domain.base.dir
content.
jboss.domain.config.dir
jboss.domain.base.dir
/configuration
jboss.domain.data.dir
jboss.domain.log.dir
jboss.domain.base.dir
file storage.
/data
jboss.domain.base.dir
host-controller.log and
/log
process-controller.log files
jboss.domain.temp.dir
jboss.domain.base.dir
storage
/tmp
jboss.domain.servers.dir
jboss.domain.base.dir
content
/content
jboss.domain.base.dir
/servers
--name=value
For example:
$JBOSS_HOME/bin/standalone.sh --server-config=standalone-ha.xml
If the parameter name is a single character, it is prefixed by a single '-' instead of two. Some parameters
have both a long and short option.
-x=value
For example:
WildFly 9
$JBOSS_HOME/bin/standalone.sh -P=/some/location/jboss.properties
For some command line arguments frequently used in previous major releases of WildFly, replacing the "="
in the above examples with a space is supported, for compatibility.
-b 192.168.100.10
If possible, use the -x=value syntax. New parameters will always support this syntax.
The sections below describe the command line parameter names that are available in standalone and
domain mode.
Standalone
Name
Default if
Value
absent
--admin-only
--server-config
-c
--read-only-server-config -
WildFly 9
Managed Domain
Name
Default if
Value
absent
-
--admin-only
--domain-config
-c
--host-config
host.xml
--read-only-host-config
The following parameters take no value and are only usable on slave host controllers (i.e. hosts configured
to connect to a remote domain controller.)
Name
Function
--backup
Causes the slave host controller to create and maintain a local copy of the domain
configuration file
--cached-dc If the slave host controller is unable to contact the master domain controller to get its
configuration at boot, boot from a local copy previously created using --backup. The
slave host controller will not be able make any modifications to the domain configuration,
but it will be able to launch servers.
WildFly 9
Common parameters
These parameters apply in both standalone or managed domain mode:
Name
Function
-b=<value>
--version
Prints the version of WildFly to standard output and exits the JVM.
-v
-V
--help
Prints a help message explaining the options and exits the JVM.
-h
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
WildFly 9
$JBOSS_HOME/bin/standalone.sh -b=192.168.100.10
In the standard config files, public interfaces are those not associated with server management. Public
interfaces handle normal end-user requests.
Interface names
The interface named "public" is not inherently special. It is provided as a convenience. You can
name your interfaces to suit your environment.
To bind the public interfaces to all IPv4 addresses (the IPv4 wildcard address), use the following syntax:
$JBOSS_HOME/bin/standalone.sh -b=0.0.0.0
$JBOSS_HOME/bin/standalone.sh -bmanagement=192.168.100.10
In the standard config files, management interfaces are those sockets associated with server management,
such as the socket used by the CLI, the HTTP socket used by the admin console, and the JMX connector
socket.
Be Careful
The -b switch only controls the interface bindings because the standard config files that ship with
WildFly sets things up that way. If you change the <interfaces> section in your configuration to
ignore the system properties controlled by -b, then setting -b in your launch command will have no
effect.
For example, this perfectly valid setting for the "public" interface causes -b to have no effect on
the "public" interface:
<interface name="public">
<nic name="eth0"/>
</interface>
The key point is the contents of the configuration files determine the configuration. Settings
like -b are not overrides of the configuration files. They only provide a shorter syntax for
setting a system properties that may or may not be referenced in the configuration files. They are
provided as a convenience, and you can choose to modify your configuration to ignore them.
WildFly 9
$JBOSS_HOME/bin/standalone.sh -u=230.0.1.2
Be Careful
As with the -b switch, the -u switch only controls the multicast address used because the standard
config files that ship with WildFly 8 sets things up that way. If you change the <socket-binding>
sections in your configuration to ignore the system properties controlled by -u, then setting -u in
your launch command will have no effect.
WildFly 9
The domain and host controller components manage the distribution of binaries across network boundaries.
Deployment Commands
Distributing deployment binaries involves two steps: uploading the deployment to the repository the domain
controller will use to distribute its contents, and then assigning the deployment to one or more server groups.
You can do this in one sweep with the CLI:
After you've uploaded the binary using the deploy command, it will be available to the domain controller,
and assigned to a server group:
[domain@localhost:9999 /] :read-children-names(child-type=deployment)
{
"outcome" => "success",
"result" => [
"mysql-connector-java-5.1.15.jar",
"test-application.war"
]
}
[domain@localhost:9999 /]
/server-group=main-server-group/deployment=test-application.war:read-resource
{
"outcome" => "success",
"result" => {
"enabled" => true,
"name" => "test-application.war",
"runtime-name" => "test-application.war"
}
}
You can remove binaries from server groups with the undeploy command:
WildFly 9
Managing deployments through the web interface provides an alternate, sometimes simpler
approach.
Content Repository
Deployments are referenced in the domain configuration file, and co-located with the domain controller:
[...]
<deployments>
<deployment name="test-application.war"
runtime-name="test-application.war">
<content sha1="dda9881fa7811b22f1424b4c5acccb13c71202bd"/>
</deployment>
</deployments>
[...]
<server-groups>
<server-group name="main-server-group" profile="default">
[...]
<deployments>
<deployment name="test-application.war" runtime-name="test-application.war"/>
</deployments>
</server-group>
</server-groups>
[...]
(See domain/configuration/domain.xml)
ls domain/content/
|---/47
|-----95cc29338b5049e238941231b36b3946952991
|---/dd
|-----a9881fa7811b22f1424b4c5acccb13c71202bd
Standalone Server
Deployments on a standalone server work in a similar way to those on managed domains. The main
difference is that there are no server group associations.
WildFly 9
Deployment Commands
The same CLI commands used for managed domains work for standalone servers when deploying and
removing an application:
Users are encouraged to use the WildFly 8 management APIs to upload and deploy deployment
content instead of relying on the deployment scanner that periodically scans the directory,
particularly if running production systems.
WildFly 9
Deployment Modes
The WildFly 8 filesystem deployment scanner operates in one of two different modes, depending on whether
it will directly monitor the deployment content in order to decide to deploy or redeploy it.
Auto-deploy mode:
The scanner will directly monitor the deployment content, automatically deploying new content and
redeploying content whose timestamp has changed. This is similiar to the behavior of previous AS releases,
although there are differences:
A change in any file in an exploded deployment triggers redeploy. Because EE 6 applications do not
require deployment descriptors,
there is no attempt to monitor deployment descriptors and only redeploy when a deployment
descriptor changes.
The scanner will place marker files in this directory as an indication of the status of its attempts to
deploy or undeploy content. These are detailed below.
Manual deploy mode:
The scanner will not attempt to directly monitor the deployment content and decide if or when the end user
wishes the content to be deployed. Instead, the scanner relies on a system of marker files, with the user's
addition or removal of a marker file serving as a sort of command telling the scanner to deploy, undeploy or
redeploy content.
Auto-deploy mode and manual deploy mode can be independently configured for zipped deployment content
and exploded deployment content. This is done via the "auto-deploy" attribute on the deployment-scanner
element in the standalone.xml configuration file:
By default, auto-deploy of zipped content is enabled, and auto-deploy of exploded content is disabled.
Manual deploy mode is strongly recommended for exploded content, as exploded content is inherently
vulnerable to the scanner trying to auto-deploy partially copied content.
Marker Files
The marker files always have the same name as the deployment content to which they relate, but with an
additional file suffix appended. For example, the marker file to indicate the example.war file should be
deployed is named example.war.dodeploy. Different marker file suffixes have different meanings.
The relevant marker file types are:
WildFly 9
File
Purpose
.dodeploy
.skipdeploy
.isdeploying
.deployed
.failed
.pending
Basic workflows:
All examples assume variable $JBOSS_HOME points to the root of the WildFly 8 distribution.
WildFly 9
A) Add new zipped content and deploy it:
1. cp target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
B) Add new unzipped content and deploy it:
1. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
C) Undeploy currently deployed content:
1. rm $JBOSS_HOME/standalone/deployments/example.war.deployed
D) Auto-deploy mode only: Undeploy currently deployed content:
1. rm $JBOSS_HOME/standalone/deployments/example.war
E) Replace currently deployed zipped content with a new version and deploy it:
1. cp target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
F) Manual mode only: Replace currently deployed unzipped content with a new version and deploy it:
1. rm $AS/standalone/deployments/example.war.deployed
2. wait for $JBOSS_HOME/standalone/deployments/example.war.undeployed file to appear
3. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
4. touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
G) Auto-deploy mode only: Replace currently deployed unzipped content with a new version and deploy it:
1. touch $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
2. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
3. rm $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
H) Manual mode only: Live replace portions of currently deployed unzipped content without redeploying:
1. cp -r target/example.war/foo.html $JBOSS_HOME/standalone/deployments/example.war
I) Auto-deploy mode only: Live replace portions of currently deployed unzipped content without redeploying:
1. touch $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
2. cp -r target/example.war/foo.html $JBOSS_HOME/standalone/deployments/example.war
J) Manual or auto-deploy mode: Redeploy currently deployed content (i.e. bounce it with no content change):
1. touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
K) Auto-deploy mode only: Redeploy currently deployed content (i.e. bounce it with no content change):
WildFly 9
1. touch $JBOSS_HOME/standalone/deployments/example.war
The above examples use Unix shell commands. Windows equivalents are:
cp src dest --> xcopy /y src dest
cp -r src dest --> xcopy /e /s /y src dest
rm afile --> del afile
touch afile --> echo>> afile
Note that the behavior of 'touch' and 'echo' are different but the differences are not relevant to the
usages in the examples above.
WildFly 9
[domain@localhost:9999 /] :read-children-names(child-type=host)
{
"outcome" => "success",
"result" => ["local"]
}
[domain@localhost:9999 /] /host=local:read-children-names(child-type=server-config)
{
"outcome" => "success",
"result" => [
"my-server",
"server-one",
"server-three"
]
}
Now that we know, that there are two servers configured on host "local", we can go ahead and check
their status:
[domain@localhost:9999 /]
/host=local/server-config=server-one:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"auto-start" => true,
"group" => "main-server-group",
"interface" => undefined,
"name" => "server-one",
"path" => undefined,
"socket-binding-group" => undefined,
"socket-binding-port-offset" => undefined,
"status" => "STARTED",
"system-property" => undefined,
"jvm" => {"default" => undefined}
}
}
You can change the server state through the "start" and "stop" operations
WildFly 9
[domain@localhost:9999 /] /host=local/server-config=server-one:stop
{
"outcome" => "success",
"result" => "STOPPING"
}
Navigating through the domain topology is much more simple when you use the web interface.
Managed Domain
In a managed domain the JVM settings can be declared at different scopes: For a specific server group, for
a host or for a particular server. If not declared, the settings are inherited from the parent scope. This allows
you to customize or extend the JVM settings within every layer.
Let's take a look at the JVM declaration for a server group:
<server-groups>
<server-group name="main-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
<server-group name="other-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
</server-groups>
(See
domain/configuration/domain.xml)
In this example the server group "main-server-group" declares a heap size of 64m and a maximum heap size
of 512m. Any server that belongs to this group will inherit these settings. You can change these settings for
the group as a whole, or a specific server or host:
WildFly 9
<servers>
<server name="server-one" group="main-server-group" auto-start="true">
<jvm name="default"/>
</server>
<server name="server-two" group="main-server-group" auto-start="true">
<jvm name="default">
<heap size="64m" max-size="256m"/>
</jvm>
<socket-binding-group ref="standard-sockets" port-offset="150"/>
</server>
<server name="server-three" group="other-server-group" auto-start="false">
<socket-binding-group ref="standard-sockets" port-offset="250"/>
</server>
</servers>
(See domain/configuration/host.xml)
In this case, server-two, belongs to the main-server-group and inherits the JVM settings named default, but
declares a lower maximum heap size.
[domain@localhost:9999 /] /host=local/server-config=server-two/jvm=default:read-resource
{
"outcome" => "success",
"result" => {
"heap-size" => "64m",
"max-heap-size" => "256m",
}
}
Standalone Server
For a standalone sever you have to pass in the JVM settings either as command line arguments when
executing the $JBOSS_HOME/bin/standalone.sh script, or by declaring them in
$JBOSS_HOME/bin/standalone.conf. (For Windows users, the script to execute is
%JBOSS_HOME%/bin/standalone.bat while the JVM settings can be declared in
%JBOSS_HOME%/bin/standalone.conf.bat.)
WildFly 9
<management>
<security-realms>
...
</security-realms>
<audit-log>
<formatters>
<json-formatter name="json-formatter"/>
</formatters>
<handlers>
<file-handler name="file" formatter="json-formatter" path="audit-log.log"
relative-to="jboss.server.data.dir"/>
</handlers>
<logger log-boot="true" log-read-only="true" enabled="false">
<handlers>
<handler name="file"/>
</handlers>
</logger>
</audit-log>
...
[standalone@localhost:9990 /]
/core-service=management/access=audit:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"file-handler" => {"file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.server.data.dir"
}},
"json-formatter" => {"json-formatter" => {
"compact" => false,
"date-format" => "yyyy-MM-dd HH:mm:ss",
"date-separator" => " - ",
"escape-control-characters" => false,
"escape-new-line" => false,
"include-date" => true
}},
"logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"file" => {}}
}},
"syslog-handler" => undefined
}
}
WildFly 9
The audit logging subsystem has a lot of internal dependencies, and it logs operations changing,
enabling and disabling its components. When configuring or changing things at runtime it is a good
idea to make these changes as part of a CLI batch. For example if you are adding a syslog handler
you need to add the handler and its information as one step. Similarly if you are using a file
handler, and want to change its path and relative-to attributes, that needs to happen as one
step.
JSON Formatter
The first thing that needs configuring is the formatter, we currently support outputting log records as JSON.
You can define several formatters, for use with different handlers. A log record has the following format, and
it is the formatter's job to format the data presented:
2013-08-12 11:01:12 - {
"type" : "core",
"r/o" : false,
"booting" : false,
"version" : "8.0.0.Alpha4",
"user" : "$local",
"domainUUID" : null,
"access" : "NATIVE",
"remote-address" : "127.0.0.1/127.0.0.1",
"success" : true,
"ops" : [JMX|WFLY8:JMX subsystem configuration],
"operation" : "write-attribute",
"name" : "enabled",
"value" : true,
"operation-headers" : {"caller-type" : "user"}
}]
}
It includes an optional timestamp and then the following information in the json record
WildFly 9
Field name
Description
type
This can have the values core, meaning it is a management operation, or jmx
meaning it comes from the jmx subsystem (see the jmx subsystem for configuration of
the jmx subsystem's audit logging)
r/o
true if the operation does not change the management model, false otherwise
booting
true if the operation was executed during the bootup process, false if it was
executed once the server is up and running
version
user
The username of the authenticated user. In this case the operation has been logged
via the CLI on the same machine as the running server, so the special $local user
is used
domainUUID
An ID to link together all operations as they are propagated from the Doman
Controller to it servers, slave Host Controllers, and slave Host Controller servers
access
ops
The operations being executed. This is a list of the operations serialized to JSON. At
boot this will be all the operations resulting from parsing the xml. Once booted the list
will typically just contain a single entry
WildFly 9
Attribute
Description
include-date
date-separator
A string containing characters to separate the date and the rest of the
formatted log message. Will be ignored if include-date=false
date-format
compact
If true will format the JSON on one line. There may still be values
containing new lines, so if having the whole record on one line is
important, set escape-new-line or escape-control-characters to true
escape-control-characters If true it will escape all control characters (ascii entries with a decimal
value < 32) with the ascii code in octal, e.g. a new line becomes '#012'.
If this is true, it will override escape-new-line=false
escape-new-line
If true it will escape all new lines with the ascii code in octal, e.g.
"#012".
Handlers
A handler is responsible for taking the formatted data and logging it to a location. There are currently two
types of handlers, File and Syslog. You can configure several of each type of handler and use them to log
information.
WildFly 9
File handler
The file handlers log the audit log records to a file on the server. The attributes for the file handler are
Attribute
Description
Read
Only
formatter
false
path
false
relative-to
false
true
max-failure-count
false
handler
disabled-due-to-failure true if this handler was disabled due to logging failures
true
Syslog handler
The default configuration does not have syslog audit logging set up. Syslog is a better choice for audit
logging since you can log to a remote syslog server, and secure the authentication to happen over TLS with
client certificate authentication. Syslog servers vary a lot in their capabilities so not all settings in this section
apply to all syslog servers. We have tested with rsyslog.
The address for the syslog handler is
/core-service=management/access=audit/syslog-handler=* and just like file handlers you can
add as many syslog entries as you like. The syslog handler resources reference the main RFC's for syslog a
fair bit, for reference they can be found at:
*http://www.ietf.org/rfc/rfc3164.txt
*http://www.ietf.org/rfc/rfc5424.txt
*http://www.ietf.org/rfc/rfc6587.txt
The syslog handler resource has the following attributes:
WildFly 9
formatter
false
failure-count
true
max-failure-count
false
handler
disabled-due-to-failure true if this handler was disabled due to logging failures
syslog-format
true
false
RFC-5424 or RFC-3164
max-length
false
truncate
UDP
Configures the handler to use UDP to communicate with the syslog server. The address of the UDP resource
is /core-service=management/access=audit/syslog-handler=*/protocol=udp. The attributes
of the UDP resource are:
Attribute Description
host
port
The port of the syslog server listening for the udp requests
WildFly 9
TCP
Configures the handler to use TCP to communicate with the syslog server. The address of the TCP resource
is /core-service=management/access=audit/syslog-handler=*/protocol=tcp. The attributes
of the TCP resource are:
Attribute
Description
host
port
The port of the syslog server listening for the tcp requests
message-transfer The message transfer setting as described in section 3.4 of RFC-6587. This can
either be OCTET_COUNTING as described in section 3.4.1 of RFC-6587, or
NON_TRANSPARENT_FRAMING as described in section 3.4.1 of RFC-6587
TLS
Configures the handler to use TLC to communicate securely with the syslog server. The address of the TLS
resource is /core-service=management/access=audit/syslog-handler=*/protocol=tls. The
attributes of the TLS resource are the same as for TCP:
Attribute
Description
host
port
The port of the syslog server listening for the tls requests
message-transfer The message transfer setting as described in section 3.4 of RFC-6587. This can
either be OCTET_COUNTING as described in section 3.4.1 of RFC-6587, or
NON_TRANSPARENT_FRAMING as described in section 3.4.1 of RFC-6587
If the syslog server's TLS certificate is not signed by a certificate signing authority, you will need to set up a
truststore to trust the certificate. The resource for the trust store is a child of the TLS resource, and the full
address is
/core-service=management/access=audit/syslog-handler=*/protocol=tls/authentication=trustst
. The attributes of the truststore resource are:
Attribute
Description
keystore-password
keystore-path
keystore-relative-to The name of another previously named path, or of one of the standard paths
provided by the system. If keystore-relative-to is provided, the value
of the keystore-path attribute is treated as relative to the path specified by
this attribute
WildFly 9
TLS with Client certificate authentication.
If you have set up the syslog server to require client certificate authentication, when creating your handler
you will also need to set up a client certificate store containing the certificate to be presented to the syslog
server. The address of the client certificate store resource is
Description
keystore-password
key-password
keystore-path
keystore-relative-to The name of another previously named path, or of one of the standard paths
provided by the system. If keystore-relative-to is provided, the value
of the keystore-path attribute is treated as relative to the path specified by
this attribute
Logger configuration
The final part that needs configuring is the logger for the management operations. This references one or
more handlers and is configured at /core-service=management/access=audit/logger=audit-log
. The attributes for this resource are:
Attribute
Description
enabled
log-boot
true to log the management operations when booting the server, false otherwise
log-read-only If true all operations will be audit logged, if false only operations that change the
model will be logged
Then which handlers are used to log the management operations are configured as handler=* children of
the logger.
WildFly 9
[domain@localhost:9990 /]
/host=master/core-service=management/access=audit:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"file-handler" => {
"host-file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.domain.data.dir"
},
"server-file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.server.data.dir"
}
},
"json-formatter" => {"json-formatter" => {
"compact" => false,
"date-format" => "yyyy-MM-dd HH:mm:ss",
"date-separator" => " - ",
"escape-control-characters" => false,
"escape-new-line" => false,
"include-date" => true
}},
"logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"host-file" => {}}
}},
"server-logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"server-file" => {}}
}},
"syslog-handler" => undefined
}
}
We now have two file handlers, one called host-file used to configure the file to log management
operations on the host, and one called server-file used to log management operations executed on the
servers. Then logger=audit-log is used to configure the logger for the host controller, referencing the
host-file handler. server-logger=audit-log is used to configure the logger for the managed
servers, referencing the server-file handler. The attributes for server-logger=audit-log are the
same as for server-logger=audit-log in the previous section. Having the host controller and server
loggers configured independently means we can control audit logging for managed servers and the host
controller independently.
WildFly 9
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:cancel-non-progressing-operation
{
"outcome" => "success",
"result" => "-1155777943"
}
The result value is an internal identification number for the operation that was cancelled.
On a managed domain host controller, the equivalent resource is in the host=<hostname> portion of the
management resource tree:
[domain@localhost:9990 /]
/host=host-a/core-service=management/service=management-operations:cancel-non-progressing-operation{
"outcome" => "success",
"result" => "2156877946"
}
[domain@localhost:9990 /]
/host=host-a/server=server-one/core-service=management/service=management-operations:cancel-non-progressing-op
"outcome" => "success",
"result" => "6497786512"
}
An operation is considered to be not proceeding normally if it has been executing with the exclusive
operation lock held for longer than 15 seconds. Read-only operations do not acquire the exclusive operation
lock, so this operation will not cancel read-only operations. Operations blocking waiting for another operation
to release the exclusive lock will also not be cancelled.
If there isn't any operation that is failing to proceed normally, there will be a failure response:
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:cancel-non-progressing-operation
{
"outcome" => "failed",
"failure-description" => "WFLYDM0089: No operation was found that has been holding the
operation execution write lock for long than [15] seconds",
"rolled-back" => true
}
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:find-non-progressing-operation
{
"outcome" => "success",
"result" => "-1155777943"
}
If there is no non-progressing operation, the outcome will still be success but the result will be undefined.
Once the id of the operation is known, the management resource for the operation can be examined to learn
more about its status.
[standalone@localhost:9990 /]
/core-service=management/service=management-operations/active-operation=-1155777943:read-resource(include-runt
"outcome" => "success",
"result" => {
"access-mechanism" => "undefined",
"address" => [
("deployment" => "example")
],
"caller-thread" => "management-handler-thread - 24",
"cancelled" => false,
"exclusive-running-time" => 101918273645L,
"execution-status" => "awaiting-stability",
"operation" => "deploy",
"running-time" => 101918279999L
}
}
WildFly 9
Field
Meaning
access-mechanism
The mechanism used to submit a request to the server. NATIVE, JMX, HTTP
address
The address of the resource targeted by the operation. The value in the final
element of the address will be '<hidden>' if the caller is not authorized to address
the operation's target resource.
caller-thread
cancelled
exclusive-running-time Amount of time in nanoseconds the operation has been executing with the
exclusive operation execution lock held, or -1 if the operation does not hold the
exclusive execution lock.
execution-status
operation
The name of the operation, or '<hidden>' if the caller is not authorized to address
the operation's target resource.
running-time
Meaning
executing
awaiting-other-operation The caller thread is blocking waiting for another operation to release the
exclusive execution lock
awaiting-stability
The caller thread has made changes to the service container and is waiting for
the service container to stabilize
completing
rolling-back
All currently executing operations can be viewed in one request using the read-children-resources
operation:
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:read-children-resources(child-type=active-operation){
"outcome" => "success",
"result" => {"-1155777943" => {
"access-mechanism" => "undefined",
"address" => [
("deployment" => "example")
],
"caller-thread" => "management-handler-thread - 24",
"cancelled" => false,
"exclusive-running-time" => 101918273645L,
"execution-status" => "awaiting-stability",
"operation" => "deploy",
"running-time" => 101918279999L
},
{"-1246693202" => {
"access-mechanism" => "undefined",
"address" => [
("core-service" => "management"),
("service" => "management-operations")
],
"caller-thread" => "management-handler-thread - 30",
"cancelled" => false,
"exclusive-running-time" => -1L,
"execution-status" => "executing",
"operation" => "read-children-resources",
"running-time" => 3356000L
}}
}
[standalone@localhost:9990 /]
/core-service=management/service=management-operations/active-operation=-1155777943:cancel
{
"outcome" => "success",
"result" => undefined
}
WildFly 9
Note the blocking timeout is not a guaranteed maximum execution time for an operation. If it only a timeout
that will be enforced at various points during operation execution.
WildFly 9
Within standalone_xml_history itself following a successful first time boot we end up with three new
files:
*standalone.initial.xml - This contains the original configuration that was used the first time we
successfully booted. This file will never be overwritten. You may of course delete the history directory and
any files in it at any stage.
*standalone.boot.xml - This contains the original configuration that was used for the last successful
boot of the server. This gets overwritten every time we boot the server successfully.
*standalone.last.xml - At this stage the contents will be identical to standalone.boot.xml.
This
file gets overwritten each time the server successfully writes the
configuration, if there was an unexpected failure writing the configuration this
file is the last known successful write.
standalone_xml_history contains a directory called current which should be empty. Now if we
execute a management operation that modifies the model, for example adding a new system property using
the CLI:
[standalone@localhost:9999 /] /system-property=test:add(value="test123")
{"outcome" => "success"}
Snapshots
In addition to the backups taken by the server as described above you can manually take take snapshots
which will be stored in the snapshot folder under the _xml_history folder, the automatic backups
described above are subject to automatic house keeping so will eventually be automatically removed, the
snapshots on the other hand can be entirely managed by the administrator.
You may also take your own snapshots using the CLI:
[standalone@localhost:9999 /] :take-snapshot
{
"outcome" => "success",
"result" => {"name" =>
"/Users/kabir/jboss-7.0.0.CR1/standalone/configuration/standalone_xml_history/snapshot/20110630-172258657stand
WildFly 9
You can also use the CLI to list all the snapshots
[standalone@localhost:9999 /] :list-snapshots
{
"outcome" => "success",
"result" => {
"directory" =>
"/Users/kabir/jboss-7.0.0.CR1/standalone/configuration/standalone_xml_history/snapshot",
"names" => [
"20110630-165714239standalone.xml",
"20110630-165821795standalone.xml",
"20110630-170113581standalone.xml",
"20110630-171411463standalone.xml",
"20110630-171908397standalone.xml",
"20110630-172258657standalone.xml"
]
}
}
[standalone@localhost:9999 /] :delete-snapshot(name="20110630-165714239standalone.xml")
{"outcome" => "success"}
[standalone@localhost:9999 /] :delete-snapshot(name="all")
{"outcome" => "success"}
In domain mode executing the snapshot operations against the root node will work against the domain
model. To do this for a host model you need to navigate to the host in question:
[domain@localhost:9999 /] /host=master:list-snapshots
{
"outcome" => "success",
"result" => {
"domain-results" => {"step-1" => {
"directory" =>
"/Users/kabir/jboss-7.0.0.CR1/domain/configuration/host_xml_history/snapshot",
"names" => [
"20110630-141129571host.xml",
"20110630-172522225host.xml"
]
}},
"server-operations" => undefined
}
}
WildFly 9
Subsequent Starts
For subsequent server starts it may be desirable to take the state of the server back to one of the previously
known states, for a number of items an abbreviated reverence to the file can be used: Abreviation Parameter
initial
Description
--server-config=initial This will start the server using the initial configuration first
used to start the server.
boot
--server-config=boot
This will use the configuration from the last successful boot
of the server.
last
--server-config=last
v?
--server-config=v?
???? -
--server-config=???? -
?????
?????
In addition to this the --server-config parameter can always be used to specify a configuration relative
to the jboss.server.config.dir and finally if no matching configuration is found an attempt to locate
the configuration as an absolute path will be made.
WildFly 9
WildFly 9
WildFly 9
WildFly 9
Standard Operations
Besides the global operations described above, by convention nearly every resource should expose an add
operation and a remove operation. Exceptions to this convention are the root resource, and resources that
do not store persistent configuration and are created dynamically at runtime (e.g. resources representing the
JVM's platform mbeans or resources representing aspects of the running state of a deployment.)
WildFly 9
The source code for jboss-dmr is available on Github. The maven coordinates for a jboss-dmr release are
org.jboss.jboss-dmr:jboss-dmr.
Next, create a ModelNode and use the beanshell print function to output what type it is:
bsh % node.set(1);
bsh % print(node.getType());
INT
bsh % node.set(true);
bsh % print(node.getType());
BOOLEAN
bsh % node.set("Hello, world");
bsh % print(node.getType());
STRING
WildFly 9
bsh % node.set(2);
bsh % print(node.asInt());
2
bsh % node.set("A string");
bsh % print(node.asString());
A string
ModelNode will attempt to perform type conversions when you invoke the asXXX methods:
bsh %
bsh %
1
bsh %
true
bsh %
bsh %
false
bsh %
bsh %
true
node.set(1);
print(node.asString());
print(node.asBoolean());
node.set(0);
print(node.asBoolean());
node.set("true");
print(node.asBoolean());
The ModelNode.getType() method can be used to ensure a node has an expected value type before
attempting a type conversion.
One set variant takes another ModelNode as its argument. The value of the passed in node is copied, so
there is no shared state between the two model nodes:
WildFly 9
A ModelNode can be cloned. Again, there is no shared state between the original node and its clone:
bsh % clone.protect();
bsh % clone.set("A different string");
// Error: // Uncaught Exception: Method Invocation clone.set : at Line: 15 : in file: <unknown
file> : clone .set ( "A different string" )
Target exception: java.lang.UnsupportedOperationException
java.lang.UnsupportedOperationException
at org.jboss.dmr.ModelNode.checkProtect(ModelNode.java:1441)
at org.jboss.dmr.ModelNode.set(ModelNode.java:351)
....
Lists
The above examples aren't particularly interesting; if all we can do with a ModelNode is wrap a simple Java
primitive, what use is that? However, a ModelNode's value can be more complex than a simple primitive,
and using these more complex types we can build complex data structures. The first more complex type is
ModelType.LIST.
Use the add methods to initialize a node's value as a list and add to the list:
WildFly 9
bsh %
bsh %
bsh %
bsh %
LIST
bsh % print(list.asInt());
2
Use the overloaded get method variant that takes an int param to retrieve an item. The item is returned as a
ModelNode:
Here's one of the trickiest things about jboss-dmr: The get methods actually mutate state; they are not
"read-only". For example, calling get with an index that does not exist yet in the list will actually create a
child of type ModelType.UNDEFINED at that index (and will create UNDEFINED children for any
intervening indices.)
Since the get call always returns a ModelNode and never null it is safe to manipulate the return value:
bsh % list.get(5).set(30);
bsh % print(list.get(5).asInt());
30
That's not so interesting in the above example, but later on with node of type ModelType.OBJECT we'll see
how that kind of method chaining can let you build up fairly complex data structures with a minimum of code.
WildFly 9
Use the asList() method to get a List<ModelNode> of the children:
The asString() and toString() methods provide slightly differently formatted text representations of a
ModelType.LIST node:
bsh % print(list.asString());
[5,10,"A string",undefined,undefined,30]
bsh % print(list.toString());
[
5,
10,
"A string",
undefined,
undefined,
30
]
Finally, if you've previously used set to assign a node's value to some non-list type, you cannot use the add
method:
bsh % node.add(5);
// Error: // Uncaught Exception: Method Invocation node.add : at Line: 18 : in file: <unknown
file> : node .add ( 5 )
Target exception: java.lang.IllegalArgumentException
java.lang.IllegalArgumentException
at org.jboss.dmr.ModelValue.addChild(ModelValue.java:120)
at org.jboss.dmr.ModelNode.add(ModelNode.java:1007)
at org.jboss.dmr.ModelNode.add(ModelNode.java:761)
...
You can, however, use the setEmptyList() method to change the node's type, and then use add:
bsh % node.setEmptyList();
bsh % node.add(5);
bsh % print(node.toString());
[5]
WildFly 9
Properties
The third public class in the jboss-dmr library is org.jboss.dmr.Property. A Property is a String =>
ModelNode tuple.
bsh % node.set(prop);
bsh % print(node.getType());
PROPERTY
bsh % print(node.toString());
("stuff" => [
5,
10,
"A string",
undefined,
undefined,
30
])
Directly instantiating a Property via its constructor is not common. More typically one of the two argument
ModelNode.add or ModelNode.set variants is used. The first argument is the property name:
WildFly 9
ModelType.OBJECT
The most powerful and most commonly used complex value type in jboss-dmr is ModelType.OBJECT. A
ModelNode whose value is ModelType.OBJECT internally maintains a Map<String, ModelNode.
Use the get method variant that takes a string argument to add an entry to the map. If no entry exists under
the given name, a new entry is added with a the value being a ModelType.UNDEFINED node. The node is
returned:
Again it is important to remember that the get operation may mutate the state of a model node by
adding a new entry. It is not a read-only operation.
Since get will never return null, a common pattern is to use method chaining to create the key/value pair:
WildFly 9
bsh % range.get("max").set(10);
bsh % print(range.toString());
{
"min" => 2,
"max" => 10
}
A call to get passing an already existing key will of course return the same model node as was returned the
first time get was called with that key:
Multiple parameters can be passed to get. This is a simple way to traverse a tree made up of
ModelType.OBJECT nodes. Again, get may mutate the node on which it is invoked; e.g. it will actually
create the tree if nodes do not exist. This next example uses a workaround to get beanshell to handle the
overloaded get method that takes a variable number of arguments:
bsh %
bsh %
bsh %
{"US"
The semantics of the backing map in a node of ModelType.OBJECT are those of a LinkedHashMap. The
map remembers the order in which key/value pairs are added. This is relevant when iterating over the pairs
after calling asPropertyList() and for controlling the order in which key/value pairs appear in the output
from toString().
Since the get method will actually mutate the state of a node if the given key does not exist, ModelNode
provides a couple methods to let you check whether the entry is there. The has method simply does that:
WildFly 9
bsh % print(range.has("unit"));
false
bsh % print(range.has("min"));
true
Very often, the need is to not only know whether the key/value pair exists, but whether the value is defined
(i.e. not ModelType.UNDEFINED. This kind of check is analogous to checking whether a field in a Java
class has a null value. The hasDefined lets you do this:
bsh % print(range.hasDefined("unit"));
false
bsh % // Establish an undefined child 'unit';
bsh % range.get("unit");
bsh % print(range.toString());
{
"min" => 2,
"max" => 10,
"unit" => undefined
}
bsh % print(range.hasDefined("unit"));
false
bsh % range.get("unit").set("meters");
bsh % print(range.hasDefined("unit"));
true
ModelType.EXPRESSION
A value of type ModelType.EXPRESSION is stored as a string, but can later be resolved to different value.
The string has a special syntax that should be familiar to those who have used the system property
substitution feature in previous JBoss AS releases.
[<prefix>][${<system-property-name>[:<default-value>]}][<suffix>]*
For example:
${queue.length}
http://${host}
http://${host:localhost}:${port:8080}/index.html
WildFly 9
bsh % print(expression.asString());
${queue.length}
However, calling toString() tells you that this node's value is not of ModelType.STRING:
bsh % print(expression.toString());
expression "${queue.length}"
When the resolve operation is called, the string is parsed and any embedded system properties are
resolved against the JVM's current system property values. A new ModelNode is returned whose value is
the resolved string:
bsh % print(resolved.getType());
STRING
The resolved.asInt() call in the previous example only worked because the string "10" happens to be
convertible into the int 10.
Calling resolve() has no effect on the value of the node on which the method is invoked:
If an expression cannot be resolved, resolve just uses the original string. The string can include more than
one system property substitution:
bsh % expression.setExpression("http://${host}:${port}/index.html");
bsh % resolved = expression.resolve();
bsh % print(resolved.asString());
http://${host}:${port}/index.html
The expression can optionally include a default value, separated from the name of the system property by a
colon:
WildFly 9
bsh % expression.setExpression("http://${host:localhost}:${port:8080}/index.html");
bsh % resolved = expression.resolve();
bsh % print(resolved.asString());
http://localhost:8080/index.html
The resolve method works on nodes of other types as well; it returns a copy without attempting any real
resolution:
bsh
bsh
bsh
bsh
INT
bsh
bsh
5
bsh
10
%
%
%
%
% resolved.set(5);
% print(resolved.asInt());
% print(basic.asInt());
ModelType.TYPE
You can also pass one of the values of the ModelType enum to set:
bsh %
bsh %
bsh %
TYPE
bsh %
LIST
This is useful when using a ModelNode data structure to describe another ModelNode data structure.
WildFly 9
WildFly 9
{
"description => "A manageable resource",
"tail-comment-allowed" => false,
"attributes" => {
"foo" => {
.... details of attribute foo
}
},
"operations" => {
"start" => {
.... details of the start operation
}
},
"children" => {
"bar" => {
.... details of the relationship with children of type "bar"
}
}
}
Description of an Attribute
An attribute is a portion of the management model that is not directly addressable. Instead, it is conceptually
a property of an addressable management resource. For each attribute in the model, the following
descriptive information will be available:
WildFly 9
description String text description of the attribute
type org.jboss.dmr.ModelType the type of the attribute value. One of the enum values
BIG_DECIMAL, BIG_INTEGER, BOOLEAN, BYTES, DOUBLE, INT, LIST, LONG, OBJECT,
PROPERTY, STRING. Most of these are self-explanatory. An OBJECT will be represented in the
detyped model as a map of string keys to values of some other legal type, conceptually similar to a
javax.management.openmbean.CompositeData. A PROPERTY is a single key/value pair,
where the key is a string, and the value is of some other legal type.
value-type ModelType or complex structure Only present if type is LIST or OBJECT. If all
elements in the LIST or all the values of the OBJECT type are of the same type, this will be one of the
ModelType enums BIG_DECIMAL, BIG_INTEGER, BOOLEAN, BYTES, DOUBLE, INT, LONG,
STRING. Otherwise, value-type will detail the structure of the attribute value, enumerating the
value's fields and the type of their value.
expressions-allowed boolean indicates whether the value of the attribute may be of type
ModelType.EXPRESSION, instead of its standard type (see type and value-type above for
discussion of an attribute's standard type.) A value of ModelType.EXPRESSION contains a
system-property substitution expression that the server will resolve against the server-side system
property map before using the value. For example, an attribute named max-threads may have an
expression value of ${example.pool.max-threads:10} instead of just 10. Default value if not
present is false.
required boolean true if the attribute will always exist in a representation of its portion of the
model; false if it may not (implying a null value.) If not present, true is the default.
storage String Either "configuration" or "runtime". If "configuration", the attribute's value is stored
as part of the persistent configuration (e.g. in domain.xml, host.xml or standalone.xml.) If "runtime" the
attribute's value is not stored in the persistent configuration; the value only exists as long as the
resource is running.
access-type String One of "read-only", "read-write" or "metric". Whether an attribute value can
be written, or can only read. A "metric" is a read-only attribute whose value is not stored in the
persistent configuration, and whose value may change due to activity on the server. If an attribute is
"read-write", the resource will expose an operation named "write-attribute" whose "name" parameter
will accept this attribute's name and whose "value" parameter will accept a valid value for this
attribute. That operation will be the standard means of updating this attribute's value.
restart-required String One of "no-services", "all-services", "resource-services" or "jvm".
Only relevant to attributes whose access-type is read-write. Indicates whether execution of a
write-attribute operation whose name parameter specifies this attribute requires a restart of services
(or an entire JVM) in order for the change to take effect in the runtime . See discussion of "Applying
Updates to Runtime Services" below. Default value is "no-services".
alternatives List of string Indicates an exclusive relationship between attributes. If this
attribute is defined, the other attributes listed in this descriptor's value should be undefined (even if
their required descriptor says true; i.e. the presence of this attribute satisfies the requirement.) Default
is undefined; i.e. this does not apply to most attributes.
WildFly 9
requires List of string Indicates that if this attribute has a value (other than undefined), the other
attributes listed in this descriptor's value must also have a value, even if their required descriptor says
false. This would typically be used in conjunction with alternatives. For example, attributes "a" and "b"
are required, but are alternatives to each other; "c" and "d" are optional. But "b" requires "c" and "d",
so if "b" is used, "c" and "d" must also be defined. Default is undefined; i.e. this does not apply to most
attributes.
head-comment-allowed boolean indicates whether the model can store an XML comment that
would be written in the persistent form of the model (e.g. domain.xml) before the start of the XML
element that represents this attribute. This item is optional, and if not present defaults to false. (This is
a different default from what is used for an entire management resource, since model attributes often
map to XML attributes, which don't allow comments.) (Note: storing XML comments in the in-memory
model is not currently supported. This description key is for future use.)
tail-comment-allowed boolean similar to head-comment-allowed, but indicates whether a
comment just before the close of the XML element is supported. A tail comment can only be
supported if the element has child elements, in which case a comment can be inserted between the
final child element and the element's closing tag. This item is optional, and if not present defaults to
false. (This is a different default from what is used for an entire management resource, since model
attributes often map to XML attributes, which don't allow comments.) (Note: storing XML comments in
the in-memory model is not currently supported. This description key is for future use.)
arbitrary key/value pairs that further describe the attribute value, e.g. "max" => 2. See "Arbitrary
Descriptors" below.
Some examples:
"foo" => {
"description" => "The foo",
"type" => INT,
"max" => 2
}
"bar" => {
"description" => "The bar",
"type" => OBJECT,
"value-type" => {
"size" => INT,
"color" => STRING
}
}
Description of an Operation
A management resource may have operations associated with it. The description of an operation will include
the following information:
WildFly 9
WildFly 9
Arbitrary Descriptors
The description of an attribute, operation parameter or operation return value type can include arbitrary
key/value pairs that provide extra information. Whether a particular key/value pair is present depends on the
context, e.g. a pair with key "max" would probably only occur as part of the description of some numeric
type.
WildFly 9
Following are standard keys and their expected value type. If descriptor authors want to add an arbitrary
key/value pair to some descriptor and the semantic matches the meaning of one of the following items, the
standard key/value type must be used.
min int the minimum value of some numeric type. The absence of this item implies there is no
minimum value.
max int the maximum value of some numeric type. The absence of this item implies there is no
maximum value.
min-length int the minimum length of some string, list or byte[] type. The absence of this item
implies a minimum length of zero.
max-length int the maximum length of some string, list or byte[]. The absence of this item
implies there is no maximum value.
nillable boolean whether null or a ModelNode of type ModelType.UNDEFINED is a legal
value. The absence of this item implies false; i.e. null/undefined is not a legal value.
allowed List a list of legal values. The type of the elements in the list should match the type of
the attribute.
default the default value for the attribute if not present in the model
unit - The unit of the value, if one is applicable - e.g. ns, ms, s, m, h, KB, MB, TB. See the
org.jboss.as.controller.client.helpers.MeasurementUnit in the
org.jboss.as:jboss-as-controller-client artifact for a listing of legal measurement units..
Some examples:
{
"operation-name" => "incrementFoo",
"description" => "Increase the value of the 'foo' attribute by the given amount",
"request-properties" => {
"increment" => {
"type" => INT,
"description" => "The amount to increment",
"required" => true
}},
"reply-properties" => {
"type" => INT,
"description" => "The new value",
}
}
{
"operation-name" => "start",
"description" => "Starts the thing",
"request-properties" => {},
"reply-properties" => {}
}
WildFly 9
{
....
"children" => {
"connector" => {
.... description of the relationship with children of type "connector"
},
"virtual-host" => {
.... description of the relationship with children of type "virtual-host"
}
}
WildFly 9
{
"description" => "The connectors used to handle client connections",
"min-occurs" > 1,
"model-description" => {
"description" => "Handles client connections",
"attributes => {
... details of children as documented above
},
"operations" => {
.... details of operations as documented above
},
"children" => {
.... details of the children's children
}
}
}
{
"description" => "The connectors used to handle client connections",
"min-occurs" > 1,
"model-description" => undefined
}
WildFly 9
Because restarting a service can be disruptive to end-user request handling, the handlers for management
operations will not restart any service without some form of explicit instruction from the end user indicating a
service restart is desired. In a few cases, simply executing the operation is an indication the user wants
services to restart (e.g. a /host=master/server-config=server-one:restart operation in a
managed domain, or a /:reload operation on a standalone server.) For all other cases, if an operation (or
attribute write) cannot be performed without restarting a service, the metadata describing the operation or
attribute will include a "restart-required" descriptor whose value indicates what is necessary for the
operation to affect the runtime:
no-services Applying the operation to the runtime does not require the restart of any services.
This value is the default if the restart-required descriptor is not present.
all-services The operation can only immediately update the persistent configuration; applying
the operation to the runtime will require a subsequent restart of all services in the affected VM.
Executing the operation will put the server into a "reload-required" state. Until a restart of all
services is performed the response to this operation and to any subsequent operation will include a
response header "process-state" => "reload-required". For a standalone server, a restart
of all services can be accomplished by executing the /:reload CLI command. For a server in a
managed domain, restarting all services currently requires a full restart of the affected server VM (e.g.
/host=master/server-config=server-one:restart).
jvm --The operation can only immediately update the persistent configuration; applying the operation
to the runtime will require a full process restart (i.e. stop the JVM and launch a new JVM). Executing
the operation will put the server into a "restart-required" state. Until a restart is performed the
response to this operation and to any subsequent operation will include a response header "
process-state" => "restart-required". For a standalone server, a full process restart
requires first stopping the server via OS-level operations (Ctrl-C, kill) or via the /:shutdown CLI
command, and then starting the server again from the command line. For a server in a managed
domain, restarting a server requires executing the
/host=<host>/server-config=<server>:restart operation.
resource-services The operation can only immediately update the persistent configuration;
applying the operation to the runtime will require a subsequent restart of some services associated
with the resource. If the operation includes the request header
"allow-resource-service-restart" => true, the handler for the operation will go ahead
and restart the runtime service. Otherwise executing the operation will put the server into a "
reload-required" state. (See the discussion of "all-services" above for more on the "
reload-required" state.)
WildFly 9
The CLI tool that comes with the application server uses this interface, and user can develop custom clients
that use it as well. In this section we'll cover the basics on how to develop such a client. We'll also cover
details on the format of low-level management operation requests and responses information that should
prove useful for users of the CLI tool as well.
Purpose
org.jboss.remoting:jboss-remoting
Remote communication
org.jboss:jboss-dmr
org.jboss.as:jboss-as-protocol
org.jboss.sasl:jboss-sasl
SASL authentication
org.jboss.xnio:xnio-api
Non-blocking IO
org.jboss.xnio:xnio-nio
Non-blocking IO
org.jboss.logging:jboss-logging
Logging
org.jboss.threads:jboss-threads
Thread management
WildFly 9
The custom client must have maven artifact org.jboss.as:jboss-as-controller-client and its
dependencies on the classpath.
ModelControllerClient client =
ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9999);
The address and port are what is configured in the target process'
<management><management-interfaces><native-interface.../> element.
Typically, however, the native management interface will be secured, requiring clients to authenticate. On
the client side, the custom client will need to provide the user's authentication credentials, obtained in
whatever manner is appropriate for the client (e.g. from a dialog box in a GUI-based client.) Access to these
credentials is provided by passing in an implementation of the
javax.security.auth.callback.CallbackHandler interface. For example:
WildFly 9
What we've done here is created a ModelNode of type ModelType.OBJECT with the following fields:
operation the name of the operation to invoke. All operation requests must include this field and
its value must be a String.
address the address of the resource to invoke the operation against. This field's must be of
ModelType.LIST with each element in the list being a ModelType.PROPERTY. If this field is
omitted the operation will target the root resource. The operation can be targeted at any address in
the management model; here we are targeting it at the resource for the web subsystem's http
connector.
In this case, the request includes two optional parameters:
recursive true means you want the description of child resources under this resource. Default is
false
operations true means you want the description of operations exposed by the resource to be
included. Default is false.
Different operations take different parameters, and some take no parameters at all.
See Format of a Detyped Operation Request for full details on the structure of a ModelNode that will
represent an operation request.
The example above produces an operation request ModelNode equivalent to what the CLI produces
internally when it parses and executes the following low-level CLI command:
[localhost:9999 /]
/subsystem=web/connector=http:read-resource-description(recursive=true,operations=true)
WildFly 9
See Format of a Detyped Operation Response for general details on the structure of the "returnVal"
ModelNode.
The execute operation shown above will block the calling thread until the response is received from the
process being managed. ModelControllerClient also exposes and API allowing asynchronous
invocation:
client.close();
where the return value is the detyped representation of the response, and operation is the detyped
representation of the operation being invoked.
The purpose of this section is to document the structure of operation.
See Format of a Detyped Operation Response for a discussion of the format of the response.
WildFly 9
Simple Operations
A text representation of simple operation would look like this:
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20
}
The order in which the outermost elements appear in the request is not relevant. The required elements are:
operation String The name of the operation being invoked.
address the address of the managed resource against which the request should be executed. If
not set, the address is the root resource. The address is an ordered list of key-value pairs describing
where the resource resides in the overall management resource tree. Management resources are
organized in a tree, so the order in which elements in the address occur is important.
The other key/value pairs are parameter names and their values. The names and values should match what
is specified in the operation's description.
Parameters may have any name, except for the reserved words operation, address and
operation-headers.
Operation Headers
Besides the special operation and address values discussed above, operation requests can also include
special "header" values that help control how the operation executes. These headers are created under the
special reserved word operation-headers:
WildFly 9
This produces:
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20,
"operation-headers" => {
"rollback-on-runtime-failure => false
}
}
WildFly 9
WildFly 9
Composite Operations
The root resource for a Domain or Host Controller or an individual server will expose an operation named "
composite". This operation executes a list of other operations as an atomic unit (although the atomicity
requirement can be relaxed. The structure of the request for the "composite" operation has the same
fundamental structure as a simple operation (i.e. operation name, address, params as key value pairs).
{
"operation" => "composite",
"address" => [],
"steps" => [
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"count" => "count",
"value" => 20
},
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool2")
],
"name" => "count",
"value" => 10
}
],
"operation-headers" => {
"rollback-on-runtime-failure => false
}
}
The rollback-on-runtime-failure operation header discussed above has a particular meaning when
applied to a composite operation, controlling whether steps that successfully execute should be reverted if
other steps fail at runtime. Note that if any steps modify the persistent configuration, and any of those steps
fail, all steps will be reverted. Partial/incomplete changes to the persistent configuration are not allowed.
WildFly 9
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20,
"operation-headers" => {
"rollout-plan" => {
"in-series" => [
{
"concurrent-groups" => {
"groupA" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
},
"groupB" => undefined
}
},
{
"server-group" => {
"groupC" => {
"rolling-to-servers" => false,
"max-failed-servers" => 1
}
}
},
{
"concurrent-groups" => {
"groupD" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
},
"groupE" => undefined
}
}
],
"rollback-across-groups" => true
}
}
}
WildFly 9
As you can see, the rollout plan is another structure in the operation-headers section. The root node of the
structure allows two children:
in-series a list A list of activities that are to be performed in series, with each activity reaching
completion before the next step is executed. Each activity involves the application of the operation to
the servers in one or more server groups. See below for details on each element in the list.
rollback-across-groups boolean indicates whether the need to rollback the operation on all
the servers in one server group should trigger a rollback across all the server groups. This is an
optional setting, and defaults to false.
Each element in the list under the in-series node must have one or the other of the following structures:
concurrent-groups a map of server group names to policies controlling how the operation
should be applied to that server group. For each server group in the map, the operation may be
applied concurrently. See below for details on the per-server-group policy configuration.
server-group a single key/value mapping of a server group name to a policy controlling how the
operation should be applied to that server group. See below for details on the policy configuration.
(Note: there is no difference in plan execution between this and a "concurrent-groups" map with a
single entry.)
The policy controlling how the operation is applied to the servers within a server group has the following
elements, each of which is optional:
rolling-to-servers boolean If true, the operation will be applied to each server in the group
in series. If false or not specified, the operation will be applied to the servers in the group
concurrently.
max-failed-servers int Maximum number of servers in the group that can fail to apply the
operation before it should be reverted on all servers in the group. The default value if not specified is
zero; i.e. failure on any server triggers rollback across the group.
max-failure-percentage int between 0 and 100 Maximum percentage of the total number of
servers in the group that can fail to apply the operation before it should be reverted on all servers in
the group. The default value if not specified is zero; i.e. failure on any server triggers rollback across
the group.
If both max-failed-servers and max-failure-percentage are set, max-failure-percentage
takes precedence.
Looking at the (contrived) example above, application of the operation to the servers in the domain would be
done in 3 phases. If the policy for any server group triggers a rollback of the operation across the server
group, all other server groups will be rolled back as well. The 3 phases are:
WildFly 9
1. Server groups groupA and groupB will have the operation applied concurrently. The operation will be
applied to the servers in groupA in series, while all servers in groupB will handle the operation
concurrently. If more than 20% of the servers in groupA fail to apply the operation, it will be rolled
back across that group. If any servers in groupB fail to apply the operation it will be rolled back across
that group.
2. Once all servers in groupA and groupB are complete, the operation will be applied to the servers in
groupC. Those servers will handle the operation concurrently. If more than one server in groupC fails
to apply the operation it will be rolled back across that group.
3. Once all servers in groupC are complete, server groups groupD and groupE will have the operation
applied concurrently. The operation will be applied to the servers in groupD in series, while all servers
in groupE will handle the operation concurrently. If more than 20% of the servers in groupD fail to
apply the operation, it will be rolled back across that group. If any servers in groupE fail to apply the
operation it will be rolled back across that group.
WildFly 9
This will create a rollout plan called simple in the content repository.
[domain@192.168.1.20:9999 /]
/management-client-content=rollout-plans/rollout-plan=simple:read-resource
{
"outcome" => "success",
"result" => {
"content" => {"rollout-plan" => {
"in-series" => [
{"server-group" => {"main-server-group" => {
"rolling-to-servers" => false,
"max-failed-servers" => 1
}}},
{"server-group" => {"other-server-group" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
}}}
],
"rollback-across-groups" => true
}},
"hash" => bytes {
0x13, 0x12, 0x76, 0x65, 0x8a, 0x28, 0xb8, 0xbc,
0x34, 0x3c, 0xe9, 0xe6, 0x9f, 0x24, 0x05, 0xd2,
0x30, 0xff, 0xa4, 0x34
}
}
}
Now you may reference the roolout plan in your command by adding a header just like this :
WildFly 9
where the return value is the detyped representation of the response, and operation is the detyped
representation of the operating being invoked.
The purpose of this section is to document the structure of the return value.
For the format of the request, see Format of a Detyped Operation Request.
Simple Responses
Simple responses are provided by the following types of operations:
Non-composite operations that target a single server. (See below for more on composite operations).
Non-composite operations that target a Domain Controller or slave Host Controller and don't require
the responder to apply the operation on multiple servers and aggregate their results (e.g. a simple
read of a domain configuration property.)
The response will always include a simple boolean outcome field, with one of three possible values:
success the operation executed successfully
failed the operation failed
cancelled the execution of the operation was cancelled. (This would be an unusual outcome for a
simple operation which would generally very rapidly reach a point in its execution where it couldn't be
cancelled.)
The other fields in the response will depend on whether the operation was successful.
The response for a failed operation:
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message"
}
{
"outcome" => "success",
"result" => {
"name" => "Brian",
"age" => 22
}
}
WildFly 9
A void result:
{
"outcome" => "success",
"result" => undefined
}
{
"outcome" => "cancelled"
}
WildFly 9
Response Headers
Besides the standard outcome, result and failure-description fields described above, the
response may also include various headers that provide more information about the affect of the operation or
about the overall state of the server. The headers will be child element under a field named
response-headers. For example:
{
"outcome" => "success",
"result" => undefined,
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}
A response header is typically related to whether an operation could be applied to the targeted runtime
without requiring a restart of some or all services, or even of the target process itself. Please see the
"Applying Updates to Runtime Services" section of the Description of the Management Model section for a
discussion of the basic concepts related to what happens if an operation requires a service restart to be
applied.
The current possible response headers are:
operation-requires-reload boolean indicates that the specific operation that has generated
this response requires a restart of all services in the process in order to take effect in the runtime. This
would typically only have a value of 'true'; the absence of the header is the same as a value of 'false.'
operation-requires-restart boolean indicates that the specific operation that has
generated this response requires a full process restart in order to take effect in the runtime. This
would typically only have a value of 'true'; the absence of the header is the same as a value of 'false.'
process-state enumeration Provides information about the overall state of the target process.
One of the following values:
starting the process is starting
running the process is in a normal running state. The process-state header would
typically not be seen with this value; the absence of the header is the same as a value of
'running'.
reload-required some operation (not necessarily this one) has executed that requires a
restart of all services in order for a configuration change to take effect in the runtime.
restart-required some operation (not necessarily this one) has executed that requires a
full process restart in order for a configuration change to take effect in the runtime.
stopping the process is stopping
WildFly 9
{
"outcome" => "cancelled"
}
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
}
An individual operation that itself succeeded but was rolled back due to failure of another operation:
WildFly 9
{
"outcome" => "failed",
"result" => {
"name" => "Brian",
"age" => 22
},
"rolled-back" => true
}
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
}
{
"outcome" => "success",
"result" => [
{
"outcome" => "success",
"result" => {
"name" => "Brian",
"age" => 22
}
},
{
"outcome" => "success",
"result" => undefined
}
]
}
And for a failed 3 step composite operation, where the first step succeeded and the second failed, triggering
cancellation of the 3rd and rollback of the others:
WildFly 9
{
"outcome" => "failed",
"failure-description" => "[JBAS-99999] Composite operation failed; see individual operation
results for details",
"result" => [
{
"outcome" => "failed",
"result" => {
"name" => "Brian",
"age" => 22
},
"rolled-back" => true
},
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
},
{
"outcome" => "cancelled"
}
]
}
Multi-Server Responses
Multi-server responses are provided by operations that target a Domain Controller or slave Host Controller
and require the responder to apply the operation on multiple servers and aggregate their results (e.g. nearly
all domain or host configuration updates.)
Multi-server operations are executed in several stages.
First, the operation may need to be applied against the authoritative configuration model maintained by the
Domain Controller (for domain.xml confgurations) or a Host Controller (for a host.xml configuration). If
there is a failure at this stage, the operation is automatically rolled back, with a response like this:
{
"outcome" => "failed",
"domain-failure-description" => "[JBAS-33333] Failed to apply X to the domain model"
}
If the operation was addressed to the domain model, in the next stage the Domain Controller will ask each
slave Host Controller to apply it to its local copy of the domain model. If any Host Controller fails to do so, the
Domain Controller will tell all Host Controllers to revert the change, and it will revert the change locally as
well. The response to the client will look like this:
WildFly 9
{
"outcome" => "failed",
"host-failure-descriptions" => {
"hostA" => "[DOM-3333] Failed to apply to the domain model",
"hostB" => "[DOM-3333] Failed to apply to the domain model"
}
}
If the preceding stages succeed, the operation will be pushed to all affected servers. If the operation is
successful on all servers, the response will look like this (this example operation has a void response, hence
the result for each server is undefined):
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
}
}
}
WildFly 9
The operation need not succeed on all servers in order to get an "outcome" => "success" result. All
that is required is that it succeed on at least one server without the rollback policies in the rollout plan
triggering a rollback on that server. An example response in such a situation would look like this:
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-3" => {
"host" => "host3",
"response" => {
"outcome" => "failed",
"failure-description" => "[DOM-4556] Something didn't work right",
"rolled-back" => true
}
}
}
}
}
Finally, if the operation fails or is rolled back on all servers, an example response would look like this:
WildFly 9
{
"outcome" => "failed",
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "failed",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "failed",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-3" => {
"host" => "host3",
"response" => {
"outcome" => "failed",
"failure-description" => "[DOM-4556] Something didn't work right",
"rolled-back" => true
}
}
}
}
}
WildFly 9
WildFly 9
5.10.1 Properties
Adding, reading and removing system property using CLI
For standalone mode:
For domain mode the same commands are used, you can add/read/remove system properties for:
All hosts and server instances in domain
[domain@IP_ADDRESS:9999 /] /system-property=foo:add(value=bar)
[domain@IP_ADDRESS:9999 /] /system-property=foo:read-resource
[domain@IP_ADDRESS:9999 /] /system-property=foo:remove
[domain@IP_ADDRESS:9999 /] /host=master/system-property=foo:add(value=bar)
[domain@IP_ADDRESS:9999 /] /host=master/system-property=foo:read-resource
[domain@IP_ADDRESS:9999 /] /host=master/system-property=foo:remove
[domain@IP_ADDRESS:9999 /]
/host=master/server-config=server-one/system-property=foo:add(value=bar)
[domain@IP_ADDRESS:9999 /]
/host=master/server-config=server-one/system-property=foo:read-resource
[domain@IP_ADDRESS:9999 /] /host=master/server-config=server-one/system-property=foo:remove
WildFly 9
[standalone@IP_ADDRESS:9999 /]
/core-service=platform-mbean/type=runtime:read-attribute(name=system-properties)
Domain
[domain@IP_ADDRESS:9999 /]
/host=master/core-service=platform-mbean/type=runtime:read-attribute(name=system-properties)
[domain@IP_ADDRESS:9999 /]
/host=master/server=server-one/core-service=platform-mbean/type=runtime:read-attribute(name=system-properties)
WildFly 9
5.10.2 Configuration
List Subsystems
[standalone@localhost:9999 /] /:read-children-names(child-type=subsystem)
{
"outcome" => "success",
"result" => [
"batch",
"datasources",
"deployment-scanner",
"ee",
"ejb3",
"infinispan",
"io",
"jaxrs",
"jca",
"jdr",
"jmx",
"jpa",
"jsf",
"logging",
"mail",
"naming",
"pojo",
"remoting",
"resource-adapters",
"sar",
"security",
"threads",
"transactions",
"undertow",
"webservices",
"weld"
]
}
WildFly 9
/subsystem=datasources/data-source=ExampleDS:read-resource-description
{
"outcome" => "success",
"result" => {
"description" => "A JDBC data-source configuration",
"head-comment-allowed" => true,
"tail-comment-allowed" => true,
"attributes" => {
"connection-url" => {
"type" => STRING,
"description" => "The JDBC driver connection URL",
"expressions-allowed" => true,
"nillable" => false,
"min-length" => 1L,
"max-length" => 2147483647L,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
"driver-class" => {
"type" => STRING,
"description" => "The fully qualified name of the JDBC driver class",
"expressions-allowed" => true,
"nillable" => true,
"min-length" => 1L,
"max-length" => 2147483647L,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
"datasource-class" => {
"type" => STRING,
"description" => "The fully qualified name of the JDBC datasource class",
"expressions-allowed" => true,
"nillable" => true,
"min-length" => 1L,
"max-length" => 2147483647L,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
"jndi-name" => {
"type" => STRING,
"description" => "Specifies the JNDI name for the datasource",
"expressions-allowed" => true,
"nillable" => false,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
...
WildFly 9
[domain@localhost:9999 /] /host=master:read-config-as-xml
[domain@localhost:9999 /] :read-config-as-xml
[domain@localhost:9999 /] /host=master:take-snapshot
{
"outcome" => "success",
"result" => {
"domain-results" => {"step-1" => {"name" =>
"JBOSS_HOME/domain/configuration/host_xml_history/snapshot/20110908-165640215host.xml"}},
"server-operations" => undefined
}
}
WildFly 9
./jboss-cli.sh --connect
Connected to standalone controller at localhost:9999
[standalone@localhost:9999 /] cd interface=public
[standalone@localhost:9999 interface=public] :read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"any" => undefined,
"any-address" => undefined,
"any-ipv4-address" => undefined,
"any-ipv6-address" => undefined,
"criteria" => [("inet-address" => expression "${jboss.bind.address:127.0.0.1}")],
"inet-address" => expression "${jboss.bind.address:127.0.0.1}",
"link-local-address" => undefined,
"loopback" => undefined,
"loopback-address" => undefined,
"multicast" => undefined,
"name" => "public",
"nic" => undefined,
"nic-match" => undefined,
"not" => undefined,
"point-to-point" => undefined,
"public-address" => undefined,
"resolved-address" => "127.0.0.1",
"site-local-address" => undefined,
"subnet-match" => undefined,
"up" => undefined,
"virtual" => undefined
}
}
[standalone@localhost:9999 interface=public] :read-attribute(name=resolved-address)
{
"outcome" => "success",
"result" => "127.0.0.1"
}
[domain@localhost:9999 /]
/host=master/server=server-one/interface=public:read-attribute(name=resolved-address)
{
"outcome" => "success",
"result" => "127.0.0.1"
}
WildFly 9
5.10.3 Runtime
Get all configuration and runtime details from CLI
./bin/jboss-cli.sh -c command=":read-resource(include-runtime=true, recursive=true,
recursive-depth=10)"
5.10.4 Scripting
Windows and "Press any key to continue ..." issue
WildFly 8 scripts for Windows end with "Press any key to continue ...". This behavior is useful when script is
executed by double clicking the script but not when you need to invoke several commands from custom
script (e.g. 'bin/jboss-admin.bat --connect command=:shutdown').
To avoid "Press any key to continue ..." message you need to specify NOPAUSE variable. Call 'set
NOPAUSE=true' in command line before running any WildFly 8 .bat script or include it in your custom script
before invoking scripts from WildFly 8.
5.10.5 Statistics
Read statistics of active datasources
/subsystem=datasources/data-source=ExampleDS/statistics=pool:read-resource(include-runtime=true)
/subsystem=datasources/data-source=ExampleDS/statistics=jdbc:read-resource(include-runtime=true)
or
/subsystem=datasources/data-source=ExampleDS:read-resource(include-runtime=true,recursive=true)
WildFly 9
WildFly 9
5.12.1 Properties
Adding, reading and removing system property using CLI
For standalone mode:
For domain mode the same commands are used, you can add/read/remove system properties for:
All hosts and server instances in domain
[domain@IP_ADDRESS:9999 /] /system-property=foo:add(value=bar)
[domain@IP_ADDRESS:9999 /] /system-property=foo:read-resource
[domain@IP_ADDRESS:9999 /] /system-property=foo:remove
[domain@IP_ADDRESS:9999 /] /host=master/system-property=foo:add(value=bar)
[domain@IP_ADDRESS:9999 /] /host=master/system-property=foo:read-resource
[domain@IP_ADDRESS:9999 /] /host=master/system-property=foo:remove
[domain@IP_ADDRESS:9999 /]
/host=master/server-config=server-one/system-property=foo:add(value=bar)
[domain@IP_ADDRESS:9999 /]
/host=master/server-config=server-one/system-property=foo:read-resource
[domain@IP_ADDRESS:9999 /] /host=master/server-config=server-one/system-property=foo:remove
WildFly 9
[standalone@IP_ADDRESS:9999 /]
/core-service=platform-mbean/type=runtime:read-attribute(name=system-properties)
Domain
[domain@IP_ADDRESS:9999 /]
/host=master/core-service=platform-mbean/type=runtime:read-attribute(name=system-properties)
[domain@IP_ADDRESS:9999 /]
/host=master/server=server-one/core-service=platform-mbean/type=runtime:read-attribute(name=system-properties)
WildFly 9
5.12.2 Configuration
List Subsystems
[standalone@localhost:9999 /] /:read-children-names(child-type=subsystem)
{
"outcome" => "success",
"result" => [
"batch",
"datasources",
"deployment-scanner",
"ee",
"ejb3",
"infinispan",
"io",
"jaxrs",
"jca",
"jdr",
"jmx",
"jpa",
"jsf",
"logging",
"mail",
"naming",
"pojo",
"remoting",
"resource-adapters",
"sar",
"security",
"threads",
"transactions",
"undertow",
"webservices",
"weld"
]
}
WildFly 9
/subsystem=datasources/data-source=ExampleDS:read-resource-description
{
"outcome" => "success",
"result" => {
"description" => "A JDBC data-source configuration",
"head-comment-allowed" => true,
"tail-comment-allowed" => true,
"attributes" => {
"connection-url" => {
"type" => STRING,
"description" => "The JDBC driver connection URL",
"expressions-allowed" => true,
"nillable" => false,
"min-length" => 1L,
"max-length" => 2147483647L,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
"driver-class" => {
"type" => STRING,
"description" => "The fully qualified name of the JDBC driver class",
"expressions-allowed" => true,
"nillable" => true,
"min-length" => 1L,
"max-length" => 2147483647L,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
"datasource-class" => {
"type" => STRING,
"description" => "The fully qualified name of the JDBC datasource class",
"expressions-allowed" => true,
"nillable" => true,
"min-length" => 1L,
"max-length" => 2147483647L,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
"jndi-name" => {
"type" => STRING,
"description" => "Specifies the JNDI name for the datasource",
"expressions-allowed" => true,
"nillable" => false,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
...
WildFly 9
[domain@localhost:9999 /] /host=master:read-config-as-xml
[domain@localhost:9999 /] :read-config-as-xml
[domain@localhost:9999 /] /host=master:take-snapshot
{
"outcome" => "success",
"result" => {
"domain-results" => {"step-1" => {"name" =>
"JBOSS_HOME/domain/configuration/host_xml_history/snapshot/20110908-165640215host.xml"}},
"server-operations" => undefined
}
}
WildFly 9
./jboss-cli.sh --connect
Connected to standalone controller at localhost:9999
[standalone@localhost:9999 /] cd interface=public
[standalone@localhost:9999 interface=public] :read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"any" => undefined,
"any-address" => undefined,
"any-ipv4-address" => undefined,
"any-ipv6-address" => undefined,
"criteria" => [("inet-address" => expression "${jboss.bind.address:127.0.0.1}")],
"inet-address" => expression "${jboss.bind.address:127.0.0.1}",
"link-local-address" => undefined,
"loopback" => undefined,
"loopback-address" => undefined,
"multicast" => undefined,
"name" => "public",
"nic" => undefined,
"nic-match" => undefined,
"not" => undefined,
"point-to-point" => undefined,
"public-address" => undefined,
"resolved-address" => "127.0.0.1",
"site-local-address" => undefined,
"subnet-match" => undefined,
"up" => undefined,
"virtual" => undefined
}
}
[standalone@localhost:9999 interface=public] :read-attribute(name=resolved-address)
{
"outcome" => "success",
"result" => "127.0.0.1"
}
[domain@localhost:9999 /]
/host=master/server=server-one/interface=public:read-attribute(name=resolved-address)
{
"outcome" => "success",
"result" => "127.0.0.1"
}
WildFly 9
5.12.3 Runtime
Get all configuration and runtime details from CLI
./bin/jboss-cli.sh -c command=":read-resource(include-runtime=true, recursive=true,
recursive-depth=10)"
5.12.4 Scripting
Windows and "Press any key to continue ..." issue
WildFly 8 scripts for Windows end with "Press any key to continue ...". This behavior is useful when script is
executed by double clicking the script but not when you need to invoke several commands from custom
script (e.g. 'bin/jboss-admin.bat --connect command=:shutdown').
To avoid "Press any key to continue ..." message you need to specify NOPAUSE variable. Call 'set
NOPAUSE=true' in command line before running any WildFly 8 .bat script or include it in your custom script
before invoking scripts from WildFly 8.
5.12.5 Statistics
Read statistics of active datasources
/subsystem=datasources/data-source=ExampleDS/statistics=pool:read-resource(include-runtime=true)
/subsystem=datasources/data-source=ExampleDS/statistics=jdbc:read-resource(include-runtime=true)
or
/subsystem=datasources/data-source=ExampleDS:read-resource(include-runtime=true,recursive=true)
WildFly 9
Standalone Server
For many use cases, the centralized management capability available via a managed domain is not
necessary. For these use cases, a WildFly 8 instance can be run as a "standalone server". A standalone
server instance is an independent process, much like an JBoss Application Server 3, 4, 5, or 6 instance is.
Standalone instances can be launched via the standalone.sh or standalone.bat launch scripts.
If more than one standalone instance is launched and multi-server management is desired, it is the user's
responsibility to coordinate management across the servers. For example, to deploy an application across all
of the standalone servers, the user would need to individually deploy the application on each server.
It is perfectly possible to launch multiple standalone server instances and have them form an HA cluster, just
like it was possible with JBoss Application Server 3, 4, 5 and 6.
Managed Domain
One of the primary new features of WildFly 8 is the ability to manage multiple WildFly instances from a single
control point. A collection of such servers is referred to as the members of a "domain" with a single Domain
Controller process acting as the central management control point. All of the WildFly 8 instances in the
domain share a common management policy, with the Domain Controller acting to ensure that each server
is configured according to that policy. Domains can span multiple physical (or virtual) machines, with all
WildFly 8 instances on a given host under the control of a special Host Controller process. One Host
Controller instance is configured to act as the central Domain Controller. The Host Controller on each host
interacts with the Domain Controller to control the lifecycle of the application server instances running on its
host and to assist the Domain Controller in managing them.
When you launch a WildFly 8 managed domain on a host (via the domain.sh or domain.bat launch
scripts) your intent is to launch a Host Controller and usually at least one WildFly instance. On one of the
hosts the Host Controller should be configured to act as the Domain Controller. See [WLFY8:Domain Setup]
for details.
The following is an example managed domain topology:
WildFly 9
Host
Each "Host" box in the above diagram represents a physical or virtual host. A physical host can contain zero,
one or more server instances.
WildFly 9
Host Controller
When the domain.sh or domain.bat script is run on a host, a process known as a Host Controller is
launched. The Host Controller is solely concerned with server management; it does not itself handle
application server workloads. The Host Controller is responsible for starting and stopping the individual
application server processes that run on its host, and interacts with the Domain Controller to help manage
them.
Each Host Controller by default reads its configuration from the domain/configuration/host.xml file
located in the unzipped WildFly 8 installation on its host's filesystem. The host.xml file contains
configuration information that is specific to the particular host. Primarily:
the listing of the names of the actual WildFly 8 instances that are meant to run off of this installation.
configuration of how the Host Controller is to contact the Domain Controller to register itself and
access the domain configuration. This may either be configuration of how to find and contact a remote
Domain Controller, or a configuration telling the Host Controller to itself act as the Domain Controller.
configuration of items that are specific to the local physical installation. For example, named interface
definitions declared in domain.xml (see below) can be mapped to an actual machine-specific IP
address in host.xml. Abstract path names in domain.xml can be mapped to actual filesystem
paths in host.xml.
Domain Controller
One Host Controller instance is configured to act as the central management point for the entire domain, i.e.
to be the Domain Controller. The primary responsibility of the Domain Controller is to maintain the domain's
central management policy, to ensure all Host Controllers are aware of its current contents, and to assist the
Host Controllers in ensuring any running application server instances are configured in accordance with this
policy. This central management policy is stored by default in the domain/configuration/domain.xml
file in the unzipped WildFly 8 installation on Domain Controller's host's filesystem.
A domain.xml file must be located in the domain/configuration directory of an installation that's
meant to run the Domain Controller. It does not need to be present in installations that are not meant to run a
Domain Controller; i.e. those whose Host Controller is configured to contact a remote Domain Controller.
The presence of a domain.xml file on such a server does no harm.
The domain.xml file includes, among other things, the configuration of the various "profiles" that WildFly 8
instances in the domain can be configured to run. A profile configuration includes the detailed configuration
of the various subsystems that comprise that profile (e.g. an embedded JBoss Web instance is a subsystem;
a JBoss TS transaction manager is a subsystem, etc). The domain configuration also includes the definition
of groups of sockets that those subsystems may open. The domain configuration also includes the definition
of "server groups":
WildFly 9
Server Group
A server group is set of server instances that will be managed and configured as one. In a managed domain
each application server instance is a member of a server group. (Even if the group only has a single server,
the server is still a member of a group.) It is the responsibility of the Domain Controller and the Host
Controllers to ensure that all servers in a server group have a consistent configuration. They should all be
configured with the same profile and they should have the same deployment content deployed.
The domain can have multiple server groups. The above diagram shows two server groups, "ServerGroupA"
and "ServerGroupB". Different server groups can be configured with different profiles and deployments; for
example in a domain with different tiers of servers providing different services. Different server groups can
also run the same profile and have the same deployments; for example to support rolling application
upgrade scenarios where a complete service outage is avoided by first upgrading the application on one
server group and then upgrading a second server group.
An example server group definition is as follows:
WildFly 9
Server
Each "Server" in the above diagram represents an actual application server instance. The server runs in a
separate JVM process from the Host Controller. The Host Controller is responsible for launching that
process. (In a managed domain the end user cannot directly launch a server process from the command
line.)
The Host Controller synthesizes the server's configuration by combining elements from the domain wide
configuration (from domain.xml ) and the host-specific configuration (from host.xml ).
WildFly 9
Extensions
An extension is a module that extends the core capabilities of the server. The WildFly 8 core is very simple
and lightweight; most of the capabilities people associate with an application server are provided via
extensions. An extension is packaged as a module in the modules folder. The user indicates that they want
a particular extension to be available by including an <extension/> element naming its module in the
domain.xml or standalone.xml file.
<extensions>
[...]
<extension
<extension
<extension
<extension
</extensions>
module="org.jboss.as.transactions"/>
module="org.jboss.as.web" />
module="org.jboss.as.webservices" />
module="org.jboss.as.weld" />
Paths
A logical name for a filesystem path. The domain.xml, host.xml and standalone.xml configurations
all include a section where paths can be declared. Other sections of the configuration can then reference
those paths by their logical name, rather than having to include the full details of the path (which may vary on
different machines). For example, the logging subsystem configuration includes a reference to the "
jboss.server.log.dir" path that points to the server's "log" directory.
WildFly 9
WildFly 8 automatically provides a number of standard paths without any need for the user to configure them
in a configuration file:
jboss.home - the root directory of the WildFly distribution
user.home - user's home directory
user.dir - user's current working directory
java.home - java installation directory
jboss.server.base.dir - root directory for an individual server instance
jboss.server.data.dir - directory the server will use for persistent data file storage
jboss.server.log.dir - directory the server will use for log file storage
jboss.server.tmp.dir - directory the server will use for temporary file storage
jboss.domain.servers.dir - directory under which a host controller will create the working area
for individual server instances (managed domain mode only)
Users can add their own paths or override all except the first 5 of the above by adding a <path/> element
to their configuration file.
<path name="x"/>
Such a configuration simply says, "There is a path named 'x' that other parts of the domain.xml
configuration can reference. The actual filesystem location pointed to by 'x' is host-specific and will be
specified in each machine's host.xml file." If this approach is used, there must be a path element in each
machine's host.xml that specifies what the actual filesystem path is:
A <path/> element in a standalone.xml must include the specification of the actual filesystem path.
WildFly 9
Interfaces
A logical name for a network interface/IP address/host name to which sockets can be bound. The
domain.xml, host.xml and standalone.xml configurations all include a section where interfaces can
be declared. Other sections of the configuration can then reference those interfaces by their logical name,
rather than having to include the full details of the interface (which may vary on different machines). An
interface configuration includes the logical name of the interface as well as information specifying the criteria
to use for resolving the actual physical address to use. See Interfaces and ports for further details.
An <interface/> element in a domain.xml need not include anything more than the name attribute; i.e. it
need not include any information indicating what the actual IP address associated with the name is:
<interface name="internal"/>
Such a configuration simply says, "There is an interface named 'internal' that other parts of the domain.xml
configuration can reference. The actual IP address pointed to by 'internal' is host-specific and will be
specified in each machine's host.xml file." If this approach is used, there must be an interface element in
each machine's host.xml that specifies the criteria for determining the IP address:
<interface name="internal">
<nic name="eth1"/>
</interface>
An <interface/> element in a standalone.xml must include the criteria for determining the IP address.
WildFly 9
System Properties
System property values can be set in a number of places in domain.xml, host.xml and
standalone.xml. The values in standalone.xml are set as part of the server boot process. Values in
domain.xml and host.xml are applied to servers when they are launched.
When a system property is configured in domain.xml or host.xml, the servers it ends up being applied to
depends on where it is set. Setting a system property in a child element directly under the domain.xml root
results in the property being set on all servers. Setting it in a <system-property/> element inside a
<server-group/> element in domain.xml results in the property being set on all servers in the group.
Setting it in a child element directly under the host.xml root results in the property being set on all servers
controlled by that host's Host Controller. Finally, setting it in a <system-property/> element inside a
<server/> element in host.xml result in the property being set on that server. The same property can be
configured in multiple locations, with a value in a <server/> element taking precedence over a value
specified directly under the host.xml root element, the value in a host.xml taking precedence over
anything from domain.xml, and a value in a <server-group/> element taking precedence over a value
specified directly under the domain.xml root element.
WildFly 9
Address
All WildFly management resources are organized in a tree. The path to the node in the tree for a particular
resource is its address. Each segment in a resource's address is a key/value pair:
The key is the resource's type, in the context of its parent. So, for example, the root resource for a
standalone server has children of type subsystem, interface, socket-binding, etc. The
resource for the subsystem that provides the AS's webserver capability has children of type
connector and virtual-server. The resource for the subsystem that provides the AS's
messaging server capability has, among others, children of type jms-queue and jms-topic.
The value is the name of a particular resource of the given type, e.g web or messaging for
subsystems or http or https for web subsystem connectors.
The full address for a resource is the ordered list of key/value pairs that lead from the root of the tree to the
resource. Typical notation is to separate the elements in the address with a '/' and to separate the key and
the value with an '=':
/subsystem=web/connector=http
/subsystem=messaging/jms-queue=testQueue
/interface=public
When using the HTTP API, a '/' is used to separate the key and the value instead of an '=':
http://localhost:9990/management/subsystem/web/connector/http
http://localhost:9990/management/subsystem/messaging/jms-queue/testQueue
http://localhost:9990/management/interface/public
Operations
Querying or modifying the state of a resource is done via an operation. An operation has the following
characteristics:
A string name
Zero or more named parameters. Each parameter has a string name, and a value of type
org.jboss.dmr.ModelNode (or, when invoked via the CLI, the text representation of a
ModelNode; when invoked via the HTTP API, the JSON representation of a ModelNode.)
Parameters may be optional.
A return value, which will be of type org.jboss.dmr.ModelNode (or, when invoked via the CLI, the
text representation of a ModelNode; when invoked via the HTTP API, the JSON representation of a
ModelNode.)
Every resource except the root resource will have an add operation and should have a remove operation
("should" because in WildFly 8 many do not). The parameters for the add operation vary depending on the
resource. The remove operation has no parameters.
WildFly 9
There are also a number of "global" operations that apply to all resources. See Global operations for full
details.
The operations a resource supports can themselves be determined by invoking an operation: the
read-operation-names operation. Once the name of an operation is known, details about its parameters
and return value can be determined by invoking the read-operation-description operation. For
example, to learn the names of the operations exposed by the root resource for a standalone server, and
then learn the full details of one of them, via the CLI one would:
WildFly 9
[standalone@localhost:9999 /] :read-operation-names
{
"outcome" => "success",
"result" => [
"add-namespace",
"add-schema-location",
"delete-snapshot",
"full-replace-deployment",
"list-snapshots",
"read-attribute",
"read-children-names",
"read-children-resources",
"read-children-types",
"read-config-as-xml",
"read-operation-description",
"read-operation-names",
"read-resource",
"read-resource-description",
"reload",
"remove-namespace",
"remove-schema-location",
"replace-deployment",
"shutdown",
"take-snapshot",
"upload-deployment-bytes",
"upload-deployment-stream",
"upload-deployment-url",
"validate-address",
"write-attribute"
]
}
[standalone@localhost:9999 /] :read-operation-description(name=upload-deployment-url)
{
"outcome" => "success",
"result" => {
"operation-name" => "upload-deployment-url",
"description" => "Indicates that the deployment content available at the included URL
should be added to the deployment content repository. Note that this operation does not indicate
the content should be deployed into the runtime.",
"request-properties" => {"url" => {
"type" => STRING,
"description" => "The URL at which the deployment content is available for upload to
the domain's or standalone server's deployment content repository.. Note that the URL must be
accessible from the target of the operation (i.e. the Domain Controller or standalone server).",
"required" => true,
"min-length" => 1,
"nillable" => false
}},
"reply-properties" => {
"type" => BYTES,
"description" => "The hash of managed deployment content that has been uploaded to
the domain's or standalone server's deployment content repository.",
"min-length" => 20,
"max-length" => 20,
"nillable" => false
}
}
}
WildFly 9
See Descriptions below for more on how to learn about the operations a resource exposes.
Attributes
Management resources expose information about their state as attributes. Attributes have string name, and
a value of type org.jboss.dmr.ModelNode (or: for the CLI, the text representation of a ModelNode; for
HTTP API, the JSON representation of a ModelNode.)
Attributes can either be read-only or read-write. Reading and writing attribute values is done via the global
read-attribute and write-attribute operations.
The read-attribute operation takes a single parameter "name" whose value is a the name of the
attribute. For example, to read the "port" attribute of a socket-binding resource via the CLI:
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets/socket-binding=https:read-attribute(name=port)
{
"outcome" => "success",
"result" => 8443
}
If an attribute is writable, the write-attribute operation is used to mutate its state. The operation takes
two parameters:
name the name of the attribute
value the value of the attribute
For example, to read the "port" attribute of a socket-binding resource via the CLI:
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets/socket-binding=https:write-attribute(name=port,value=8444){"outcome"
=> "success"}
WildFly 9
[standalone@localhost:9999 /] /subsystem=web/connector=http:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"bytesReceived" => "0",
"bytesSent" => "0",
"errorCount" => "0",
"maxTime" => "0",
"processingTime" => "0",
"protocol" => "HTTP/1.1",
"requestCount" => "0",
"scheme" => "http",
"socket-binding" => "http",
"ssl" => undefined,
"virtual-server" => undefined
}
}
Omit the "include-runtime" parameter (or set it to "false") to limit output to those attributes whose values are
stored in the persistent configuration:
[standalone@localhost:9999 /] /subsystem=web/connector=http:read-resource
{
"outcome" => "success",
"result" => {
"protocol" => "HTTP/1.1",
"scheme" => "http",
"socket-binding" => "http",
"ssl" => undefined,
"virtual-server" => undefined
}
}
See Descriptions below for how to learn more about the attributes a particular resource exposes.
WildFly 9
Children
Management resources may support child resources. The types of children a resource supports (e.g.
connector for the web subsystem resource) can be obtained by querying the resource's description (see
Descriptions below) or by invoking the read-children-types operation. Once you know the legal child
types, you can query the names of all children of a given type by using the global read-children-types
operation. The operation takes a single parameter "child-type" whose value is the type. For example, a
resource representing a socket binding group has children. To find the type of those children and the names
of resources of that type via the CLI one could:
[standalone@localhost:9999 /] /socket-binding-group=standard-sockets:read-children-types
{
"outcome" => "success",
"result" => ["socket-binding"]
}
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets:read-children-names(child-type=socket-binding)
{
"outcome" => "success",
"result" => [
"http",
"https",
"jmx-connector-registry",
"jmx-connector-server",
"jndi",
"osgi-http",
"remoting",
"txn-recovery-environment",
"txn-status-manager"
]
}
Descriptions
All resources expose metadata that describes their attributes, operations and child types. This metadata is
itself obtained by invoking one or more of the global operations each resource supports. We showed
examples of the read-operation-names, read-operation-description, read-children-types
and read-children-names operations above.
The read-resource-description operation can be used to find the details of the attributes and child
types associated with a resource. For example, using the CLI:
WildFly 9
[standalone@localhost:9999 /] /socket-binding-group=standard-sockets:read-resource-description
{
"outcome" => "success",
"result" => {
"description" => "Contains a list of socket configurations.",
"head-comment-allowed" => true,
"tail-comment-allowed" => false,
"attributes" => {
"name" => {
"type" => STRING,
"description" => "The name of the socket binding group.",
"required" => true,
"head-comment-allowed" => false,
"tail-comment-allowed" => false,
"access-type" => "read-only",
"storage" => "configuration"
},
"default-interface" => {
"type" => STRING,
"description" => "Name of an interface that should be used as the interface for
any sockets that do not explicitly declare one.",
"required" => true,
"head-comment-allowed" => false,
"tail-comment-allowed" => false,
"access-type" => "read-write",
"storage" => "configuration"
},
"port-offset" => {
"type" => INT,
"description" => "Increment to apply to the base port values defined in the
socket bindings to derive the runtime values to use on this server.",
"required" => false,
"head-comment-allowed" => true,
"tail-comment-allowed" => false,
"access-type" => "read-write",
"storage" => "configuration"
}
},
"operations" => {},
"children" => {"socket-binding" => {
"description" => "The individual socket configurtions.",
"min-occurs" => 0,
"model-description" => undefined
}}
}
}
Note the "operations" => }} in the output above. If the command had included the
{{operations parameter (i.e.
/socket-binding-group=standard-sockets:read-resource-description(operations=true)
) the output would have included the description of each operation supported by the resource.
WildFly 9
See the Global operations section for details on other parameters supported by the
read-resource-description operation and all the other globally available operations.
Standalone server
The structure of the managed resource tree is quite close to the structure of the standalone.xml
configuration file.
The root resource
extension extensions installed in the server
path paths available on the server
system-property system properties set as part of the configuration (i.e. not on the
command line)
core-service=management the server's core management services
core-service=service-container resource for the JBoss MSC ServiceContainer
that's at the heart of the AS
subsystem the subsystems installed on the server. The bulk of the management model will
be children of type subsystem
interface interface configurations
socket-binding-group the central resource for the server's socket bindings
socket-binding individual socket binding configurations
deployment available deployments on the server
WildFly 9
Managed domain
In a managed domain, the structure of the managed resource tree spans the entire domain, covering both
the domain wide configuration (e.g. what's in domain.xml, the host specific configuration for each host (e.g.
what's in host.xml, and the resources exposed by each running application server. The Host Controller
processes in a managed domain provide access to all or part of the overall resource tree. How much is
available depends on whether the management client is interacting with the Host Controller that is acting as
the master Domain Controller. If the Host Controller is the master Domain Controller, then the section of the
tree for each host is available. If the Host Controller is a slave to a remote Domain Controller, then only the
portion of the tree associated with that host is available.
WildFly 9
The root resource for the entire domain. The persistent configuration associated with this resource
and its children, except for those of type host, is persisted in the domain.xml file on the Domain
Controller.
extension extensions available in the domain
path paths available on across the domain
system-property system properties set as part of the configuration (i.e. not on the
command line) and available across the domain
profile sets of subsystem configurations that can be assigned to server groups
subsystem configuration of subsystems that are part of the profile
interface interface configurations
socket-binding-group sets of socket bindings configurations that can be applied to
server groups
socket-binding individual socket binding configurations
deployment deployments available for assignment to server groups
server-group server group configurations
host the individual Host Controllers. Each child of this type represents the root resource for a
particular host. The persistent configuration associated with one of these resources or its
children is persisted in the host's host.xml file.
path paths available on each server on the host
system-property system properties to set on each server on the host
core-service=management the Host Controller's core management services
interface interface configurations that apply to the Host Controller or servers on the
host
jvm JVM configurations that can be applied when launching servers
server-config configuration describing how the Host Controller should launch a
server; what server group configuration to use, and any server-specific overrides of
items specified in other resources
server the root resource for a running server. Resources from here and below are
not directly persisted; the domain-wide and host level resources contain the persistent
configuration that drives a server
extension extensions installed in the server
path paths available on the server
system-property system properties set as part of the configuration (i.e. not
on the command line)
core-service=management the server's core management services
core-service=service-container resource for the JBoss MSC
ServiceContainer that's at the heart of the AS
subsystem the subsystems installed on the server. The bulk of the
management model will be children of type subsystem
interface interface configurations
socket-binding-group the central resource for the server's socket bindings
socket-binding individual socket binding configurations
deployment available deployments on the server
WildFly 9
Extensions
An extension is a module that extends the core capabilities of the server. The WildFly 8 core is very simple
and lightweight; most of the capabilities people associate with an application server are provided via
extensions. An extension is packaged as a module in the modules folder. The user indicates that they want
a particular extension to be available by including an <extension/> element naming its module in the
domain.xml or standalone.xml file.
<extensions>
[...]
<extension
<extension
<extension
<extension
</extensions>
module="org.jboss.as.transactions"/>
module="org.jboss.as.web" />
module="org.jboss.as.webservices" />
module="org.jboss.as.weld" />
WildFly 9
Paths
A logical name for a filesystem path. The domain.xml, host.xml and standalone.xml configurations
all include a section where paths can be declared. Other sections of the configuration can then reference
those paths by their logical name, rather than having to include the full details of the path (which may vary on
different machines). For example, the logging subsystem configuration includes a reference to the "
jboss.server.log.dir" path that points to the server's "log" directory.
WildFly 8 automatically provides a number of standard paths without any need for the user to configure them
in a configuration file:
jboss.home - the root directory of the WildFly distribution
user.home - user's home directory
user.dir - user's current working directory
java.home - java installation directory
jboss.server.base.dir - root directory for an individual server instance
jboss.server.data.dir - directory the server will use for persistent data file storage
jboss.server.log.dir - directory the server will use for log file storage
jboss.server.tmp.dir - directory the server will use for temporary file storage
jboss.domain.servers.dir - directory under which a host controller will create the working area
for individual server instances (managed domain mode only)
Users can add their own paths or override all except the first 5 of the above by adding a <path/> element
to their configuration file.
<path name="x"/>
WildFly 9
Such a configuration simply says, "There is a path named 'x' that other parts of the domain.xml
configuration can reference. The actual filesystem location pointed to by 'x' is host-specific and will be
specified in each machine's host.xml file." If this approach is used, there must be a path element in each
machine's host.xml that specifies what the actual filesystem path is:
A <path/> element in a standalone.xml must include the specification of the actual filesystem path.
Interfaces
A logical name for a network interface/IP address/host name to which sockets can be bound. The
domain.xml, host.xml and standalone.xml configurations all include a section where interfaces can
be declared. Other sections of the configuration can then reference those interfaces by their logical name,
rather than having to include the full details of the interface (which may vary on different machines). An
interface configuration includes the logical name of the interface as well as information specifying the criteria
to use for resolving the actual physical address to use. See Interfaces and ports for further details.
An <interface/> element in a domain.xml need not include anything more than the name attribute; i.e. it
need not include any information indicating what the actual IP address associated with the name is:
<interface name="internal"/>
Such a configuration simply says, "There is an interface named 'internal' that other parts of the domain.xml
configuration can reference. The actual IP address pointed to by 'internal' is host-specific and will be
specified in each machine's host.xml file." If this approach is used, there must be an interface element in
each machine's host.xml that specifies the criteria for determining the IP address:
<interface name="internal">
<nic name="eth1"/>
</interface>
An <interface/> element in a standalone.xml must include the criteria for determining the IP address.
WildFly 9
System Properties
System property values can be set in a number of places in domain.xml, host.xml and
standalone.xml. The values in standalone.xml are set as part of the server boot process. Values in
domain.xml and host.xml are applied to servers when they are launched.
When a system property is configured in domain.xml or host.xml, the servers it ends up being applied to
depends on where it is set. Setting a system property in a child element directly under the domain.xml root
results in the property being set on all servers. Setting it in a <system-property/> element inside a
<server-group/> element in domain.xml results in the property being set on all servers in the group.
Setting it in a child element directly under the host.xml root results in the property being set on all servers
controlled by that host's Host Controller. Finally, setting it in a <system-property/> element inside a
<server/> element in host.xml result in the property being set on that server. The same property can be
configured in multiple locations, with a value in a <server/> element taking precedence over a value
specified directly under the host.xml root element, the value in a host.xml taking precedence over
anything from domain.xml, and a value in a <server-group/> element taking precedence over a value
specified directly under the domain.xml root element.
WildFly 9
Address
All WildFly management resources are organized in a tree. The path to the node in the tree for a particular
resource is its address. Each segment in a resource's address is a key/value pair:
The key is the resource's type, in the context of its parent. So, for example, the root resource for a
standalone server has children of type subsystem, interface, socket-binding, etc. The
resource for the subsystem that provides the AS's webserver capability has children of type
connector and virtual-server. The resource for the subsystem that provides the AS's
messaging server capability has, among others, children of type jms-queue and jms-topic.
The value is the name of a particular resource of the given type, e.g web or messaging for
subsystems or http or https for web subsystem connectors.
The full address for a resource is the ordered list of key/value pairs that lead from the root of the tree to the
resource. Typical notation is to separate the elements in the address with a '/' and to separate the key and
the value with an '=':
/subsystem=web/connector=http
/subsystem=messaging/jms-queue=testQueue
/interface=public
When using the HTTP API, a '/' is used to separate the key and the value instead of an '=':
http://localhost:9990/management/subsystem/web/connector/http
http://localhost:9990/management/subsystem/messaging/jms-queue/testQueue
http://localhost:9990/management/interface/public
Operations
Querying or modifying the state of a resource is done via an operation. An operation has the following
characteristics:
A string name
Zero or more named parameters. Each parameter has a string name, and a value of type
org.jboss.dmr.ModelNode (or, when invoked via the CLI, the text representation of a
ModelNode; when invoked via the HTTP API, the JSON representation of a ModelNode.)
Parameters may be optional.
A return value, which will be of type org.jboss.dmr.ModelNode (or, when invoked via the CLI, the
text representation of a ModelNode; when invoked via the HTTP API, the JSON representation of a
ModelNode.)
Every resource except the root resource will have an add operation and should have a remove operation
("should" because in WildFly 8 many do not). The parameters for the add operation vary depending on the
resource. The remove operation has no parameters.
WildFly 9
There are also a number of "global" operations that apply to all resources. See Global operations for full
details.
The operations a resource supports can themselves be determined by invoking an operation: the
read-operation-names operation. Once the name of an operation is known, details about its parameters
and return value can be determined by invoking the read-operation-description operation. For
example, to learn the names of the operations exposed by the root resource for a standalone server, and
then learn the full details of one of them, via the CLI one would:
WildFly 9
[standalone@localhost:9999 /] :read-operation-names
{
"outcome" => "success",
"result" => [
"add-namespace",
"add-schema-location",
"delete-snapshot",
"full-replace-deployment",
"list-snapshots",
"read-attribute",
"read-children-names",
"read-children-resources",
"read-children-types",
"read-config-as-xml",
"read-operation-description",
"read-operation-names",
"read-resource",
"read-resource-description",
"reload",
"remove-namespace",
"remove-schema-location",
"replace-deployment",
"shutdown",
"take-snapshot",
"upload-deployment-bytes",
"upload-deployment-stream",
"upload-deployment-url",
"validate-address",
"write-attribute"
]
}
[standalone@localhost:9999 /] :read-operation-description(name=upload-deployment-url)
{
"outcome" => "success",
"result" => {
"operation-name" => "upload-deployment-url",
"description" => "Indicates that the deployment content available at the included URL
should be added to the deployment content repository. Note that this operation does not indicate
the content should be deployed into the runtime.",
"request-properties" => {"url" => {
"type" => STRING,
"description" => "The URL at which the deployment content is available for upload to
the domain's or standalone server's deployment content repository.. Note that the URL must be
accessible from the target of the operation (i.e. the Domain Controller or standalone server).",
"required" => true,
"min-length" => 1,
"nillable" => false
}},
"reply-properties" => {
"type" => BYTES,
"description" => "The hash of managed deployment content that has been uploaded to
the domain's or standalone server's deployment content repository.",
"min-length" => 20,
"max-length" => 20,
"nillable" => false
}
}
}
WildFly 9
See Descriptions below for more on how to learn about the operations a resource exposes.
Attributes
Management resources expose information about their state as attributes. Attributes have string name, and
a value of type org.jboss.dmr.ModelNode (or: for the CLI, the text representation of a ModelNode; for
HTTP API, the JSON representation of a ModelNode.)
Attributes can either be read-only or read-write. Reading and writing attribute values is done via the global
read-attribute and write-attribute operations.
The read-attribute operation takes a single parameter "name" whose value is a the name of the
attribute. For example, to read the "port" attribute of a socket-binding resource via the CLI:
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets/socket-binding=https:read-attribute(name=port)
{
"outcome" => "success",
"result" => 8443
}
If an attribute is writable, the write-attribute operation is used to mutate its state. The operation takes
two parameters:
name the name of the attribute
value the value of the attribute
For example, to read the "port" attribute of a socket-binding resource via the CLI:
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets/socket-binding=https:write-attribute(name=port,value=8444){"outcome"
=> "success"}
WildFly 9
[standalone@localhost:9999 /] /subsystem=web/connector=http:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"bytesReceived" => "0",
"bytesSent" => "0",
"errorCount" => "0",
"maxTime" => "0",
"processingTime" => "0",
"protocol" => "HTTP/1.1",
"requestCount" => "0",
"scheme" => "http",
"socket-binding" => "http",
"ssl" => undefined,
"virtual-server" => undefined
}
}
Omit the "include-runtime" parameter (or set it to "false") to limit output to those attributes whose values are
stored in the persistent configuration:
[standalone@localhost:9999 /] /subsystem=web/connector=http:read-resource
{
"outcome" => "success",
"result" => {
"protocol" => "HTTP/1.1",
"scheme" => "http",
"socket-binding" => "http",
"ssl" => undefined,
"virtual-server" => undefined
}
}
See Descriptions below for how to learn more about the attributes a particular resource exposes.
WildFly 9
Children
Management resources may support child resources. The types of children a resource supports (e.g.
connector for the web subsystem resource) can be obtained by querying the resource's description (see
Descriptions below) or by invoking the read-children-types operation. Once you know the legal child
types, you can query the names of all children of a given type by using the global read-children-types
operation. The operation takes a single parameter "child-type" whose value is the type. For example, a
resource representing a socket binding group has children. To find the type of those children and the names
of resources of that type via the CLI one could:
[standalone@localhost:9999 /] /socket-binding-group=standard-sockets:read-children-types
{
"outcome" => "success",
"result" => ["socket-binding"]
}
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets:read-children-names(child-type=socket-binding)
{
"outcome" => "success",
"result" => [
"http",
"https",
"jmx-connector-registry",
"jmx-connector-server",
"jndi",
"osgi-http",
"remoting",
"txn-recovery-environment",
"txn-status-manager"
]
}
Descriptions
All resources expose metadata that describes their attributes, operations and child types. This metadata is
itself obtained by invoking one or more of the global operations each resource supports. We showed
examples of the read-operation-names, read-operation-description, read-children-types
and read-children-names operations above.
The read-resource-description operation can be used to find the details of the attributes and child
types associated with a resource. For example, using the CLI:
WildFly 9
[standalone@localhost:9999 /] /socket-binding-group=standard-sockets:read-resource-description
{
"outcome" => "success",
"result" => {
"description" => "Contains a list of socket configurations.",
"head-comment-allowed" => true,
"tail-comment-allowed" => false,
"attributes" => {
"name" => {
"type" => STRING,
"description" => "The name of the socket binding group.",
"required" => true,
"head-comment-allowed" => false,
"tail-comment-allowed" => false,
"access-type" => "read-only",
"storage" => "configuration"
},
"default-interface" => {
"type" => STRING,
"description" => "Name of an interface that should be used as the interface for
any sockets that do not explicitly declare one.",
"required" => true,
"head-comment-allowed" => false,
"tail-comment-allowed" => false,
"access-type" => "read-write",
"storage" => "configuration"
},
"port-offset" => {
"type" => INT,
"description" => "Increment to apply to the base port values defined in the
socket bindings to derive the runtime values to use on this server.",
"required" => false,
"head-comment-allowed" => true,
"tail-comment-allowed" => false,
"access-type" => "read-write",
"storage" => "configuration"
}
},
"operations" => {},
"children" => {"socket-binding" => {
"description" => "The individual socket configurtions.",
"min-occurs" => 0,
"model-description" => undefined
}}
}
}
Note the "operations" => }} in the output above. If the command had included the
{{operations parameter (i.e.
/socket-binding-group=standard-sockets:read-resource-description(operations=true)
) the output would have included the description of each operation supported by the resource.
WildFly 9
See the Global operations section for details on other parameters supported by the
read-resource-description operation and all the other globally available operations.
Standalone server
The structure of the managed resource tree is quite close to the structure of the standalone.xml
configuration file.
The root resource
extension extensions installed in the server
path paths available on the server
system-property system properties set as part of the configuration (i.e. not on the
command line)
core-service=management the server's core management services
core-service=service-container resource for the JBoss MSC ServiceContainer
that's at the heart of the AS
subsystem the subsystems installed on the server. The bulk of the management model will
be children of type subsystem
interface interface configurations
socket-binding-group the central resource for the server's socket bindings
socket-binding individual socket binding configurations
deployment available deployments on the server
WildFly 9
Managed domain
In a managed domain, the structure of the managed resource tree spans the entire domain, covering both
the domain wide configuration (e.g. what's in domain.xml, the host specific configuration for each host (e.g.
what's in host.xml, and the resources exposed by each running application server. The Host Controller
processes in a managed domain provide access to all or part of the overall resource tree. How much is
available depends on whether the management client is interacting with the Host Controller that is acting as
the master Domain Controller. If the Host Controller is the master Domain Controller, then the section of the
tree for each host is available. If the Host Controller is a slave to a remote Domain Controller, then only the
portion of the tree associated with that host is available.
WildFly 9
The root resource for the entire domain. The persistent configuration associated with this resource
and its children, except for those of type host, is persisted in the domain.xml file on the Domain
Controller.
extension extensions available in the domain
path paths available on across the domain
system-property system properties set as part of the configuration (i.e. not on the
command line) and available across the domain
profile sets of subsystem configurations that can be assigned to server groups
subsystem configuration of subsystems that are part of the profile
interface interface configurations
socket-binding-group sets of socket bindings configurations that can be applied to
server groups
socket-binding individual socket binding configurations
deployment deployments available for assignment to server groups
server-group server group configurations
host the individual Host Controllers. Each child of this type represents the root resource for a
particular host. The persistent configuration associated with one of these resources or its
children is persisted in the host's host.xml file.
path paths available on each server on the host
system-property system properties to set on each server on the host
core-service=management the Host Controller's core management services
interface interface configurations that apply to the Host Controller or servers on the
host
jvm JVM configurations that can be applied when launching servers
server-config configuration describing how the Host Controller should launch a
server; what server group configuration to use, and any server-specific overrides of
items specified in other resources
server the root resource for a running server. Resources from here and below are
not directly persisted; the domain-wide and host level resources contain the persistent
configuration that drives a server
extension extensions installed in the server
path paths available on the server
system-property system properties set as part of the configuration (i.e. not
on the command line)
core-service=management the server's core management services
core-service=service-container resource for the JBoss MSC
ServiceContainer that's at the heart of the AS
subsystem the subsystems installed on the server. The bulk of the
management model will be children of type subsystem
interface interface configurations
socket-binding-group the central resource for the server's socket bindings
socket-binding individual socket binding configurations
deployment available deployments on the server
WildFly 9
Standalone Server
For many use cases, the centralized management capability available via a managed domain is not
necessary. For these use cases, a WildFly 8 instance can be run as a "standalone server". A standalone
server instance is an independent process, much like an JBoss Application Server 3, 4, 5, or 6 instance is.
Standalone instances can be launched via the standalone.sh or standalone.bat launch scripts.
If more than one standalone instance is launched and multi-server management is desired, it is the user's
responsibility to coordinate management across the servers. For example, to deploy an application across all
of the standalone servers, the user would need to individually deploy the application on each server.
It is perfectly possible to launch multiple standalone server instances and have them form an HA cluster, just
like it was possible with JBoss Application Server 3, 4, 5 and 6.
Managed Domain
One of the primary new features of WildFly 8 is the ability to manage multiple WildFly instances from a single
control point. A collection of such servers is referred to as the members of a "domain" with a single Domain
Controller process acting as the central management control point. All of the WildFly 8 instances in the
domain share a common management policy, with the Domain Controller acting to ensure that each server
is configured according to that policy. Domains can span multiple physical (or virtual) machines, with all
WildFly 8 instances on a given host under the control of a special Host Controller process. One Host
Controller instance is configured to act as the central Domain Controller. The Host Controller on each host
interacts with the Domain Controller to control the lifecycle of the application server instances running on its
host and to assist the Domain Controller in managing them.
When you launch a WildFly 8 managed domain on a host (via the domain.sh or domain.bat launch
scripts) your intent is to launch a Host Controller and usually at least one WildFly instance. On one of the
hosts the Host Controller should be configured to act as the Domain Controller. See [WLFY8:Domain Setup]
for details.
The following is an example managed domain topology:
WildFly 9
Host
Each "Host" box in the above diagram represents a physical or virtual host. A physical host can contain zero,
one or more server instances.
WildFly 9
Host Controller
When the domain.sh or domain.bat script is run on a host, a process known as a Host Controller is
launched. The Host Controller is solely concerned with server management; it does not itself handle
application server workloads. The Host Controller is responsible for starting and stopping the individual
application server processes that run on its host, and interacts with the Domain Controller to help manage
them.
Each Host Controller by default reads its configuration from the domain/configuration/host.xml file
located in the unzipped WildFly 8 installation on its host's filesystem. The host.xml file contains
configuration information that is specific to the particular host. Primarily:
the listing of the names of the actual WildFly 8 instances that are meant to run off of this installation.
configuration of how the Host Controller is to contact the Domain Controller to register itself and
access the domain configuration. This may either be configuration of how to find and contact a remote
Domain Controller, or a configuration telling the Host Controller to itself act as the Domain Controller.
configuration of items that are specific to the local physical installation. For example, named interface
definitions declared in domain.xml (see below) can be mapped to an actual machine-specific IP
address in host.xml. Abstract path names in domain.xml can be mapped to actual filesystem
paths in host.xml.
Domain Controller
One Host Controller instance is configured to act as the central management point for the entire domain, i.e.
to be the Domain Controller. The primary responsibility of the Domain Controller is to maintain the domain's
central management policy, to ensure all Host Controllers are aware of its current contents, and to assist the
Host Controllers in ensuring any running application server instances are configured in accordance with this
policy. This central management policy is stored by default in the domain/configuration/domain.xml
file in the unzipped WildFly 8 installation on Domain Controller's host's filesystem.
A domain.xml file must be located in the domain/configuration directory of an installation that's
meant to run the Domain Controller. It does not need to be present in installations that are not meant to run a
Domain Controller; i.e. those whose Host Controller is configured to contact a remote Domain Controller.
The presence of a domain.xml file on such a server does no harm.
The domain.xml file includes, among other things, the configuration of the various "profiles" that WildFly 8
instances in the domain can be configured to run. A profile configuration includes the detailed configuration
of the various subsystems that comprise that profile (e.g. an embedded JBoss Web instance is a subsystem;
a JBoss TS transaction manager is a subsystem, etc). The domain configuration also includes the definition
of groups of sockets that those subsystems may open. The domain configuration also includes the definition
of "server groups":
WildFly 9
Server Group
A server group is set of server instances that will be managed and configured as one. In a managed domain
each application server instance is a member of a server group. (Even if the group only has a single server,
the server is still a member of a group.) It is the responsibility of the Domain Controller and the Host
Controllers to ensure that all servers in a server group have a consistent configuration. They should all be
configured with the same profile and they should have the same deployment content deployed.
The domain can have multiple server groups. The above diagram shows two server groups, "ServerGroupA"
and "ServerGroupB". Different server groups can be configured with different profiles and deployments; for
example in a domain with different tiers of servers providing different services. Different server groups can
also run the same profile and have the same deployments; for example to support rolling application
upgrade scenarios where a complete service outage is avoided by first upgrading the application on one
server group and then upgrading a second server group.
An example server group definition is as follows:
WildFly 9
Server
Each "Server" in the above diagram represents an actual application server instance. The server runs in a
separate JVM process from the Host Controller. The Host Controller is responsible for launching that
process. (In a managed domain the end user cannot directly launch a server process from the command
line.)
The Host Controller synthesizes the server's configuration by combining elements from the domain wide
configuration (from domain.xml ) and the host-specific configuration (from host.xml ).
WildFly 9
Example IP Adresses
In this example the domain controller uses 192.168.0.101 and the host controller 192.168.0.10
Configuring a host to act as the Domain Controller is done through the domain-controller declaration in
host.xml. If it includes the <local/> element, then this host will become the domain controller:
<domain-controller>
<local/>
</domain-controller>
(See domain/configuration/host.xml)
A host acting as the Domain Controller must expose a management interface on an address accessible to
the other hosts in the domain. Exposing an HTTP(S) management interface is not required, but is
recommended as it allows the Administration Console to work:
<management-interfaces>
<native-interface security-realm="ManagementRealm">
<socket interface="management" port="${jboss.management.native.port:9999}"/>
</native-interface>
<http-interface security-realm="ManagementRealm">
<socket interface="management" port="${jboss.management.http.port:9990}"/>
</http-interface>
</management-interfaces>
The interface attributes above refer to a named interface declaration later in the host.xml file. This interface
declaration will be used to resolve a corresponding network interface.
WildFly 9
<interfaces>
<interface name="management">
<inet-address value="192.168.0.101"/>
</interface>
</interfaces>
(See domain/configuration/host.xml)
Please consult the chapter "Interface Configuration" for a more detailed explanation on how to configure
network interfaces.
Next by default the master domain controller is configured to require authentication so a user needs to be
added that can be used by the slave domain controller to connect.
Make use of the add-user utility to add a new user, for this example I am adding a new user called slave.
add-user MUST be run on the master domain controller and NOT the slave.
When you reach the final question of the interactive flow answer y or yes to indicate that the new user will
be used for a process e.g.
Is this new user going to be used for one AS process to connect to another AS process e.g. slave
domain controller?
yes/no? y
To represent the user add the following to the server-identities definition <secret
value="cE3EBEkE=" />
Make a note of the XML Element output as that is going to be required within the slave configuration.
<host xmlns="urn:jboss:domain:3.0"
name="slave">
[...]
</host>
WildFly 9
(See domain/configuration/host.xml)
If the name attribute is not set, the default name for the host will be the value of the jboss.host.name}
system property. If that is not set, the value of the {{HOSTNAME or COMPUTERNAME
environment variable will be used, one of which will be set on most operating systems. If neither is set the
name will be the value of InetAddress.getLocalHost().getHostName().
A security realm needs to be defined to hold the identity of the slave. Since it is performing a specific
purpose I would suggest a new realm is defined although it is possible to combine this with an existing
realm.
<security-realm name="SlaveRealm">
<server-identities>
<secret value="cE3EBEkE=" />
</server-identities>
</security-realm>
The <secret /> element here is the one output from add-user previously. To create the <secret />
element yourself the value needs to be the password encoded using Base64.
Tell it how to find the domain controller so it can register itself with the domain:
<domain-controller>
<remote protocol="remote" host="192.168.0.101" port="9999" username="slave"
security-realm="SlaveRealm"/>
</domain-controller>
Since we have also exposed the HTTP management interface we could also use :
<domain-controller>
<remote protocol="http-remoting" host="192.168.0.101" port="9990" username="slave"
security-realm="SlaveRealm"/>
</domain-controller>
(See domain/configuration/host.xml)
The username attribute here is optional, if it is omitted then the name of the host will be used instead, in this
example that was already set to name.
The name of each host needs to be unique when registering with the domain controller, however
the username does not - using the username attribute allows the same account to be used by
multiple hosts if this makes sense in your environment.
The <remote /> element is also associated with the security realm SlaveRealm, this is how it picks up
the password from the <secret /> element.
WildFly 9
<server-groups>
<server-group name="main-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
<permgen size="128m" max-size="128m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
<server-group name="other-server-group" profile="bigger">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="bigger-sockets"/>
</server-group>
</server-groups>
(See domain/configuration/domain.xml)
The domain controller also defines the socket binding groups and the profiles. The socket binding groups
define the default socket bindings that are used:
<socket-binding-groups>
<socket-binding-group name="standard-sockets" default-interface="public">
<socket-binding name="http" port="8080"/>
[...]
</socket-binding-group>
<socket-binding-group name="bigger-sockets" include="standard-sockets"
default-interface="public">
<socket-binding name="unique-to-bigger" port="8123"/>
</socket-binding-group>
</socket-binding-groups>
(See domain/configuration/domain.xml)
In this example the bigger-sockets group includes all the socket bindings defined in the
standard-sockets groups and then defines an extra socket binding of its own.
A profile is a collection of subsystems, and these subsystems are what implement the functionality people
expect of an application server.
WildFly 9
<profiles>
<profile name="default">
<subsystem xmlns="urn:jboss:domain:web:1.0">
<connector name="http" scheme="http" protocol="HTTP/1.1" socket-binding="http"/>
[...]
</subsystem>
<\!-\- The rest of the subsystems here \-->
[...]
</profile>
<profile name="bigger">
<subsystem xmlns="urn:jboss:domain:web:1.0">
<connector name="http" scheme="http" protocol="HTTP/1.1" socket-binding="http"/>
[...]
</subsystem>
<\!-\- The same subsystems as defined by 'default' here \-->
[...]
<subsystem xmlns="urn:jboss:domain:fictional-example:1.0">
<socket-to-use name="unique-to-bigger"/>
</subsystem>
</profile>
</profiles>
(See domain/configuration/domain.xml)
Here we have two profiles. The bigger profile contains all the same subsystems as the default profile
(athough the parameters for the various subsystems could be different in each profile), and adds the
fictional-example subsystem which references the unique-to-bigger socket binding.
5.14.4 Servers
The host controller defines one or more servers:
<servers>
<server name="server-one" group="main-server-group">
<\!-\- server-one inherits the default socket-group declared in the server-group \-->
<jvm name="default"/>
</server>
<server name="server-two" group="main-server-group" auto-start="true">
<socket-binding-group ref="standard-sockets" port-offset="150"/>
<jvm name="default">
<heap size="64m" max-size="256m"/>
</jvm>
</server>
<server name="server-three" group="other-server-group" auto-start="false">
<socket-binding-group ref="bigger-sockets" port-offset="250"/>
</server>
</servers>
(See domain/configuration/host.xml)
WildFly 9
server-one and server-two both are associated with main-server-group so that means they both
run the subsystems defined by the default profile, and have the socket bindings defined by the
standard-sockets socket binding group. Since all the servers defined by a host will be run on the same
physical host we would get port conflicts unless we used <socket-binding-group
ref="standard-sockets" port-offset="150"/> for server-two. This means that server-two
will use the socket bindings defined by standard-sockets but it will add 150 to each port number defined,
so the value used for http will be 8230 for server-two.
server-three will not be started due to its auto-start="false". The default value if no auto-start
is given is true so both server-one and server-two will be started when the host controller is started.
server-three belongs to other-server-group, so if its auto-start were changed to true it would
start up using the subsystems from the bigger profile, and it would use the bigger-sockets socket
binding group.
JVM
The host controller contains the main jvm definitions with arguments:
<jvms>
<jvm name="default">
<heap size="64m" max-size="128m"/>
</jvm>
</jvms>
(See domain/configuration/host.xml)
From the preceeding examples we can see that we also had a jvm reference at server group level in the
domain controller. The jvm's name must match one of the definitions in the host controller. The values
supplied at domain controller and host controller level are combined, with the host controller taking
precedence if the same parameter is given in both places.
Finally, as seen, we can also override the jvm at server level. Again, the jvm's name must match one of the
definitions in the host controller. The values are combined with the ones coming in from domain controller
and host controller level, this time the server definition takes precedence if the same parameter is given in all
places.
Following these rules the jvm parameters to start each server would be
Server
JVM parameters
server-one
server-two
WildFly 9
[standalone@localhost:9999 /] :read-children-names(child-type=interface)
{
"outcome" => "success",
"result" => [
"management",
"public"
]
}
This means the server in question declares two interfaces: One is referred to as " management"; the other
one "public". The "management" interface is used for all components and services that are required by the
management layer (i.e. the HTTP Management Endpoint). The "public" interface binding is used for any
application related network communication (i.e. Web, Messaging, etc). There is nothing special about these
names; interfaces can be declared with any name. Other sections of the configuration can then reference
those interfaces by their logical name, rather than having to include the full details of the interface (which, on
servers in a management domain, may vary on different machines).
The domain.xml, host.xml and standalone.xml configuration files all include a section where
interfaces can be declared. If we take a look at the XML declaration it reveals the selection criteria. The
criteria is one of two types: either a single element indicating that the interface should be bound to a wildcard
address, or a set of one or more characteristics that an interface or address must have in order to be a valid
match. The selection criteria in this example are specific IP addresses for each interface:
<interfaces>
<interface name="management">
<inet-address value="127.0.0.1"/>
</interface>
<interface name="public">
<inet-address value="127.0.0.1"/>
</interface>
</interfaces>
WildFly 9
<interface name="global">
<!-- Use the wildcard address -->
<any-address/>
</interface>
<interface name="external">
<nic name="eth0"/>
</interface>
<interface name="default">
<!-- Match any interface/address on the right subnet if it's
up, supports multicast and isn't point-to-point -->
<subnet-match value="192.168.0.0/16"/>
<up/>
<multicast/>
<not>
<point-to-point/>
</not>
</interface>
WildFly 9
WildFly 9
WildFly 9
IP address literals
To change the IP address literals referenced in standalone.xml (or domain.xml), first visit the interface
declarations and ensure that valid IPv6 addresses are being used as interface values. For example, to
change the default configuration in which the loopback interface is used as the primary interface, change
from the IPv4 loopback address:
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:[::1]}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:[::1]}"/>
</interface>
</interfaces>
Note that when embedding IPv6 address literals in the substitution expression, square brackets surrounding
the IP address literal are used to avoid ambiguity. This follows the convention for the use of IPv6 literals in
URLs.
Over and above making such changes for the interface definitions, you should also check the rest of your
configuration file and adjust IP address literals from IPv4 to IPv6 as required.
WildFly 9
WildFly 9
WildFly 9
WildFly 9
Standard Operations
Besides the global operations described above, by convention nearly every resource should expose an add
operation and a remove operation. Exceptions to this convention are the root resource, and resources that
do not store persistent configuration and are created dynamically at runtime (e.g. resources representing the
JVM's platform mbeans or resources representing aspects of the running state of a deployment.)
WildFly 9
The source code for jboss-dmr is available on Github. The maven coordinates for a jboss-dmr release are
org.jboss.jboss-dmr:jboss-dmr.
Next, create a ModelNode and use the beanshell print function to output what type it is:
bsh % node.set(1);
bsh % print(node.getType());
INT
bsh % node.set(true);
bsh % print(node.getType());
BOOLEAN
bsh % node.set("Hello, world");
bsh % print(node.getType());
STRING
WildFly 9
bsh % node.set(2);
bsh % print(node.asInt());
2
bsh % node.set("A string");
bsh % print(node.asString());
A string
ModelNode will attempt to perform type conversions when you invoke the asXXX methods:
bsh %
bsh %
1
bsh %
true
bsh %
bsh %
false
bsh %
bsh %
true
node.set(1);
print(node.asString());
print(node.asBoolean());
node.set(0);
print(node.asBoolean());
node.set("true");
print(node.asBoolean());
The ModelNode.getType() method can be used to ensure a node has an expected value type before
attempting a type conversion.
One set variant takes another ModelNode as its argument. The value of the passed in node is copied, so
there is no shared state between the two model nodes:
WildFly 9
A ModelNode can be cloned. Again, there is no shared state between the original node and its clone:
bsh % clone.protect();
bsh % clone.set("A different string");
// Error: // Uncaught Exception: Method Invocation clone.set : at Line: 15 : in file: <unknown
file> : clone .set ( "A different string" )
Target exception: java.lang.UnsupportedOperationException
java.lang.UnsupportedOperationException
at org.jboss.dmr.ModelNode.checkProtect(ModelNode.java:1441)
at org.jboss.dmr.ModelNode.set(ModelNode.java:351)
....
Lists
The above examples aren't particularly interesting; if all we can do with a ModelNode is wrap a simple Java
primitive, what use is that? However, a ModelNode's value can be more complex than a simple primitive,
and using these more complex types we can build complex data structures. The first more complex type is
ModelType.LIST.
Use the add methods to initialize a node's value as a list and add to the list:
WildFly 9
bsh %
bsh %
bsh %
bsh %
LIST
bsh % print(list.asInt());
2
Use the overloaded get method variant that takes an int param to retrieve an item. The item is returned as a
ModelNode:
Here's one of the trickiest things about jboss-dmr: The get methods actually mutate state; they are not
"read-only". For example, calling get with an index that does not exist yet in the list will actually create a
child of type ModelType.UNDEFINED at that index (and will create UNDEFINED children for any
intervening indices.)
Since the get call always returns a ModelNode and never null it is safe to manipulate the return value:
bsh % list.get(5).set(30);
bsh % print(list.get(5).asInt());
30
That's not so interesting in the above example, but later on with node of type ModelType.OBJECT we'll see
how that kind of method chaining can let you build up fairly complex data structures with a minimum of code.
WildFly 9
Use the asList() method to get a List<ModelNode> of the children:
The asString() and toString() methods provide slightly differently formatted text representations of a
ModelType.LIST node:
bsh % print(list.asString());
[5,10,"A string",undefined,undefined,30]
bsh % print(list.toString());
[
5,
10,
"A string",
undefined,
undefined,
30
]
Finally, if you've previously used set to assign a node's value to some non-list type, you cannot use the add
method:
bsh % node.add(5);
// Error: // Uncaught Exception: Method Invocation node.add : at Line: 18 : in file: <unknown
file> : node .add ( 5 )
Target exception: java.lang.IllegalArgumentException
java.lang.IllegalArgumentException
at org.jboss.dmr.ModelValue.addChild(ModelValue.java:120)
at org.jboss.dmr.ModelNode.add(ModelNode.java:1007)
at org.jboss.dmr.ModelNode.add(ModelNode.java:761)
...
You can, however, use the setEmptyList() method to change the node's type, and then use add:
bsh % node.setEmptyList();
bsh % node.add(5);
bsh % print(node.toString());
[5]
WildFly 9
Properties
The third public class in the jboss-dmr library is org.jboss.dmr.Property. A Property is a String =>
ModelNode tuple.
bsh % node.set(prop);
bsh % print(node.getType());
PROPERTY
bsh % print(node.toString());
("stuff" => [
5,
10,
"A string",
undefined,
undefined,
30
])
Directly instantiating a Property via its constructor is not common. More typically one of the two argument
ModelNode.add or ModelNode.set variants is used. The first argument is the property name:
WildFly 9
ModelType.OBJECT
The most powerful and most commonly used complex value type in jboss-dmr is ModelType.OBJECT. A
ModelNode whose value is ModelType.OBJECT internally maintains a Map<String, ModelNode.
Use the get method variant that takes a string argument to add an entry to the map. If no entry exists under
the given name, a new entry is added with a the value being a ModelType.UNDEFINED node. The node is
returned:
Again it is important to remember that the get operation may mutate the state of a model node by
adding a new entry. It is not a read-only operation.
Since get will never return null, a common pattern is to use method chaining to create the key/value pair:
WildFly 9
bsh % range.get("max").set(10);
bsh % print(range.toString());
{
"min" => 2,
"max" => 10
}
A call to get passing an already existing key will of course return the same model node as was returned the
first time get was called with that key:
Multiple parameters can be passed to get. This is a simple way to traverse a tree made up of
ModelType.OBJECT nodes. Again, get may mutate the node on which it is invoked; e.g. it will actually
create the tree if nodes do not exist. This next example uses a workaround to get beanshell to handle the
overloaded get method that takes a variable number of arguments:
bsh %
bsh %
bsh %
{"US"
The semantics of the backing map in a node of ModelType.OBJECT are those of a LinkedHashMap. The
map remembers the order in which key/value pairs are added. This is relevant when iterating over the pairs
after calling asPropertyList() and for controlling the order in which key/value pairs appear in the output
from toString().
Since the get method will actually mutate the state of a node if the given key does not exist, ModelNode
provides a couple methods to let you check whether the entry is there. The has method simply does that:
WildFly 9
bsh % print(range.has("unit"));
false
bsh % print(range.has("min"));
true
Very often, the need is to not only know whether the key/value pair exists, but whether the value is defined
(i.e. not ModelType.UNDEFINED. This kind of check is analogous to checking whether a field in a Java
class has a null value. The hasDefined lets you do this:
bsh % print(range.hasDefined("unit"));
false
bsh % // Establish an undefined child 'unit';
bsh % range.get("unit");
bsh % print(range.toString());
{
"min" => 2,
"max" => 10,
"unit" => undefined
}
bsh % print(range.hasDefined("unit"));
false
bsh % range.get("unit").set("meters");
bsh % print(range.hasDefined("unit"));
true
ModelType.EXPRESSION
A value of type ModelType.EXPRESSION is stored as a string, but can later be resolved to different value.
The string has a special syntax that should be familiar to those who have used the system property
substitution feature in previous JBoss AS releases.
[<prefix>][${<system-property-name>[:<default-value>]}][<suffix>]*
For example:
${queue.length}
http://${host}
http://${host:localhost}:${port:8080}/index.html
WildFly 9
bsh % print(expression.asString());
${queue.length}
However, calling toString() tells you that this node's value is not of ModelType.STRING:
bsh % print(expression.toString());
expression "${queue.length}"
When the resolve operation is called, the string is parsed and any embedded system properties are
resolved against the JVM's current system property values. A new ModelNode is returned whose value is
the resolved string:
bsh % print(resolved.getType());
STRING
The resolved.asInt() call in the previous example only worked because the string "10" happens to be
convertible into the int 10.
Calling resolve() has no effect on the value of the node on which the method is invoked:
If an expression cannot be resolved, resolve just uses the original string. The string can include more than
one system property substitution:
bsh % expression.setExpression("http://${host}:${port}/index.html");
bsh % resolved = expression.resolve();
bsh % print(resolved.asString());
http://${host}:${port}/index.html
The expression can optionally include a default value, separated from the name of the system property by a
colon:
WildFly 9
bsh % expression.setExpression("http://${host:localhost}:${port:8080}/index.html");
bsh % resolved = expression.resolve();
bsh % print(resolved.asString());
http://localhost:8080/index.html
The resolve method works on nodes of other types as well; it returns a copy without attempting any real
resolution:
bsh
bsh
bsh
bsh
INT
bsh
bsh
5
bsh
10
%
%
%
%
% resolved.set(5);
% print(resolved.asInt());
% print(basic.asInt());
ModelType.TYPE
You can also pass one of the values of the ModelType enum to set:
bsh %
bsh %
bsh %
TYPE
bsh %
LIST
This is useful when using a ModelNode data structure to describe another ModelNode data structure.
WildFly 9
WildFly 9
{
"description => "A manageable resource",
"tail-comment-allowed" => false,
"attributes" => {
"foo" => {
.... details of attribute foo
}
},
"operations" => {
"start" => {
.... details of the start operation
}
},
"children" => {
"bar" => {
.... details of the relationship with children of type "bar"
}
}
}
Description of an Attribute
An attribute is a portion of the management model that is not directly addressable. Instead, it is conceptually
a property of an addressable management resource. For each attribute in the model, the following
descriptive information will be available:
WildFly 9
description String text description of the attribute
type org.jboss.dmr.ModelType the type of the attribute value. One of the enum values
BIG_DECIMAL, BIG_INTEGER, BOOLEAN, BYTES, DOUBLE, INT, LIST, LONG, OBJECT,
PROPERTY, STRING. Most of these are self-explanatory. An OBJECT will be represented in the
detyped model as a map of string keys to values of some other legal type, conceptually similar to a
javax.management.openmbean.CompositeData. A PROPERTY is a single key/value pair,
where the key is a string, and the value is of some other legal type.
value-type ModelType or complex structure Only present if type is LIST or OBJECT. If all
elements in the LIST or all the values of the OBJECT type are of the same type, this will be one of the
ModelType enums BIG_DECIMAL, BIG_INTEGER, BOOLEAN, BYTES, DOUBLE, INT, LONG,
STRING. Otherwise, value-type will detail the structure of the attribute value, enumerating the
value's fields and the type of their value.
expressions-allowed boolean indicates whether the value of the attribute may be of type
ModelType.EXPRESSION, instead of its standard type (see type and value-type above for
discussion of an attribute's standard type.) A value of ModelType.EXPRESSION contains a
system-property substitution expression that the server will resolve against the server-side system
property map before using the value. For example, an attribute named max-threads may have an
expression value of ${example.pool.max-threads:10} instead of just 10. Default value if not
present is false.
required boolean true if the attribute will always exist in a representation of its portion of the
model; false if it may not (implying a null value.) If not present, true is the default.
storage String Either "configuration" or "runtime". If "configuration", the attribute's value is stored
as part of the persistent configuration (e.g. in domain.xml, host.xml or standalone.xml.) If "runtime" the
attribute's value is not stored in the persistent configuration; the value only exists as long as the
resource is running.
access-type String One of "read-only", "read-write" or "metric". Whether an attribute value can
be written, or can only read. A "metric" is a read-only attribute whose value is not stored in the
persistent configuration, and whose value may change due to activity on the server. If an attribute is
"read-write", the resource will expose an operation named "write-attribute" whose "name" parameter
will accept this attribute's name and whose "value" parameter will accept a valid value for this
attribute. That operation will be the standard means of updating this attribute's value.
restart-required String One of "no-services", "all-services", "resource-services" or "jvm".
Only relevant to attributes whose access-type is read-write. Indicates whether execution of a
write-attribute operation whose name parameter specifies this attribute requires a restart of services
(or an entire JVM) in order for the change to take effect in the runtime . See discussion of "Applying
Updates to Runtime Services" below. Default value is "no-services".
alternatives List of string Indicates an exclusive relationship between attributes. If this
attribute is defined, the other attributes listed in this descriptor's value should be undefined (even if
their required descriptor says true; i.e. the presence of this attribute satisfies the requirement.) Default
is undefined; i.e. this does not apply to most attributes.
WildFly 9
requires List of string Indicates that if this attribute has a value (other than undefined), the other
attributes listed in this descriptor's value must also have a value, even if their required descriptor says
false. This would typically be used in conjunction with alternatives. For example, attributes "a" and "b"
are required, but are alternatives to each other; "c" and "d" are optional. But "b" requires "c" and "d",
so if "b" is used, "c" and "d" must also be defined. Default is undefined; i.e. this does not apply to most
attributes.
head-comment-allowed boolean indicates whether the model can store an XML comment that
would be written in the persistent form of the model (e.g. domain.xml) before the start of the XML
element that represents this attribute. This item is optional, and if not present defaults to false. (This is
a different default from what is used for an entire management resource, since model attributes often
map to XML attributes, which don't allow comments.) (Note: storing XML comments in the in-memory
model is not currently supported. This description key is for future use.)
tail-comment-allowed boolean similar to head-comment-allowed, but indicates whether a
comment just before the close of the XML element is supported. A tail comment can only be
supported if the element has child elements, in which case a comment can be inserted between the
final child element and the element's closing tag. This item is optional, and if not present defaults to
false. (This is a different default from what is used for an entire management resource, since model
attributes often map to XML attributes, which don't allow comments.) (Note: storing XML comments in
the in-memory model is not currently supported. This description key is for future use.)
arbitrary key/value pairs that further describe the attribute value, e.g. "max" => 2. See "Arbitrary
Descriptors" below.
Some examples:
"foo" => {
"description" => "The foo",
"type" => INT,
"max" => 2
}
"bar" => {
"description" => "The bar",
"type" => OBJECT,
"value-type" => {
"size" => INT,
"color" => STRING
}
}
Description of an Operation
A management resource may have operations associated with it. The description of an operation will include
the following information:
WildFly 9
WildFly 9
Arbitrary Descriptors
The description of an attribute, operation parameter or operation return value type can include arbitrary
key/value pairs that provide extra information. Whether a particular key/value pair is present depends on the
context, e.g. a pair with key "max" would probably only occur as part of the description of some numeric
type.
WildFly 9
Following are standard keys and their expected value type. If descriptor authors want to add an arbitrary
key/value pair to some descriptor and the semantic matches the meaning of one of the following items, the
standard key/value type must be used.
min int the minimum value of some numeric type. The absence of this item implies there is no
minimum value.
max int the maximum value of some numeric type. The absence of this item implies there is no
maximum value.
min-length int the minimum length of some string, list or byte[] type. The absence of this item
implies a minimum length of zero.
max-length int the maximum length of some string, list or byte[]. The absence of this item
implies there is no maximum value.
nillable boolean whether null or a ModelNode of type ModelType.UNDEFINED is a legal
value. The absence of this item implies false; i.e. null/undefined is not a legal value.
allowed List a list of legal values. The type of the elements in the list should match the type of
the attribute.
default the default value for the attribute if not present in the model
unit - The unit of the value, if one is applicable - e.g. ns, ms, s, m, h, KB, MB, TB. See the
org.jboss.as.controller.client.helpers.MeasurementUnit in the
org.jboss.as:jboss-as-controller-client artifact for a listing of legal measurement units..
Some examples:
{
"operation-name" => "incrementFoo",
"description" => "Increase the value of the 'foo' attribute by the given amount",
"request-properties" => {
"increment" => {
"type" => INT,
"description" => "The amount to increment",
"required" => true
}},
"reply-properties" => {
"type" => INT,
"description" => "The new value",
}
}
{
"operation-name" => "start",
"description" => "Starts the thing",
"request-properties" => {},
"reply-properties" => {}
}
WildFly 9
{
....
"children" => {
"connector" => {
.... description of the relationship with children of type "connector"
},
"virtual-host" => {
.... description of the relationship with children of type "virtual-host"
}
}
WildFly 9
{
"description" => "The connectors used to handle client connections",
"min-occurs" > 1,
"model-description" => {
"description" => "Handles client connections",
"attributes => {
... details of children as documented above
},
"operations" => {
.... details of operations as documented above
},
"children" => {
.... details of the children's children
}
}
}
{
"description" => "The connectors used to handle client connections",
"min-occurs" > 1,
"model-description" => undefined
}
WildFly 9
Because restarting a service can be disruptive to end-user request handling, the handlers for management
operations will not restart any service without some form of explicit instruction from the end user indicating a
service restart is desired. In a few cases, simply executing the operation is an indication the user wants
services to restart (e.g. a /host=master/server-config=server-one:restart operation in a
managed domain, or a /:reload operation on a standalone server.) For all other cases, if an operation (or
attribute write) cannot be performed without restarting a service, the metadata describing the operation or
attribute will include a "restart-required" descriptor whose value indicates what is necessary for the
operation to affect the runtime:
no-services Applying the operation to the runtime does not require the restart of any services.
This value is the default if the restart-required descriptor is not present.
all-services The operation can only immediately update the persistent configuration; applying
the operation to the runtime will require a subsequent restart of all services in the affected VM.
Executing the operation will put the server into a "reload-required" state. Until a restart of all
services is performed the response to this operation and to any subsequent operation will include a
response header "process-state" => "reload-required". For a standalone server, a restart
of all services can be accomplished by executing the /:reload CLI command. For a server in a
managed domain, restarting all services currently requires a full restart of the affected server VM (e.g.
/host=master/server-config=server-one:restart).
jvm --The operation can only immediately update the persistent configuration; applying the operation
to the runtime will require a full process restart (i.e. stop the JVM and launch a new JVM). Executing
the operation will put the server into a "restart-required" state. Until a restart is performed the
response to this operation and to any subsequent operation will include a response header "
process-state" => "restart-required". For a standalone server, a full process restart
requires first stopping the server via OS-level operations (Ctrl-C, kill) or via the /:shutdown CLI
command, and then starting the server again from the command line. For a server in a managed
domain, restarting a server requires executing the
/host=<host>/server-config=<server>:restart operation.
resource-services The operation can only immediately update the persistent configuration;
applying the operation to the runtime will require a subsequent restart of some services associated
with the resource. If the operation includes the request header
"allow-resource-service-restart" => true, the handler for the operation will go ahead
and restart the runtime service. Otherwise executing the operation will put the server into a "
reload-required" state. (See the discussion of "all-services" above for more on the "
reload-required" state.)
WildFly 9
The CLI tool that comes with the application server uses this interface, and user can develop custom clients
that use it as well. In this section we'll cover the basics on how to develop such a client. We'll also cover
details on the format of low-level management operation requests and responses information that should
prove useful for users of the CLI tool as well.
Purpose
org.jboss.remoting:jboss-remoting
Remote communication
org.jboss:jboss-dmr
org.jboss.as:jboss-as-protocol
org.jboss.sasl:jboss-sasl
SASL authentication
org.jboss.xnio:xnio-api
Non-blocking IO
org.jboss.xnio:xnio-nio
Non-blocking IO
org.jboss.logging:jboss-logging
Logging
org.jboss.threads:jboss-threads
Thread management
WildFly 9
The custom client must have maven artifact org.jboss.as:jboss-as-controller-client and its
dependencies on the classpath.
ModelControllerClient client =
ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9999);
The address and port are what is configured in the target process'
<management><management-interfaces><native-interface.../> element.
Typically, however, the native management interface will be secured, requiring clients to authenticate. On
the client side, the custom client will need to provide the user's authentication credentials, obtained in
whatever manner is appropriate for the client (e.g. from a dialog box in a GUI-based client.) Access to these
credentials is provided by passing in an implementation of the
javax.security.auth.callback.CallbackHandler interface. For example:
WildFly 9
What we've done here is created a ModelNode of type ModelType.OBJECT with the following fields:
operation the name of the operation to invoke. All operation requests must include this field and
its value must be a String.
address the address of the resource to invoke the operation against. This field's must be of
ModelType.LIST with each element in the list being a ModelType.PROPERTY. If this field is
omitted the operation will target the root resource. The operation can be targeted at any address in
the management model; here we are targeting it at the resource for the web subsystem's http
connector.
In this case, the request includes two optional parameters:
recursive true means you want the description of child resources under this resource. Default is
false
operations true means you want the description of operations exposed by the resource to be
included. Default is false.
Different operations take different parameters, and some take no parameters at all.
See Format of a Detyped Operation Request for full details on the structure of a ModelNode that will
represent an operation request.
The example above produces an operation request ModelNode equivalent to what the CLI produces
internally when it parses and executes the following low-level CLI command:
[localhost:9999 /]
/subsystem=web/connector=http:read-resource-description(recursive=true,operations=true)
WildFly 9
See Format of a Detyped Operation Response for general details on the structure of the "returnVal"
ModelNode.
The execute operation shown above will block the calling thread until the response is received from the
process being managed. ModelControllerClient also exposes and API allowing asynchronous
invocation:
client.close();
where the return value is the detyped representation of the response, and operation is the detyped
representation of the operation being invoked.
The purpose of this section is to document the structure of operation.
See Format of a Detyped Operation Response for a discussion of the format of the response.
WildFly 9
Simple Operations
A text representation of simple operation would look like this:
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20
}
The order in which the outermost elements appear in the request is not relevant. The required elements are:
operation String The name of the operation being invoked.
address the address of the managed resource against which the request should be executed. If
not set, the address is the root resource. The address is an ordered list of key-value pairs describing
where the resource resides in the overall management resource tree. Management resources are
organized in a tree, so the order in which elements in the address occur is important.
The other key/value pairs are parameter names and their values. The names and values should match what
is specified in the operation's description.
Parameters may have any name, except for the reserved words operation, address and
operation-headers.
Operation Headers
Besides the special operation and address values discussed above, operation requests can also include
special "header" values that help control how the operation executes. These headers are created under the
special reserved word operation-headers:
WildFly 9
This produces:
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20,
"operation-headers" => {
"rollback-on-runtime-failure => false
}
}
WildFly 9
WildFly 9
Composite Operations
The root resource for a Domain or Host Controller or an individual server will expose an operation named "
composite". This operation executes a list of other operations as an atomic unit (although the atomicity
requirement can be relaxed. The structure of the request for the "composite" operation has the same
fundamental structure as a simple operation (i.e. operation name, address, params as key value pairs).
{
"operation" => "composite",
"address" => [],
"steps" => [
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"count" => "count",
"value" => 20
},
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool2")
],
"name" => "count",
"value" => 10
}
],
"operation-headers" => {
"rollback-on-runtime-failure => false
}
}
The rollback-on-runtime-failure operation header discussed above has a particular meaning when
applied to a composite operation, controlling whether steps that successfully execute should be reverted if
other steps fail at runtime. Note that if any steps modify the persistent configuration, and any of those steps
fail, all steps will be reverted. Partial/incomplete changes to the persistent configuration are not allowed.
WildFly 9
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20,
"operation-headers" => {
"rollout-plan" => {
"in-series" => [
{
"concurrent-groups" => {
"groupA" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
},
"groupB" => undefined
}
},
{
"server-group" => {
"groupC" => {
"rolling-to-servers" => false,
"max-failed-servers" => 1
}
}
},
{
"concurrent-groups" => {
"groupD" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
},
"groupE" => undefined
}
}
],
"rollback-across-groups" => true
}
}
}
WildFly 9
As you can see, the rollout plan is another structure in the operation-headers section. The root node of the
structure allows two children:
in-series a list A list of activities that are to be performed in series, with each activity reaching
completion before the next step is executed. Each activity involves the application of the operation to
the servers in one or more server groups. See below for details on each element in the list.
rollback-across-groups boolean indicates whether the need to rollback the operation on all
the servers in one server group should trigger a rollback across all the server groups. This is an
optional setting, and defaults to false.
Each element in the list under the in-series node must have one or the other of the following structures:
concurrent-groups a map of server group names to policies controlling how the operation
should be applied to that server group. For each server group in the map, the operation may be
applied concurrently. See below for details on the per-server-group policy configuration.
server-group a single key/value mapping of a server group name to a policy controlling how the
operation should be applied to that server group. See below for details on the policy configuration.
(Note: there is no difference in plan execution between this and a "concurrent-groups" map with a
single entry.)
The policy controlling how the operation is applied to the servers within a server group has the following
elements, each of which is optional:
rolling-to-servers boolean If true, the operation will be applied to each server in the group
in series. If false or not specified, the operation will be applied to the servers in the group
concurrently.
max-failed-servers int Maximum number of servers in the group that can fail to apply the
operation before it should be reverted on all servers in the group. The default value if not specified is
zero; i.e. failure on any server triggers rollback across the group.
max-failure-percentage int between 0 and 100 Maximum percentage of the total number of
servers in the group that can fail to apply the operation before it should be reverted on all servers in
the group. The default value if not specified is zero; i.e. failure on any server triggers rollback across
the group.
If both max-failed-servers and max-failure-percentage are set, max-failure-percentage
takes precedence.
Looking at the (contrived) example above, application of the operation to the servers in the domain would be
done in 3 phases. If the policy for any server group triggers a rollback of the operation across the server
group, all other server groups will be rolled back as well. The 3 phases are:
WildFly 9
1. Server groups groupA and groupB will have the operation applied concurrently. The operation will be
applied to the servers in groupA in series, while all servers in groupB will handle the operation
concurrently. If more than 20% of the servers in groupA fail to apply the operation, it will be rolled
back across that group. If any servers in groupB fail to apply the operation it will be rolled back across
that group.
2. Once all servers in groupA and groupB are complete, the operation will be applied to the servers in
groupC. Those servers will handle the operation concurrently. If more than one server in groupC fails
to apply the operation it will be rolled back across that group.
3. Once all servers in groupC are complete, server groups groupD and groupE will have the operation
applied concurrently. The operation will be applied to the servers in groupD in series, while all servers
in groupE will handle the operation concurrently. If more than 20% of the servers in groupD fail to
apply the operation, it will be rolled back across that group. If any servers in groupE fail to apply the
operation it will be rolled back across that group.
WildFly 9
This will create a rollout plan called simple in the content repository.
[domain@192.168.1.20:9999 /]
/management-client-content=rollout-plans/rollout-plan=simple:read-resource
{
"outcome" => "success",
"result" => {
"content" => {"rollout-plan" => {
"in-series" => [
{"server-group" => {"main-server-group" => {
"rolling-to-servers" => false,
"max-failed-servers" => 1
}}},
{"server-group" => {"other-server-group" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
}}}
],
"rollback-across-groups" => true
}},
"hash" => bytes {
0x13, 0x12, 0x76, 0x65, 0x8a, 0x28, 0xb8, 0xbc,
0x34, 0x3c, 0xe9, 0xe6, 0x9f, 0x24, 0x05, 0xd2,
0x30, 0xff, 0xa4, 0x34
}
}
}
Now you may reference the roolout plan in your command by adding a header just like this :
WildFly 9
where the return value is the detyped representation of the response, and operation is the detyped
representation of the operating being invoked.
The purpose of this section is to document the structure of the return value.
For the format of the request, see Format of a Detyped Operation Request.
Simple Responses
Simple responses are provided by the following types of operations:
Non-composite operations that target a single server. (See below for more on composite operations).
Non-composite operations that target a Domain Controller or slave Host Controller and don't require
the responder to apply the operation on multiple servers and aggregate their results (e.g. a simple
read of a domain configuration property.)
The response will always include a simple boolean outcome field, with one of three possible values:
success the operation executed successfully
failed the operation failed
cancelled the execution of the operation was cancelled. (This would be an unusual outcome for a
simple operation which would generally very rapidly reach a point in its execution where it couldn't be
cancelled.)
The other fields in the response will depend on whether the operation was successful.
The response for a failed operation:
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message"
}
{
"outcome" => "success",
"result" => {
"name" => "Brian",
"age" => 22
}
}
WildFly 9
A void result:
{
"outcome" => "success",
"result" => undefined
}
{
"outcome" => "cancelled"
}
WildFly 9
Response Headers
Besides the standard outcome, result and failure-description fields described above, the
response may also include various headers that provide more information about the affect of the operation or
about the overall state of the server. The headers will be child element under a field named
response-headers. For example:
{
"outcome" => "success",
"result" => undefined,
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}
A response header is typically related to whether an operation could be applied to the targeted runtime
without requiring a restart of some or all services, or even of the target process itself. Please see the
"Applying Updates to Runtime Services" section of the Description of the Management Model section for a
discussion of the basic concepts related to what happens if an operation requires a service restart to be
applied.
The current possible response headers are:
operation-requires-reload boolean indicates that the specific operation that has generated
this response requires a restart of all services in the process in order to take effect in the runtime. This
would typically only have a value of 'true'; the absence of the header is the same as a value of 'false.'
operation-requires-restart boolean indicates that the specific operation that has
generated this response requires a full process restart in order to take effect in the runtime. This
would typically only have a value of 'true'; the absence of the header is the same as a value of 'false.'
process-state enumeration Provides information about the overall state of the target process.
One of the following values:
starting the process is starting
running the process is in a normal running state. The process-state header would
typically not be seen with this value; the absence of the header is the same as a value of
'running'.
reload-required some operation (not necessarily this one) has executed that requires a
restart of all services in order for a configuration change to take effect in the runtime.
restart-required some operation (not necessarily this one) has executed that requires a
full process restart in order for a configuration change to take effect in the runtime.
stopping the process is stopping
WildFly 9
{
"outcome" => "cancelled"
}
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
}
An individual operation that itself succeeded but was rolled back due to failure of another operation:
WildFly 9
{
"outcome" => "failed",
"result" => {
"name" => "Brian",
"age" => 22
},
"rolled-back" => true
}
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
}
{
"outcome" => "success",
"result" => [
{
"outcome" => "success",
"result" => {
"name" => "Brian",
"age" => 22
}
},
{
"outcome" => "success",
"result" => undefined
}
]
}
And for a failed 3 step composite operation, where the first step succeeded and the second failed, triggering
cancellation of the 3rd and rollback of the others:
WildFly 9
{
"outcome" => "failed",
"failure-description" => "[JBAS-99999] Composite operation failed; see individual operation
results for details",
"result" => [
{
"outcome" => "failed",
"result" => {
"name" => "Brian",
"age" => 22
},
"rolled-back" => true
},
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
},
{
"outcome" => "cancelled"
}
]
}
Multi-Server Responses
Multi-server responses are provided by operations that target a Domain Controller or slave Host Controller
and require the responder to apply the operation on multiple servers and aggregate their results (e.g. nearly
all domain or host configuration updates.)
Multi-server operations are executed in several stages.
First, the operation may need to be applied against the authoritative configuration model maintained by the
Domain Controller (for domain.xml confgurations) or a Host Controller (for a host.xml configuration). If
there is a failure at this stage, the operation is automatically rolled back, with a response like this:
{
"outcome" => "failed",
"domain-failure-description" => "[JBAS-33333] Failed to apply X to the domain model"
}
If the operation was addressed to the domain model, in the next stage the Domain Controller will ask each
slave Host Controller to apply it to its local copy of the domain model. If any Host Controller fails to do so, the
Domain Controller will tell all Host Controllers to revert the change, and it will revert the change locally as
well. The response to the client will look like this:
WildFly 9
{
"outcome" => "failed",
"host-failure-descriptions" => {
"hostA" => "[DOM-3333] Failed to apply to the domain model",
"hostB" => "[DOM-3333] Failed to apply to the domain model"
}
}
If the preceding stages succeed, the operation will be pushed to all affected servers. If the operation is
successful on all servers, the response will look like this (this example operation has a void response, hence
the result for each server is undefined):
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
}
}
}
WildFly 9
The operation need not succeed on all servers in order to get an "outcome" => "success" result. All
that is required is that it succeed on at least one server without the rollback policies in the rollout plan
triggering a rollback on that server. An example response in such a situation would look like this:
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-3" => {
"host" => "host3",
"response" => {
"outcome" => "failed",
"failure-description" => "[DOM-4556] Something didn't work right",
"rolled-back" => true
}
}
}
}
}
Finally, if the operation fails or is rolled back on all servers, an example response would look like this:
WildFly 9
{
"outcome" => "failed",
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "failed",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "failed",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-3" => {
"host" => "host3",
"response" => {
"outcome" => "failed",
"failure-description" => "[DOM-4556] Something didn't work right",
"rolled-back" => true
}
}
}
}
}
WildFly 9
WildFly 9
{
"description => "A manageable resource",
"tail-comment-allowed" => false,
"attributes" => {
"foo" => {
.... details of attribute foo
}
},
"operations" => {
"start" => {
.... details of the start operation
}
},
"children" => {
"bar" => {
.... details of the relationship with children of type "bar"
}
}
}
Description of an Attribute
An attribute is a portion of the management model that is not directly addressable. Instead, it is conceptually
a property of an addressable management resource. For each attribute in the model, the following
descriptive information will be available:
description String text description of the attribute
type org.jboss.dmr.ModelType the type of the attribute value. One of the enum values
BIG_DECIMAL, BIG_INTEGER, BOOLEAN, BYTES, DOUBLE, INT, LIST, LONG, OBJECT,
PROPERTY, STRING. Most of these are self-explanatory. An OBJECT will be represented in the
detyped model as a map of string keys to values of some other legal type, conceptually similar to a
javax.management.openmbean.CompositeData. A PROPERTY is a single key/value pair,
where the key is a string, and the value is of some other legal type.
value-type ModelType or complex structure Only present if type is LIST or OBJECT. If all
elements in the LIST or all the values of the OBJECT type are of the same type, this will be one of the
ModelType enums BIG_DECIMAL, BIG_INTEGER, BOOLEAN, BYTES, DOUBLE, INT, LONG,
STRING. Otherwise, value-type will detail the structure of the attribute value, enumerating the
value's fields and the type of their value.
expressions-allowed boolean indicates whether the value of the attribute may be of type
ModelType.EXPRESSION, instead of its standard type (see type and value-type above for
discussion of an attribute's standard type.) A value of ModelType.EXPRESSION contains a
system-property substitution expression that the server will resolve against the server-side system
property map before using the value. For example, an attribute named max-threads may have an
expression value of ${example.pool.max-threads:10} instead of just 10. Default value if not
present is false.
required boolean true if the attribute will always exist in a representation of its portion of the
model; false if it may not (implying a null value.) If not present, true is the default.
WildFly 9
storage String Either "configuration" or "runtime". If "configuration", the attribute's value is stored
as part of the persistent configuration (e.g. in domain.xml, host.xml or standalone.xml.) If "runtime" the
attribute's value is not stored in the persistent configuration; the value only exists as long as the
resource is running.
access-type String One of "read-only", "read-write" or "metric". Whether an attribute value can
be written, or can only read. A "metric" is a read-only attribute whose value is not stored in the
persistent configuration, and whose value may change due to activity on the server. If an attribute is
"read-write", the resource will expose an operation named "write-attribute" whose "name" parameter
will accept this attribute's name and whose "value" parameter will accept a valid value for this
attribute. That operation will be the standard means of updating this attribute's value.
restart-required String One of "no-services", "all-services", "resource-services" or "jvm".
Only relevant to attributes whose access-type is read-write. Indicates whether execution of a
write-attribute operation whose name parameter specifies this attribute requires a restart of services
(or an entire JVM) in order for the change to take effect in the runtime . See discussion of "Applying
Updates to Runtime Services" below. Default value is "no-services".
alternatives List of string Indicates an exclusive relationship between attributes. If this
attribute is defined, the other attributes listed in this descriptor's value should be undefined (even if
their required descriptor says true; i.e. the presence of this attribute satisfies the requirement.) Default
is undefined; i.e. this does not apply to most attributes.
requires List of string Indicates that if this attribute has a value (other than undefined), the other
attributes listed in this descriptor's value must also have a value, even if their required descriptor says
false. This would typically be used in conjunction with alternatives. For example, attributes "a" and "b"
are required, but are alternatives to each other; "c" and "d" are optional. But "b" requires "c" and "d",
so if "b" is used, "c" and "d" must also be defined. Default is undefined; i.e. this does not apply to most
attributes.
head-comment-allowed boolean indicates whether the model can store an XML comment that
would be written in the persistent form of the model (e.g. domain.xml) before the start of the XML
element that represents this attribute. This item is optional, and if not present defaults to false. (This is
a different default from what is used for an entire management resource, since model attributes often
map to XML attributes, which don't allow comments.) (Note: storing XML comments in the in-memory
model is not currently supported. This description key is for future use.)
tail-comment-allowed boolean similar to head-comment-allowed, but indicates whether a
comment just before the close of the XML element is supported. A tail comment can only be
supported if the element has child elements, in which case a comment can be inserted between the
final child element and the element's closing tag. This item is optional, and if not present defaults to
false. (This is a different default from what is used for an entire management resource, since model
attributes often map to XML attributes, which don't allow comments.) (Note: storing XML comments in
the in-memory model is not currently supported. This description key is for future use.)
arbitrary key/value pairs that further describe the attribute value, e.g. "max" => 2. See "Arbitrary
Descriptors" below.
Some examples:
WildFly 9
"foo" => {
"description" => "The foo",
"type" => INT,
"max" => 2
}
"bar" => {
"description" => "The bar",
"type" => OBJECT,
"value-type" => {
"size" => INT,
"color" => STRING
}
}
Description of an Operation
A management resource may have operations associated with it. The description of an operation will include
the following information:
operation-name String the name of the operation
description String text description of the operation
request-properties Map of String to complex structure description of the parameters of the
operation. Keys are the names of the parameters, values are descriptions of the parameter value
types. See below for details on the description of parameter value types.
reply-properties complex structure, or empty description of the return value of the operation,
with an empty node meaning void. See below for details on the description of operation return value
types.
restart-required String One of "no-services", "all-services", "resource-services" or "jvm".
Indicates whether the operation makes a configuration change that requires a restart of services (or
an entire JVM) in order for the change to take effect in the runtime. See discussion of "Applying
Updates to Runtime Services" below. Default value is "no-services".
WildFly 9
Arbitrary Descriptors
The description of an attribute, operation parameter or operation return value type can include arbitrary
key/value pairs that provide extra information. Whether a particular key/value pair is present depends on the
context, e.g. a pair with key "max" would probably only occur as part of the description of some numeric
type.
WildFly 9
Following are standard keys and their expected value type. If descriptor authors want to add an arbitrary
key/value pair to some descriptor and the semantic matches the meaning of one of the following items, the
standard key/value type must be used.
min int the minimum value of some numeric type. The absence of this item implies there is no
minimum value.
max int the maximum value of some numeric type. The absence of this item implies there is no
maximum value.
min-length int the minimum length of some string, list or byte[] type. The absence of this item
implies a minimum length of zero.
max-length int the maximum length of some string, list or byte[]. The absence of this item
implies there is no maximum value.
nillable boolean whether null or a ModelNode of type ModelType.UNDEFINED is a legal
value. The absence of this item implies false; i.e. null/undefined is not a legal value.
allowed List a list of legal values. The type of the elements in the list should match the type of
the attribute.
default the default value for the attribute if not present in the model
unit - The unit of the value, if one is applicable - e.g. ns, ms, s, m, h, KB, MB, TB. See the
org.jboss.as.controller.client.helpers.MeasurementUnit in the
org.jboss.as:jboss-as-controller-client artifact for a listing of legal measurement units..
Some examples:
{
"operation-name" => "incrementFoo",
"description" => "Increase the value of the 'foo' attribute by the given amount",
"request-properties" => {
"increment" => {
"type" => INT,
"description" => "The amount to increment",
"required" => true
}},
"reply-properties" => {
"type" => INT,
"description" => "The new value",
}
}
{
"operation-name" => "start",
"description" => "Starts the thing",
"request-properties" => {},
"reply-properties" => {}
}
WildFly 9
{
....
"children" => {
"connector" => {
.... description of the relationship with children of type "connector"
},
"virtual-host" => {
.... description of the relationship with children of type "virtual-host"
}
}
WildFly 9
{
"description" => "The connectors used to handle client connections",
"min-occurs" > 1,
"model-description" => {
"description" => "Handles client connections",
"attributes => {
... details of children as documented above
},
"operations" => {
.... details of operations as documented above
},
"children" => {
.... details of the children's children
}
}
}
{
"description" => "The connectors used to handle client connections",
"min-occurs" > 1,
"model-description" => undefined
}
WildFly 9
Because restarting a service can be disruptive to end-user request handling, the handlers for management
operations will not restart any service without some form of explicit instruction from the end user indicating a
service restart is desired. In a few cases, simply executing the operation is an indication the user wants
services to restart (e.g. a /host=master/server-config=server-one:restart operation in a
managed domain, or a /:reload operation on a standalone server.) For all other cases, if an operation (or
attribute write) cannot be performed without restarting a service, the metadata describing the operation or
attribute will include a "restart-required" descriptor whose value indicates what is necessary for the
operation to affect the runtime:
no-services Applying the operation to the runtime does not require the restart of any services.
This value is the default if the restart-required descriptor is not present.
all-services The operation can only immediately update the persistent configuration; applying
the operation to the runtime will require a subsequent restart of all services in the affected VM.
Executing the operation will put the server into a "reload-required" state. Until a restart of all
services is performed the response to this operation and to any subsequent operation will include a
response header "process-state" => "reload-required". For a standalone server, a restart
of all services can be accomplished by executing the /:reload CLI command. For a server in a
managed domain, restarting all services currently requires a full restart of the affected server VM (e.g.
/host=master/server-config=server-one:restart).
jvm --The operation can only immediately update the persistent configuration; applying the operation
to the runtime will require a full process restart (i.e. stop the JVM and launch a new JVM). Executing
the operation will put the server into a "restart-required" state. Until a restart is performed the
response to this operation and to any subsequent operation will include a response header "
process-state" => "restart-required". For a standalone server, a full process restart
requires first stopping the server via OS-level operations (Ctrl-C, kill) or via the /:shutdown CLI
command, and then starting the server again from the command line. For a server in a managed
domain, restarting a server requires executing the
/host=<host>/server-config=<server>:restart operation.
resource-services The operation can only immediately update the persistent configuration;
applying the operation to the runtime will require a subsequent restart of some services associated
with the resource. If the operation includes the request header
"allow-resource-service-restart" => true, the handler for the operation will go ahead
and restart the runtime service. Otherwise executing the operation will put the server into a "
reload-required" state. (See the discussion of "all-services" above for more on the "
reload-required" state.)
WildFly 9
WildFly 9
Next, create a ModelNode and use the beanshell print function to output what type it is:
bsh % node.set(1);
bsh % print(node.getType());
INT
bsh % node.set(true);
bsh % print(node.getType());
BOOLEAN
bsh % node.set("Hello, world");
bsh % print(node.getType());
STRING
bsh % node.set(2);
bsh % print(node.asInt());
2
bsh % node.set("A string");
bsh % print(node.asString());
A string
ModelNode will attempt to perform type conversions when you invoke the asXXX methods:
WildFly 9
bsh %
bsh %
1
bsh %
true
bsh %
bsh %
false
bsh %
bsh %
true
node.set(1);
print(node.asString());
print(node.asBoolean());
node.set(0);
print(node.asBoolean());
node.set("true");
print(node.asBoolean());
The ModelNode.getType() method can be used to ensure a node has an expected value type before
attempting a type conversion.
One set variant takes another ModelNode as its argument. The value of the passed in node is copied, so
there is no shared state between the two model nodes:
A ModelNode can be cloned. Again, there is no shared state between the original node and its clone:
WildFly 9
bsh % clone.protect();
bsh % clone.set("A different string");
// Error: // Uncaught Exception: Method Invocation clone.set : at Line: 15 : in file: <unknown
file> : clone .set ( "A different string" )
Target exception: java.lang.UnsupportedOperationException
java.lang.UnsupportedOperationException
at org.jboss.dmr.ModelNode.checkProtect(ModelNode.java:1441)
at org.jboss.dmr.ModelNode.set(ModelNode.java:351)
....
Lists
The above examples aren't particularly interesting; if all we can do with a ModelNode is wrap a simple Java
primitive, what use is that? However, a ModelNode's value can be more complex than a simple primitive,
and using these more complex types we can build complex data structures. The first more complex type is
ModelType.LIST.
Use the add methods to initialize a node's value as a list and add to the list:
bsh %
bsh %
bsh %
bsh %
LIST
bsh % print(list.asInt());
2
Use the overloaded get method variant that takes an int param to retrieve an item. The item is returned as a
ModelNode:
WildFly 9
Here's one of the trickiest things about jboss-dmr: The get methods actually mutate state; they are not
"read-only". For example, calling get with an index that does not exist yet in the list will actually create a
child of type ModelType.UNDEFINED at that index (and will create UNDEFINED children for any
intervening indices.)
Since the get call always returns a ModelNode and never null it is safe to manipulate the return value:
bsh % list.get(5).set(30);
bsh % print(list.get(5).asInt());
30
That's not so interesting in the above example, but later on with node of type ModelType.OBJECT we'll see
how that kind of method chaining can let you build up fairly complex data structures with a minimum of code.
Use the asList() method to get a List<ModelNode> of the children:
The asString() and toString() methods provide slightly differently formatted text representations of a
ModelType.LIST node:
WildFly 9
bsh % print(list.asString());
[5,10,"A string",undefined,undefined,30]
bsh % print(list.toString());
[
5,
10,
"A string",
undefined,
undefined,
30
]
Finally, if you've previously used set to assign a node's value to some non-list type, you cannot use the add
method:
bsh % node.add(5);
// Error: // Uncaught Exception: Method Invocation node.add : at Line: 18 : in file: <unknown
file> : node .add ( 5 )
Target exception: java.lang.IllegalArgumentException
java.lang.IllegalArgumentException
at org.jboss.dmr.ModelValue.addChild(ModelValue.java:120)
at org.jboss.dmr.ModelNode.add(ModelNode.java:1007)
at org.jboss.dmr.ModelNode.add(ModelNode.java:761)
...
You can, however, use the setEmptyList() method to change the node's type, and then use add:
bsh % node.setEmptyList();
bsh % node.add(5);
bsh % print(node.toString());
[5]
Properties
The third public class in the jboss-dmr library is org.jboss.dmr.Property. A Property is a String =>
ModelNode tuple.
WildFly 9
bsh % node.set(prop);
bsh % print(node.getType());
PROPERTY
bsh % print(node.toString());
("stuff" => [
5,
10,
"A string",
undefined,
undefined,
30
])
Directly instantiating a Property via its constructor is not common. More typically one of the two argument
ModelNode.add or ModelNode.set variants is used. The first argument is the property name:
WildFly 9
ModelType.OBJECT
The most powerful and most commonly used complex value type in jboss-dmr is ModelType.OBJECT. A
ModelNode whose value is ModelType.OBJECT internally maintains a Map<String, ModelNode.
Use the get method variant that takes a string argument to add an entry to the map. If no entry exists under
the given name, a new entry is added with a the value being a ModelType.UNDEFINED node. The node is
returned:
Again it is important to remember that the get operation may mutate the state of a model node by
adding a new entry. It is not a read-only operation.
Since get will never return null, a common pattern is to use method chaining to create the key/value pair:
WildFly 9
bsh % range.get("max").set(10);
bsh % print(range.toString());
{
"min" => 2,
"max" => 10
}
A call to get passing an already existing key will of course return the same model node as was returned the
first time get was called with that key:
Multiple parameters can be passed to get. This is a simple way to traverse a tree made up of
ModelType.OBJECT nodes. Again, get may mutate the node on which it is invoked; e.g. it will actually
create the tree if nodes do not exist. This next example uses a workaround to get beanshell to handle the
overloaded get method that takes a variable number of arguments:
bsh %
bsh %
bsh %
{"US"
The semantics of the backing map in a node of ModelType.OBJECT are those of a LinkedHashMap. The
map remembers the order in which key/value pairs are added. This is relevant when iterating over the pairs
after calling asPropertyList() and for controlling the order in which key/value pairs appear in the output
from toString().
Since the get method will actually mutate the state of a node if the given key does not exist, ModelNode
provides a couple methods to let you check whether the entry is there. The has method simply does that:
WildFly 9
bsh % print(range.has("unit"));
false
bsh % print(range.has("min"));
true
Very often, the need is to not only know whether the key/value pair exists, but whether the value is defined
(i.e. not ModelType.UNDEFINED. This kind of check is analogous to checking whether a field in a Java
class has a null value. The hasDefined lets you do this:
bsh % print(range.hasDefined("unit"));
false
bsh % // Establish an undefined child 'unit';
bsh % range.get("unit");
bsh % print(range.toString());
{
"min" => 2,
"max" => 10,
"unit" => undefined
}
bsh % print(range.hasDefined("unit"));
false
bsh % range.get("unit").set("meters");
bsh % print(range.hasDefined("unit"));
true
ModelType.EXPRESSION
A value of type ModelType.EXPRESSION is stored as a string, but can later be resolved to different value.
The string has a special syntax that should be familiar to those who have used the system property
substitution feature in previous JBoss AS releases.
[<prefix>][${<system-property-name>[:<default-value>]}][<suffix>]*
For example:
${queue.length}
http://${host}
http://${host:localhost}:${port:8080}/index.html
WildFly 9
bsh % print(expression.asString());
${queue.length}
However, calling toString() tells you that this node's value is not of ModelType.STRING:
bsh % print(expression.toString());
expression "${queue.length}"
When the resolve operation is called, the string is parsed and any embedded system properties are
resolved against the JVM's current system property values. A new ModelNode is returned whose value is
the resolved string:
bsh % print(resolved.getType());
STRING
The resolved.asInt() call in the previous example only worked because the string "10" happens to be
convertible into the int 10.
Calling resolve() has no effect on the value of the node on which the method is invoked:
If an expression cannot be resolved, resolve just uses the original string. The string can include more than
one system property substitution:
bsh % expression.setExpression("http://${host}:${port}/index.html");
bsh % resolved = expression.resolve();
bsh % print(resolved.asString());
http://${host}:${port}/index.html
The expression can optionally include a default value, separated from the name of the system property by a
colon:
WildFly 9
bsh % expression.setExpression("http://${host:localhost}:${port:8080}/index.html");
bsh % resolved = expression.resolve();
bsh % print(resolved.asString());
http://localhost:8080/index.html
The resolve method works on nodes of other types as well; it returns a copy without attempting any real
resolution:
bsh
bsh
bsh
bsh
INT
bsh
bsh
5
bsh
10
%
%
%
%
% resolved.set(5);
% print(resolved.asInt());
% print(basic.asInt());
ModelType.TYPE
You can also pass one of the values of the ModelType enum to set:
bsh %
bsh %
bsh %
TYPE
bsh %
LIST
This is useful when using a ModelNode data structure to describe another ModelNode data structure.
WildFly 9
WildFly 9
WildFly 9
WildFly 9
WildFly 9
Standard Operations
Besides the global operations described above, by convention nearly every resource should expose an add
operation and a remove operation. Exceptions to this convention are the root resource, and resources that
do not store persistent configuration and are created dynamically at runtime (e.g. resources representing the
JVM's platform mbeans or resources representing aspects of the running state of a deployment.)
WildFly 9
http://localhost:9990/management?operation=attribute&name=server-state&json.pretty=1
WildFly 9
http://localhost:9990/management?operation=attribute&name=server-state&json.pretty=1
Using POST
Here's an example of an operation on a resource with a nested address and passed parameters. This
is same as if you would run /host=master/server=server-01:read-attribute(name=server-state)
WildFly 9
Following example will get us information from http connection in undertow subsystem including
run-time attributes
This is the same as running
/subsystem=undertow/server=default-server:read-resource(include-runtime=true,recursive=true) in
CLI
Using GET
http://localhost:9990/management/subsystem/undertow/server/default-server?operation=resource&recur
"default-host" : "default-host",
"servlet-container" : "default",
"ajp-listener" : null,
"host" : {"default-host" : {
"alias" : ["localhost"],
"default-web-module" : "ROOT.war",
"filter-ref" : {
"server-header" : {"predicate" : null},
"x-powered-by-header" : {"predicate" : null}
},
"location" : {"/" : {
"handler" : "welcome-content",
"filter-ref" : null
}},
"setting" : null
}},
"http-listener" : {"default" : {
"allow-encoded-slash" : false,
"allow-equals-in-cookie-value" : false,
"always-set-keep-alive" : true,
"buffer-pipelined-data" : true,
"buffer-pool" : "default",
"certificate-forwarding" : false,
"decode-url" : true,
"enabled" : true,
"max-buffered-request-size" : 16384,
"max-cookies" : 200,
"max-header-size" : 51200,
"max-headers" : 200,
"max-parameters" : 1000,
"max-post-size" : 10485760,
"proxy-address-forwarding" : false,
"read-timeout" : null,
"receive-buffer" : null,
"record-request-start-time" : false,
"redirect-socket" : "https",
"send-buffer" : null,
"socket-binding" : "http",
"tcp-backlog" : null,
"tcp-keep-alive" : null,
"url-charset" : "UTF-8",
"worker" : "default",
"write-timeout" : null
}},
"https-listener" : null
}
WildFly 9
Using POST
WildFly 9
"proxy-address-forwarding" : false,
"read-timeout" : null,
"receive-buffer" : null,
"record-request-start-time" : false,
"redirect-socket" : "https",
"send-buffer" : null,
"socket-binding" : "http",
"tcp-backlog" : null,
"tcp-keep-alive" : null,
"url-charset" : "UTF-8",
"worker" : "default",
"write-timeout" : null
}},
"https-listener" : null
}
}
You may also used some encoded DMR but the result won't be human readable
WildFly 9
The CLI tool that comes with the application server uses this interface, and user can develop custom clients
that use it as well. In this section we'll cover the basics on how to develop such a client. We'll also cover
details on the format of low-level management operation requests and responses information that should
prove useful for users of the CLI tool as well.
WildFly 9
Purpose
org.jboss.remoting:jboss-remoting
Remote communication
org.jboss:jboss-dmr
org.jboss.as:jboss-as-protocol
org.jboss.sasl:jboss-sasl
SASL authentication
org.jboss.xnio:xnio-api
Non-blocking IO
org.jboss.xnio:xnio-nio
Non-blocking IO
org.jboss.logging:jboss-logging
Logging
org.jboss.threads:jboss-threads
Thread management
WildFly 9
ModelControllerClient client =
ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9999);
The address and port are what is configured in the target process'
<management><management-interfaces><native-interface.../> element.
Typically, however, the native management interface will be secured, requiring clients to authenticate. On
the client side, the custom client will need to provide the user's authentication credentials, obtained in
whatever manner is appropriate for the client (e.g. from a dialog box in a GUI-based client.) Access to these
credentials is provided by passing in an implementation of the
javax.security.auth.callback.CallbackHandler interface. For example:
WildFly 9
What we've done here is created a ModelNode of type ModelType.OBJECT with the following fields:
operation the name of the operation to invoke. All operation requests must include this field and
its value must be a String.
address the address of the resource to invoke the operation against. This field's must be of
ModelType.LIST with each element in the list being a ModelType.PROPERTY. If this field is
omitted the operation will target the root resource. The operation can be targeted at any address in
the management model; here we are targeting it at the resource for the web subsystem's http
connector.
In this case, the request includes two optional parameters:
recursive true means you want the description of child resources under this resource. Default is
false
operations true means you want the description of operations exposed by the resource to be
included. Default is false.
Different operations take different parameters, and some take no parameters at all.
See Format of a Detyped Operation Request for full details on the structure of a ModelNode that will
represent an operation request.
The example above produces an operation request ModelNode equivalent to what the CLI produces
internally when it parses and executes the following low-level CLI command:
[localhost:9999 /]
/subsystem=web/connector=http:read-resource-description(recursive=true,operations=true)
WildFly 9
See Format of a Detyped Operation Response for general details on the structure of the "returnVal"
ModelNode.
The execute operation shown above will block the calling thread until the response is received from the
process being managed. ModelControllerClient also exposes and API allowing asynchronous
invocation:
client.close();
where the return value is the detyped representation of the response, and operation is the detyped
representation of the operation being invoked.
The purpose of this section is to document the structure of operation.
See Format of a Detyped Operation Response for a discussion of the format of the response.
WildFly 9
Simple Operations
A text representation of simple operation would look like this:
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20
}
The order in which the outermost elements appear in the request is not relevant. The required elements are:
operation String The name of the operation being invoked.
address the address of the managed resource against which the request should be executed. If
not set, the address is the root resource. The address is an ordered list of key-value pairs describing
where the resource resides in the overall management resource tree. Management resources are
organized in a tree, so the order in which elements in the address occur is important.
The other key/value pairs are parameter names and their values. The names and values should match what
is specified in the operation's description.
Parameters may have any name, except for the reserved words operation, address and
operation-headers.
Operation Headers
Besides the special operation and address values discussed above, operation requests can also include
special "header" values that help control how the operation executes. These headers are created under the
special reserved word operation-headers:
WildFly 9
This produces:
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20,
"operation-headers" => {
"rollback-on-runtime-failure => false
}
}
WildFly 9
WildFly 9
Composite Operations
The root resource for a Domain or Host Controller or an individual server will expose an operation named "
composite". This operation executes a list of other operations as an atomic unit (although the atomicity
requirement can be relaxed. The structure of the request for the "composite" operation has the same
fundamental structure as a simple operation (i.e. operation name, address, params as key value pairs).
{
"operation" => "composite",
"address" => [],
"steps" => [
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"count" => "count",
"value" => 20
},
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool2")
],
"name" => "count",
"value" => 10
}
],
"operation-headers" => {
"rollback-on-runtime-failure => false
}
}
The rollback-on-runtime-failure operation header discussed above has a particular meaning when
applied to a composite operation, controlling whether steps that successfully execute should be reverted if
other steps fail at runtime. Note that if any steps modify the persistent configuration, and any of those steps
fail, all steps will be reverted. Partial/incomplete changes to the persistent configuration are not allowed.
WildFly 9
{
"operation" => "write-attribute",
"address" => [
("profile" => "production"),
("subsystem" => "threads"),
("bounded-queue-thread-pool" => "pool1")
],
"name" => "count",
"value" => 20,
"operation-headers" => {
"rollout-plan" => {
"in-series" => [
{
"concurrent-groups" => {
"groupA" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
},
"groupB" => undefined
}
},
{
"server-group" => {
"groupC" => {
"rolling-to-servers" => false,
"max-failed-servers" => 1
}
}
},
{
"concurrent-groups" => {
"groupD" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
},
"groupE" => undefined
}
}
],
"rollback-across-groups" => true
}
}
}
WildFly 9
As you can see, the rollout plan is another structure in the operation-headers section. The root node of the
structure allows two children:
in-series a list A list of activities that are to be performed in series, with each activity reaching
completion before the next step is executed. Each activity involves the application of the operation to
the servers in one or more server groups. See below for details on each element in the list.
rollback-across-groups boolean indicates whether the need to rollback the operation on all
the servers in one server group should trigger a rollback across all the server groups. This is an
optional setting, and defaults to false.
Each element in the list under the in-series node must have one or the other of the following structures:
concurrent-groups a map of server group names to policies controlling how the operation
should be applied to that server group. For each server group in the map, the operation may be
applied concurrently. See below for details on the per-server-group policy configuration.
server-group a single key/value mapping of a server group name to a policy controlling how the
operation should be applied to that server group. See below for details on the policy configuration.
(Note: there is no difference in plan execution between this and a "concurrent-groups" map with a
single entry.)
The policy controlling how the operation is applied to the servers within a server group has the following
elements, each of which is optional:
rolling-to-servers boolean If true, the operation will be applied to each server in the group
in series. If false or not specified, the operation will be applied to the servers in the group
concurrently.
max-failed-servers int Maximum number of servers in the group that can fail to apply the
operation before it should be reverted on all servers in the group. The default value if not specified is
zero; i.e. failure on any server triggers rollback across the group.
max-failure-percentage int between 0 and 100 Maximum percentage of the total number of
servers in the group that can fail to apply the operation before it should be reverted on all servers in
the group. The default value if not specified is zero; i.e. failure on any server triggers rollback across
the group.
If both max-failed-servers and max-failure-percentage are set, max-failure-percentage
takes precedence.
Looking at the (contrived) example above, application of the operation to the servers in the domain would be
done in 3 phases. If the policy for any server group triggers a rollback of the operation across the server
group, all other server groups will be rolled back as well. The 3 phases are:
WildFly 9
1. Server groups groupA and groupB will have the operation applied concurrently. The operation will be
applied to the servers in groupA in series, while all servers in groupB will handle the operation
concurrently. If more than 20% of the servers in groupA fail to apply the operation, it will be rolled
back across that group. If any servers in groupB fail to apply the operation it will be rolled back across
that group.
2. Once all servers in groupA and groupB are complete, the operation will be applied to the servers in
groupC. Those servers will handle the operation concurrently. If more than one server in groupC fails
to apply the operation it will be rolled back across that group.
3. Once all servers in groupC are complete, server groups groupD and groupE will have the operation
applied concurrently. The operation will be applied to the servers in groupD in series, while all servers
in groupE will handle the operation concurrently. If more than 20% of the servers in groupD fail to
apply the operation, it will be rolled back across that group. If any servers in groupE fail to apply the
operation it will be rolled back across that group.
WildFly 9
This will create a rollout plan called simple in the content repository.
[domain@192.168.1.20:9999 /]
/management-client-content=rollout-plans/rollout-plan=simple:read-resource
{
"outcome" => "success",
"result" => {
"content" => {"rollout-plan" => {
"in-series" => [
{"server-group" => {"main-server-group" => {
"rolling-to-servers" => false,
"max-failed-servers" => 1
}}},
{"server-group" => {"other-server-group" => {
"rolling-to-servers" => true,
"max-failure-percentage" => 20
}}}
],
"rollback-across-groups" => true
}},
"hash" => bytes {
0x13, 0x12, 0x76, 0x65, 0x8a, 0x28, 0xb8, 0xbc,
0x34, 0x3c, 0xe9, 0xe6, 0x9f, 0x24, 0x05, 0xd2,
0x30, 0xff, 0xa4, 0x34
}
}
}
Now you may reference the roolout plan in your command by adding a header just like this :
WildFly 9
where the return value is the detyped representation of the response, and operation is the detyped
representation of the operating being invoked.
The purpose of this section is to document the structure of the return value.
For the format of the request, see Format of a Detyped Operation Request.
Simple Responses
Simple responses are provided by the following types of operations:
Non-composite operations that target a single server. (See below for more on composite operations).
Non-composite operations that target a Domain Controller or slave Host Controller and don't require
the responder to apply the operation on multiple servers and aggregate their results (e.g. a simple
read of a domain configuration property.)
The response will always include a simple boolean outcome field, with one of three possible values:
success the operation executed successfully
failed the operation failed
cancelled the execution of the operation was cancelled. (This would be an unusual outcome for a
simple operation which would generally very rapidly reach a point in its execution where it couldn't be
cancelled.)
The other fields in the response will depend on whether the operation was successful.
The response for a failed operation:
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message"
}
{
"outcome" => "success",
"result" => {
"name" => "Brian",
"age" => 22
}
}
WildFly 9
A void result:
{
"outcome" => "success",
"result" => undefined
}
{
"outcome" => "cancelled"
}
WildFly 9
Response Headers
Besides the standard outcome, result and failure-description fields described above, the
response may also include various headers that provide more information about the affect of the operation or
about the overall state of the server. The headers will be child element under a field named
response-headers. For example:
{
"outcome" => "success",
"result" => undefined,
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}
A response header is typically related to whether an operation could be applied to the targeted runtime
without requiring a restart of some or all services, or even of the target process itself. Please see the
"Applying Updates to Runtime Services" section of the Description of the Management Model section for a
discussion of the basic concepts related to what happens if an operation requires a service restart to be
applied.
The current possible response headers are:
operation-requires-reload boolean indicates that the specific operation that has generated
this response requires a restart of all services in the process in order to take effect in the runtime. This
would typically only have a value of 'true'; the absence of the header is the same as a value of 'false.'
operation-requires-restart boolean indicates that the specific operation that has
generated this response requires a full process restart in order to take effect in the runtime. This
would typically only have a value of 'true'; the absence of the header is the same as a value of 'false.'
process-state enumeration Provides information about the overall state of the target process.
One of the following values:
starting the process is starting
running the process is in a normal running state. The process-state header would
typically not be seen with this value; the absence of the header is the same as a value of
'running'.
reload-required some operation (not necessarily this one) has executed that requires a
restart of all services in order for a configuration change to take effect in the runtime.
restart-required some operation (not necessarily this one) has executed that requires a
full process restart in order for a configuration change to take effect in the runtime.
stopping the process is stopping
WildFly 9
{
"outcome" => "cancelled"
}
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
}
An individual operation that itself succeeded but was rolled back due to failure of another operation:
WildFly 9
{
"outcome" => "failed",
"result" => {
"name" => "Brian",
"age" => 22
},
"rolled-back" => true
}
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
}
{
"outcome" => "success",
"result" => [
{
"outcome" => "success",
"result" => {
"name" => "Brian",
"age" => 22
}
},
{
"outcome" => "success",
"result" => undefined
}
]
}
And for a failed 3 step composite operation, where the first step succeeded and the second failed, triggering
cancellation of the 3rd and rollback of the others:
WildFly 9
{
"outcome" => "failed",
"failure-description" => "[JBAS-99999] Composite operation failed; see individual operation
results for details",
"result" => [
{
"outcome" => "failed",
"result" => {
"name" => "Brian",
"age" => 22
},
"rolled-back" => true
},
{
"outcome" => "failed",
"failure-description" => "[JBAS-12345] Some failure message",
"rolled-back" => true
},
{
"outcome" => "cancelled"
}
]
}
Multi-Server Responses
Multi-server responses are provided by operations that target a Domain Controller or slave Host Controller
and require the responder to apply the operation on multiple servers and aggregate their results (e.g. nearly
all domain or host configuration updates.)
Multi-server operations are executed in several stages.
First, the operation may need to be applied against the authoritative configuration model maintained by the
Domain Controller (for domain.xml confgurations) or a Host Controller (for a host.xml configuration). If
there is a failure at this stage, the operation is automatically rolled back, with a response like this:
{
"outcome" => "failed",
"domain-failure-description" => "[JBAS-33333] Failed to apply X to the domain model"
}
If the operation was addressed to the domain model, in the next stage the Domain Controller will ask each
slave Host Controller to apply it to its local copy of the domain model. If any Host Controller fails to do so, the
Domain Controller will tell all Host Controllers to revert the change, and it will revert the change locally as
well. The response to the client will look like this:
WildFly 9
{
"outcome" => "failed",
"host-failure-descriptions" => {
"hostA" => "[DOM-3333] Failed to apply to the domain model",
"hostB" => "[DOM-3333] Failed to apply to the domain model"
}
}
If the preceding stages succeed, the operation will be pushed to all affected servers. If the operation is
successful on all servers, the response will look like this (this example operation has a void response, hence
the result for each server is undefined):
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
}
}
}
WildFly 9
The operation need not succeed on all servers in order to get an "outcome" => "success" result. All
that is required is that it succeed on at least one server without the rollback policies in the rollout plan
triggering a rollback on that server. An example response in such a situation would look like this:
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-3" => {
"host" => "host3",
"response" => {
"outcome" => "failed",
"failure-description" => "[DOM-4556] Something didn't work right",
"rolled-back" => true
}
}
}
}
}
Finally, if the operation fails or is rolled back on all servers, an example response would look like this:
WildFly 9
{
"outcome" => "failed",
"server-groups" => {
"groupA" => {
"serverA-1" => {
"host" => "host1",
"response" => {
"outcome" => "success",
"result" => undefined
}
},
"serverA-2" => {
"host" => "host2",
"response" => {
"outcome" => "success",
"result" => undefined
}
}
},
"groupB" => {
"serverB-1" => {
"host" => "host1",
"response" => {
"outcome" => "failed",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-2" => {
"host" => "host2",
"response" => {
"outcome" => "failed",
"result" => undefined,
"rolled-back" => true
}
},
"serverB-3" => {
"host" => "host3",
"response" => {
"outcome" => "failed",
"failure-description" => "[DOM-4556] Something didn't work right",
"rolled-back" => true
}
}
}
}
}
WildFly 9
<management-interfaces>
[...]
<http-interface security-realm="ManagementRealm">
<socket-binding http="management-http"/>
</http-interface>
<management-interfaces>
The HTTP API Endpoint serves two different contexts. One for executing management operations and
another one that allows you to access the web interface:
Domain API: http://<host>:9990/management
Web Console: http://<host>:9990/console
WildFly 9
Default URL
By default the web interface can be accessed here: http://localhost:9990/console.
WildFly 9
The user are stored in a properties file called mgmt-users.properties under standalone/configuration and
domain/configuration depending on the running mode of the server, these files contain the users username
along with a pre-prepared hash of the username along with the name of the realm and the users password.
Although the properties files do not contain the plain text passwords they should still be guarded as
the pre-prepared hashes could be used to gain access to any server with the same realm if the
same user has used the same password.
WildFly 9
To manipulate the files and add users we provide a utility add-user.sh and add-user.bat to add the users and
generate the hashes, to add a user you should execute the script and follow the guided process.
The full details of the add-user utility are described later but for the purpose of accessing the management
interface you need to enter the following values: Type of user - This will be a 'Management User' to selection option a.
Realm - This MUST match the realm name used in the configuration so unless you have changed the
configuration to use a different realm name leave this set as 'ManagementRealm'.
Username - The username of the user you are adding.
Password - The users password.
Provided the validation passes you will then be asked to confirm you want to add the user and the properties
files will be updated.
For the final question, as this is a user that is going to be accessing the admin console just answer 'n' - this
option will be described later for adding slave host controllers that authenticate against a master domain
controller but that is a later topic.
Updates to the properties file are picked up in real time so either click 'Try Again' on the error page that was
displayed in the browser or navigate to the console again and you should then be prompted to enter the
username and password to connect to the server.
WildFly 9
<management-interfaces>
<native-interface security-realm="ManagementRealm">
<socket-binding native="management-native"/>
</native-interface>
</native-interf [...]
<management-interfaces>
./bin/jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server
or 'help' for the list of supported commands.
[disconnected /]
[disconnected /] connect
[domain@localhost:9999 /]
[domain@localhost:9999 /] quit
Closed connection to localhost:9999
localhost:9999 is the default host and port combination for the WildFly 9 domain controller client.
WildFly 9
The host and the port of the server can be provided as an optional parameter, if the server is not listening on
localhost:9999.
./bin/jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server
[disconnected /] connect 192.168.0.10:9999
Connected to standalone controller at 192.168.0.1:9999
The :9999 is not required as the CLI will use port 9999 by default. The port needs to be provided if the server
is listening on some other port.
To terminate the session type quit.
[domain@localhost:9999 /] help
Supported commands:
cn (or cd)
connect
deploy
help (or h)
history
ls
pwn (or pwd)
quit (or q)
undeploy
version
add-jms-queue
remove-jms-queue
add-jms-topic
remove-jms-topic
add-jms-cf
remove-jms-cf
creates
removes
creates
removes
creates
removes
data-source
xa-data-source
WildFly 9
interactive Mode
The CLI can also be run in non-interactive mode to support scripts and other types of command line or batch
processing. The --command and --commands arguments can be used to pass a command or a list of
commands to execute. Additionally a --file argument is supported which enables CLI commands to be
provided from a text file.
For example the following command can be used to list all the current deployments
The output can be combined with other shell commands for further processing, for example to find out what
.war files are deployed:
Operation Requests
Operation requests allow for low level interaction with the management model. They are different from the
high level commands (i.e. create-jms-queue) in that they allow you to read and modify the server
configuration as if you were editing the XML configuration files directly. The configuration is represented as a
tree of addressable resources, where each node in the tree (aka resource) offers a set of operations to
execute.
An operation request basically consists of three parts: The address, an operation name and an optional set
of parameters.
The formal specification for an operation request is:
For example:
/profile=production/subsystem=threads/bounded-queue-thread-pool=pool1:write-core-threads
(count=0, per-cpu=20)
WildFly 9
Tab Completion
Tab-completion is supported for all commands and options, i.e. node-types and node-names,
operation names and parameter names. We are also considering adding aliases that are less
verbose for the user, and will translate into the corresponding operation requests in the
background.
Whitespaces between the separators in the operation request strings are not significant.
Addressing resources
Operation requests might not always have the address part or the parameters. E.g.
:read-resource
which will list all the node types for the current node.
To syntactically disambiguate between the commands and operations, operations require one of the
following prefixes:
To execute an operation against the current node, e.g.
cd subsystem=web
:read-resource(recursive="true")
cd subsystem=web
./connector=http:read-resource
/subsystem=threads:read-resource
WildFly 9
add
read-attribute
read-children-names
read-children-resources
read-children-types
read-operation-description
read-operation-names
read-resource
read-resource-description
remove
validate-address
write-attribute
For a list of specific operations (e.g. operations that relate to the logging subsystem) you can always query
the model itself. For example, to read the operations supported by the logging subsystem resource on a
standalone server:
[[standalone@localhost:9999 /] /subsystem=logging:read-operation-names
{
"outcome" => "success",
"result" => [
"add",
"change-root-log-level",
"read-attribute",
"read-children-names",
"read-children-resources",
"read-children-types",
"read-operation-description",
"read-operation-names",
"read-resource",
"read-resource-description",
"remove-root-logger",
"root-logger-assign-handler",
"root-logger-unassign-handler",
"set-root-logger",
"validate-address",
"write-attribute"
]
}
As you can see, the logging resource offers four additional operations, namely root-logger-assign-handler,
root-logger-unassign-handler , set-root-logger and remove-root-logger.
Further documentation about a resource or operation can be retrieved through the description:
WildFly 9
[standalone@localhost:9999 /]
/subsystem=logging:read-operation-description(name=change-root-log-level)
{
"outcome" => "success",
"result" => {
"operation-name" => "change-root-log-level",
"description" => "Change the root logger level.",
"request-properties" => {"level" => {
"type" => STRING,
"description" => "The log level specifying which message levels will be logged by
this logger.
Message levels lower than this value will be discarded.",
"required" => true
}}
}
}
Full model
To see the full model enter :read-resource(recursive=true).
Command History
Command (and operation request) history is enabled by default. The history is kept both in-memory and in a
file on the disk, i.e. it is preserved between the command line sessions. The history file name is
.jboss-cli-history and is automatically created in the user's home directory. When the command line interface
is launched this file is read and the in-memory history is initialized with its content.
While in the command line session, you can use the arrow keys to go back and forth in the history
of commands and operations.
To manipulate the history you can use history command. If executed without any arguments, it will print all
the recorded commands and operations (up to the configured maximum, which defaults to 500) from the
in-memory history.
history supports three optional arguments:
disable - will disable history expansion (but will not clear the previously recorded history);
enabled - will re-enable history expansion (starting from the last recorded command before the history
expansion was disabled);
clear - will clear the in-memory history (but not the file one).
WildFly 9
Batch Processing
The batch mode allows one to group commands and operations and execute them together as an atomic
unit. If at least one of the commands or operations fails, all the other successfully executed commands and
operations in the batch are rolled back.
Not all of the commands are allowed in the batch. For example, commands like cd, ls, help, etc. are not
allowed in the batch since they don't translate into operation requests. Only the commands that translate into
operation requests are allowed in the batch. The batch, actually, is executed as a composite operation
request.
The batch mode is entered by executing command batch.
[standalone@localhost:9999 /] batch
[standalone@localhost:9999 / #] /subsystem=datasources/data-source="java\:\/H2DS":enable
[standalone@localhost:9999 / #] /subsystem=messaging/jms-queue="newQueue":add
[standalone@localhost:9999 / #] run-batch
The batch executed successfully.
[standalone@localhost:9999 / #] holdback-batch
[standalone@localhost:9999 /]
[standalone@localhost:9999 /] batch
Re-activated batch
#1 /subsystem=datasources/data-source=java:/H2DS:\/H2DS:enable
There are several other notable batch commands available as well (tab complete to see the list):
clear-batch
edit-batch-line (e.g. edit-batch line 3 create-jms-topic name=mytopic)
remove-batch-line (e.g. remove-batch-line 3)
move-batch-line (e.g. move-batch-line 3 1)
discard-batch
WildFly 9
The XML configuration files act as a central, authoritative source of configuration. Any configuration
changes made via the web interface or the CLI are persisted back to the XML configuration files. If
a domain or standalone server is offline, the XML configuration files can be hand edited as well,
and any changes will be picked up when the domain or standalone server is next started. However,
users are encouraged to use the web interface or the CLI in preference to making offline edits to
the configuration files. External changes made to the configuration files while processes are
running will not be detected, and may be overwritten.
WildFly 9
The user are stored in a properties file called mgmt-users.properties under standalone/configuration and
domain/configuration depending on the running mode of the server, these files contain the users username
along with a pre-prepared hash of the username along with the name of the realm and the users password.
Although the properties files do not contain the plain text passwords they should still be guarded as
the pre-prepared hashes could be used to gain access to any server with the same realm if the
same user has used the same password.
WildFly 9
To manipulate the files and add users we provide a utility add-user.sh and add-user.bat to add the users and
generate the hashes, to add a user you should execute the script and follow the guided process.
The full details of the add-user utility are described later but for the purpose of accessing the management
interface you need to enter the following values: Type of user - This will be a 'Management User' to selection option a.
Realm - This MUST match the realm name used in the configuration so unless you have changed the
configuration to use a different realm name leave this set as 'ManagementRealm'.
Username - The username of the user you are adding.
Password - The users password.
Provided the validation passes you will then be asked to confirm you want to add the user and the properties
files will be updated.
For the final question, as this is a user that is going to be accessing the admin console just answer 'n' - this
option will be described later for adding slave host controllers that authenticate against a master domain
controller but that is a later topic.
Updates to the properties file are picked up in real time so either click 'Try Again' on the error page that was
displayed in the browser or navigate to the console again and you should then be prompted to enter the
username and password to connect to the server.
WildFly 9
System properties
To set a system property, pass its new value using the standard jvm -Dkey=value options:
$JBOSS_HOME/bin/standalone.sh -Djboss.home.dir=some/location/WildFly/jboss-as \
-Djboss.server.config.dir=some/location/WildFly/jboss-as/custom-standalone
This command starts up a standalone server instance using a non-standard AS home directory and a
custom configuration directory. For specific information about system properties, refer to the definitions
below.
Instead of passing the parameters directly, you can put them into a properties file, and pass the properties
file to the script, as in the two examples below.
$JBOSS_HOME/bin/domain.sh --properties=/some/location/jboss.properties
$JBOSS_HOME/bin/domain.sh -P=/some/location/jboss.properties
Note however, that properties set this way are not processed as part of JVM launch. They are processed
early in the boot process, but this mechanism should not be used for setting properties that control JVM
behavior (e.g. java.net.perferIPv4Stack) or the behavior of the JBoss Modules classloading system.
The syntax for passing in parameters and properties files is the same regardless of whether you are running
the domain.sh, standalone.sh, or the Microsoft Windows scriptsdomain.bat or standalone.bat.
WildFly 9
The properties file is a standard Java property file containing key=value pairs:
jboss.home.dir=/some/location/WildFly/jboss-as
jboss.domain.config.dir=/some/location/WildFly/custom-domain
System properties can also be set via the xml configuration files. Note however that for a standalone server
properties set this way will not be set until the xml configuration is parsed and the commands created by the
parser have been executed. So this mechanism should not be used for setting properties whose value needs
to be set before this point.
Standalone
Property name
Usage
Default value
java.ext.dirs
null
jboss.home.dir
Set by standalone.sh to
installation.
$JBOSS_HOME
jboss.home.dir/standalone
jboss.server.base.dir
jboss.server.base.dir
/configuration
jboss.server.data.dir
jboss.server.log.dir
jboss.server.base.dir
file storage.
/data
jboss.server.base.dir/log
server.log file.
jboss.server.temp.dir
jboss.server.base.dir/tmp
storage.
jboss.server.deploy.dir The directory used to store deployed
content
jboss.server.data.dir
/content
WildFly 9
Managed Domain
Property name
Usage
Default value
jboss.home.dir
Set by domain.sh to
installation.
$JBOSS_HOME
jboss.home.dir/domain
jboss.domain.base.dir
content.
jboss.domain.config.dir
jboss.domain.base.dir
/configuration
jboss.domain.data.dir
jboss.domain.log.dir
jboss.domain.base.dir
file storage.
/data
jboss.domain.base.dir
host-controller.log and
/log
process-controller.log files
jboss.domain.temp.dir
jboss.domain.base.dir
storage
/tmp
jboss.domain.servers.dir
jboss.domain.base.dir
content
/content
jboss.domain.base.dir
/servers
--name=value
For example:
$JBOSS_HOME/bin/standalone.sh --server-config=standalone-ha.xml
If the parameter name is a single character, it is prefixed by a single '-' instead of two. Some parameters
have both a long and short option.
-x=value
For example:
WildFly 9
$JBOSS_HOME/bin/standalone.sh -P=/some/location/jboss.properties
For some command line arguments frequently used in previous major releases of WildFly, replacing the "="
in the above examples with a space is supported, for compatibility.
-b 192.168.100.10
If possible, use the -x=value syntax. New parameters will always support this syntax.
The sections below describe the command line parameter names that are available in standalone and
domain mode.
Standalone
Name
Default if
Value
absent
--admin-only
--server-config
-c
--read-only-server-config -
WildFly 9
Managed Domain
Name
Default if
Value
absent
-
--admin-only
--domain-config
-c
--host-config
host.xml
--read-only-host-config
The following parameters take no value and are only usable on slave host controllers (i.e. hosts configured
to connect to a remote domain controller.)
Name
Function
--backup
Causes the slave host controller to create and maintain a local copy of the domain
configuration file
--cached-dc If the slave host controller is unable to contact the master domain controller to get its
configuration at boot, boot from a local copy previously created using --backup. The
slave host controller will not be able make any modifications to the domain configuration,
but it will be able to launch servers.
WildFly 9
Common parameters
These parameters apply in both standalone or managed domain mode:
Name
Function
-b=<value>
--version
Prints the version of WildFly to standard output and exits the JVM.
-v
-V
--help
Prints a help message explaining the options and exits the JVM.
-h
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
WildFly 9
$JBOSS_HOME/bin/standalone.sh -b=192.168.100.10
In the standard config files, public interfaces are those not associated with server management. Public
interfaces handle normal end-user requests.
Interface names
The interface named "public" is not inherently special. It is provided as a convenience. You can
name your interfaces to suit your environment.
To bind the public interfaces to all IPv4 addresses (the IPv4 wildcard address), use the following syntax:
$JBOSS_HOME/bin/standalone.sh -b=0.0.0.0
$JBOSS_HOME/bin/standalone.sh -bmanagement=192.168.100.10
In the standard config files, management interfaces are those sockets associated with server management,
such as the socket used by the CLI, the HTTP socket used by the admin console, and the JMX connector
socket.
Be Careful
The -b switch only controls the interface bindings because the standard config files that ship with
WildFly sets things up that way. If you change the <interfaces> section in your configuration to
ignore the system properties controlled by -b, then setting -b in your launch command will have no
effect.
For example, this perfectly valid setting for the "public" interface causes -b to have no effect on
the "public" interface:
<interface name="public">
<nic name="eth0"/>
</interface>
The key point is the contents of the configuration files determine the configuration. Settings
like -b are not overrides of the configuration files. They only provide a shorter syntax for
setting a system properties that may or may not be referenced in the configuration files. They are
provided as a convenience, and you can choose to modify your configuration to ignore them.
WildFly 9
$JBOSS_HOME/bin/standalone.sh -u=230.0.1.2
Be Careful
As with the -b switch, the -u switch only controls the multicast address used because the standard
config files that ship with WildFly 8 sets things up that way. If you change the <socket-binding>
sections in your configuration to ignore the system properties controlled by -u, then setting -u in
your launch command will have no effect.
WildFly 9
The domain and host controller components manage the distribution of binaries across network boundaries.
Deployment Commands
Distributing deployment binaries involves two steps: uploading the deployment to the repository the domain
controller will use to distribute its contents, and then assigning the deployment to one or more server groups.
You can do this in one sweep with the CLI:
After you've uploaded the binary using the deploy command, it will be available to the domain controller,
and assigned to a server group:
[domain@localhost:9999 /] :read-children-names(child-type=deployment)
{
"outcome" => "success",
"result" => [
"mysql-connector-java-5.1.15.jar",
"test-application.war"
]
}
[domain@localhost:9999 /]
/server-group=main-server-group/deployment=test-application.war:read-resource
{
"outcome" => "success",
"result" => {
"enabled" => true,
"name" => "test-application.war",
"runtime-name" => "test-application.war"
}
}
You can remove binaries from server groups with the undeploy command:
WildFly 9
Managing deployments through the web interface provides an alternate, sometimes simpler
approach.
Content Repository
Deployments are referenced in the domain configuration file, and co-located with the domain controller:
[...]
<deployments>
<deployment name="test-application.war"
runtime-name="test-application.war">
<content sha1="dda9881fa7811b22f1424b4c5acccb13c71202bd"/>
</deployment>
</deployments>
[...]
<server-groups>
<server-group name="main-server-group" profile="default">
[...]
<deployments>
<deployment name="test-application.war" runtime-name="test-application.war"/>
</deployments>
</server-group>
</server-groups>
[...]
(See domain/configuration/domain.xml)
ls domain/content/
|---/47
|-----95cc29338b5049e238941231b36b3946952991
|---/dd
|-----a9881fa7811b22f1424b4c5acccb13c71202bd
Standalone Server
Deployments on a standalone server work in a similar way to those on managed domains. The main
difference is that there are no server group associations.
WildFly 9
Deployment Commands
The same CLI commands used for managed domains work for standalone servers when deploying and
removing an application:
Users are encouraged to use the WildFly 8 management APIs to upload and deploy deployment
content instead of relying on the deployment scanner that periodically scans the directory,
particularly if running production systems.
WildFly 9
Deployment Modes
The WildFly 8 filesystem deployment scanner operates in one of two different modes, depending on whether
it will directly monitor the deployment content in order to decide to deploy or redeploy it.
Auto-deploy mode:
The scanner will directly monitor the deployment content, automatically deploying new content and
redeploying content whose timestamp has changed. This is similiar to the behavior of previous AS releases,
although there are differences:
A change in any file in an exploded deployment triggers redeploy. Because EE 6 applications do not
require deployment descriptors,
there is no attempt to monitor deployment descriptors and only redeploy when a deployment
descriptor changes.
The scanner will place marker files in this directory as an indication of the status of its attempts to
deploy or undeploy content. These are detailed below.
Manual deploy mode:
The scanner will not attempt to directly monitor the deployment content and decide if or when the end user
wishes the content to be deployed. Instead, the scanner relies on a system of marker files, with the user's
addition or removal of a marker file serving as a sort of command telling the scanner to deploy, undeploy or
redeploy content.
Auto-deploy mode and manual deploy mode can be independently configured for zipped deployment content
and exploded deployment content. This is done via the "auto-deploy" attribute on the deployment-scanner
element in the standalone.xml configuration file:
By default, auto-deploy of zipped content is enabled, and auto-deploy of exploded content is disabled.
Manual deploy mode is strongly recommended for exploded content, as exploded content is inherently
vulnerable to the scanner trying to auto-deploy partially copied content.
Marker Files
The marker files always have the same name as the deployment content to which they relate, but with an
additional file suffix appended. For example, the marker file to indicate the example.war file should be
deployed is named example.war.dodeploy. Different marker file suffixes have different meanings.
The relevant marker file types are:
WildFly 9
File
Purpose
.dodeploy
.skipdeploy
.isdeploying
.deployed
.failed
.pending
Basic workflows:
All examples assume variable $JBOSS_HOME points to the root of the WildFly 8 distribution.
WildFly 9
A) Add new zipped content and deploy it:
1. cp target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
B) Add new unzipped content and deploy it:
1. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
C) Undeploy currently deployed content:
1. rm $JBOSS_HOME/standalone/deployments/example.war.deployed
D) Auto-deploy mode only: Undeploy currently deployed content:
1. rm $JBOSS_HOME/standalone/deployments/example.war
E) Replace currently deployed zipped content with a new version and deploy it:
1. cp target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
F) Manual mode only: Replace currently deployed unzipped content with a new version and deploy it:
1. rm $AS/standalone/deployments/example.war.deployed
2. wait for $JBOSS_HOME/standalone/deployments/example.war.undeployed file to appear
3. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
4. touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
G) Auto-deploy mode only: Replace currently deployed unzipped content with a new version and deploy it:
1. touch $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
2. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
3. rm $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
H) Manual mode only: Live replace portions of currently deployed unzipped content without redeploying:
1. cp -r target/example.war/foo.html $JBOSS_HOME/standalone/deployments/example.war
I) Auto-deploy mode only: Live replace portions of currently deployed unzipped content without redeploying:
1. touch $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
2. cp -r target/example.war/foo.html $JBOSS_HOME/standalone/deployments/example.war
J) Manual or auto-deploy mode: Redeploy currently deployed content (i.e. bounce it with no content change):
1. touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
K) Auto-deploy mode only: Redeploy currently deployed content (i.e. bounce it with no content change):
WildFly 9
1. touch $JBOSS_HOME/standalone/deployments/example.war
The above examples use Unix shell commands. Windows equivalents are:
cp src dest --> xcopy /y src dest
cp -r src dest --> xcopy /e /s /y src dest
rm afile --> del afile
touch afile --> echo>> afile
Note that the behavior of 'touch' and 'echo' are different but the differences are not relevant to the
usages in the examples above.
WildFly 9
[domain@localhost:9999 /] :read-children-names(child-type=host)
{
"outcome" => "success",
"result" => ["local"]
}
[domain@localhost:9999 /] /host=local:read-children-names(child-type=server-config)
{
"outcome" => "success",
"result" => [
"my-server",
"server-one",
"server-three"
]
}
Now that we know, that there are two servers configured on host "local", we can go ahead and check
their status:
[domain@localhost:9999 /]
/host=local/server-config=server-one:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"auto-start" => true,
"group" => "main-server-group",
"interface" => undefined,
"name" => "server-one",
"path" => undefined,
"socket-binding-group" => undefined,
"socket-binding-port-offset" => undefined,
"status" => "STARTED",
"system-property" => undefined,
"jvm" => {"default" => undefined}
}
}
You can change the server state through the "start" and "stop" operations
WildFly 9
[domain@localhost:9999 /] /host=local/server-config=server-one:stop
{
"outcome" => "success",
"result" => "STOPPING"
}
Navigating through the domain topology is much more simple when you use the web interface.
Managed Domain
In a managed domain the JVM settings can be declared at different scopes: For a specific server group, for
a host or for a particular server. If not declared, the settings are inherited from the parent scope. This allows
you to customize or extend the JVM settings within every layer.
Let's take a look at the JVM declaration for a server group:
<server-groups>
<server-group name="main-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
<server-group name="other-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
</server-groups>
(See
domain/configuration/domain.xml)
In this example the server group "main-server-group" declares a heap size of 64m and a maximum heap size
of 512m. Any server that belongs to this group will inherit these settings. You can change these settings for
the group as a whole, or a specific server or host:
WildFly 9
<servers>
<server name="server-one" group="main-server-group" auto-start="true">
<jvm name="default"/>
</server>
<server name="server-two" group="main-server-group" auto-start="true">
<jvm name="default">
<heap size="64m" max-size="256m"/>
</jvm>
<socket-binding-group ref="standard-sockets" port-offset="150"/>
</server>
<server name="server-three" group="other-server-group" auto-start="false">
<socket-binding-group ref="standard-sockets" port-offset="250"/>
</server>
</servers>
(See domain/configuration/host.xml)
In this case, server-two, belongs to the main-server-group and inherits the JVM settings named default, but
declares a lower maximum heap size.
[domain@localhost:9999 /] /host=local/server-config=server-two/jvm=default:read-resource
{
"outcome" => "success",
"result" => {
"heap-size" => "64m",
"max-heap-size" => "256m",
}
}
Standalone Server
For a standalone sever you have to pass in the JVM settings either as command line arguments when
executing the $JBOSS_HOME/bin/standalone.sh script, or by declaring them in
$JBOSS_HOME/bin/standalone.conf. (For Windows users, the script to execute is
%JBOSS_HOME%/bin/standalone.bat while the JVM settings can be declared in
%JBOSS_HOME%/bin/standalone.conf.bat.)
WildFly 9
<management>
<security-realms>
...
</security-realms>
<audit-log>
<formatters>
<json-formatter name="json-formatter"/>
</formatters>
<handlers>
<file-handler name="file" formatter="json-formatter" path="audit-log.log"
relative-to="jboss.server.data.dir"/>
</handlers>
<logger log-boot="true" log-read-only="true" enabled="false">
<handlers>
<handler name="file"/>
</handlers>
</logger>
</audit-log>
...
[standalone@localhost:9990 /]
/core-service=management/access=audit:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"file-handler" => {"file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.server.data.dir"
}},
"json-formatter" => {"json-formatter" => {
"compact" => false,
"date-format" => "yyyy-MM-dd HH:mm:ss",
"date-separator" => " - ",
"escape-control-characters" => false,
"escape-new-line" => false,
"include-date" => true
}},
"logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"file" => {}}
}},
"syslog-handler" => undefined
}
}
WildFly 9
The audit logging subsystem has a lot of internal dependencies, and it logs operations changing,
enabling and disabling its components. When configuring or changing things at runtime it is a good
idea to make these changes as part of a CLI batch. For example if you are adding a syslog handler
you need to add the handler and its information as one step. Similarly if you are using a file
handler, and want to change its path and relative-to attributes, that needs to happen as one
step.
JSON Formatter
The first thing that needs configuring is the formatter, we currently support outputting log records as JSON.
You can define several formatters, for use with different handlers. A log record has the following format, and
it is the formatter's job to format the data presented:
2013-08-12 11:01:12 - {
"type" : "core",
"r/o" : false,
"booting" : false,
"version" : "8.0.0.Alpha4",
"user" : "$local",
"domainUUID" : null,
"access" : "NATIVE",
"remote-address" : "127.0.0.1/127.0.0.1",
"success" : true,
"ops" : [JMX|WFLY8:JMX subsystem configuration],
"operation" : "write-attribute",
"name" : "enabled",
"value" : true,
"operation-headers" : {"caller-type" : "user"}
}]
}
It includes an optional timestamp and then the following information in the json record
WildFly 9
Field name
Description
type
This can have the values core, meaning it is a management operation, or jmx
meaning it comes from the jmx subsystem (see the jmx subsystem for configuration of
the jmx subsystem's audit logging)
r/o
true if the operation does not change the management model, false otherwise
booting
true if the operation was executed during the bootup process, false if it was
executed once the server is up and running
version
user
The username of the authenticated user. In this case the operation has been logged
via the CLI on the same machine as the running server, so the special $local user
is used
domainUUID
An ID to link together all operations as they are propagated from the Doman
Controller to it servers, slave Host Controllers, and slave Host Controller servers
access
ops
The operations being executed. This is a list of the operations serialized to JSON. At
boot this will be all the operations resulting from parsing the xml. Once booted the list
will typically just contain a single entry
WildFly 9
Attribute
Description
include-date
date-separator
A string containing characters to separate the date and the rest of the
formatted log message. Will be ignored if include-date=false
date-format
compact
If true will format the JSON on one line. There may still be values
containing new lines, so if having the whole record on one line is
important, set escape-new-line or escape-control-characters to true
escape-control-characters If true it will escape all control characters (ascii entries with a decimal
value < 32) with the ascii code in octal, e.g. a new line becomes '#012'.
If this is true, it will override escape-new-line=false
escape-new-line
If true it will escape all new lines with the ascii code in octal, e.g.
"#012".
Handlers
A handler is responsible for taking the formatted data and logging it to a location. There are currently two
types of handlers, File and Syslog. You can configure several of each type of handler and use them to log
information.
WildFly 9
File handler
The file handlers log the audit log records to a file on the server. The attributes for the file handler are
Attribute
Description
Read
Only
formatter
false
path
false
relative-to
false
true
max-failure-count
false
handler
disabled-due-to-failure true if this handler was disabled due to logging failures
true
Syslog handler
The default configuration does not have syslog audit logging set up. Syslog is a better choice for audit
logging since you can log to a remote syslog server, and secure the authentication to happen over TLS with
client certificate authentication. Syslog servers vary a lot in their capabilities so not all settings in this section
apply to all syslog servers. We have tested with rsyslog.
The address for the syslog handler is
/core-service=management/access=audit/syslog-handler=* and just like file handlers you can
add as many syslog entries as you like. The syslog handler resources reference the main RFC's for syslog a
fair bit, for reference they can be found at:
*http://www.ietf.org/rfc/rfc3164.txt
*http://www.ietf.org/rfc/rfc5424.txt
*http://www.ietf.org/rfc/rfc6587.txt
The syslog handler resource has the following attributes:
WildFly 9
formatter
false
failure-count
true
max-failure-count
false
handler
disabled-due-to-failure true if this handler was disabled due to logging failures
syslog-format
true
false
RFC-5424 or RFC-3164
max-length
false
truncate
UDP
Configures the handler to use UDP to communicate with the syslog server. The address of the UDP resource
is /core-service=management/access=audit/syslog-handler=*/protocol=udp. The attributes
of the UDP resource are:
Attribute Description
host
port
The port of the syslog server listening for the udp requests
WildFly 9
TCP
Configures the handler to use TCP to communicate with the syslog server. The address of the TCP resource
is /core-service=management/access=audit/syslog-handler=*/protocol=tcp. The attributes
of the TCP resource are:
Attribute
Description
host
port
The port of the syslog server listening for the tcp requests
message-transfer The message transfer setting as described in section 3.4 of RFC-6587. This can
either be OCTET_COUNTING as described in section 3.4.1 of RFC-6587, or
NON_TRANSPARENT_FRAMING as described in section 3.4.1 of RFC-6587
TLS
Configures the handler to use TLC to communicate securely with the syslog server. The address of the TLS
resource is /core-service=management/access=audit/syslog-handler=*/protocol=tls. The
attributes of the TLS resource are the same as for TCP:
Attribute
Description
host
port
The port of the syslog server listening for the tls requests
message-transfer The message transfer setting as described in section 3.4 of RFC-6587. This can
either be OCTET_COUNTING as described in section 3.4.1 of RFC-6587, or
NON_TRANSPARENT_FRAMING as described in section 3.4.1 of RFC-6587
If the syslog server's TLS certificate is not signed by a certificate signing authority, you will need to set up a
truststore to trust the certificate. The resource for the trust store is a child of the TLS resource, and the full
address is
/core-service=management/access=audit/syslog-handler=*/protocol=tls/authentication=trustst
. The attributes of the truststore resource are:
Attribute
Description
keystore-password
keystore-path
keystore-relative-to The name of another previously named path, or of one of the standard paths
provided by the system. If keystore-relative-to is provided, the value
of the keystore-path attribute is treated as relative to the path specified by
this attribute
WildFly 9
TLS with Client certificate authentication.
If you have set up the syslog server to require client certificate authentication, when creating your handler
you will also need to set up a client certificate store containing the certificate to be presented to the syslog
server. The address of the client certificate store resource is
Description
keystore-password
key-password
keystore-path
keystore-relative-to The name of another previously named path, or of one of the standard paths
provided by the system. If keystore-relative-to is provided, the value
of the keystore-path attribute is treated as relative to the path specified by
this attribute
Logger configuration
The final part that needs configuring is the logger for the management operations. This references one or
more handlers and is configured at /core-service=management/access=audit/logger=audit-log
. The attributes for this resource are:
Attribute
Description
enabled
log-boot
true to log the management operations when booting the server, false otherwise
log-read-only If true all operations will be audit logged, if false only operations that change the
model will be logged
Then which handlers are used to log the management operations are configured as handler=* children of
the logger.
WildFly 9
[domain@localhost:9990 /]
/host=master/core-service=management/access=audit:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"file-handler" => {
"host-file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.domain.data.dir"
},
"server-file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.server.data.dir"
}
},
"json-formatter" => {"json-formatter" => {
"compact" => false,
"date-format" => "yyyy-MM-dd HH:mm:ss",
"date-separator" => " - ",
"escape-control-characters" => false,
"escape-new-line" => false,
"include-date" => true
}},
"logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"host-file" => {}}
}},
"server-logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"server-file" => {}}
}},
"syslog-handler" => undefined
}
}
We now have two file handlers, one called host-file used to configure the file to log management
operations on the host, and one called server-file used to log management operations executed on the
servers. Then logger=audit-log is used to configure the logger for the host controller, referencing the
host-file handler. server-logger=audit-log is used to configure the logger for the managed
servers, referencing the server-file handler. The attributes for server-logger=audit-log are the
same as for server-logger=audit-log in the previous section. Having the host controller and server
loggers configured independently means we can control audit logging for managed servers and the host
controller independently.
WildFly 9
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:cancel-non-progressing-operation
{
"outcome" => "success",
"result" => "-1155777943"
}
The result value is an internal identification number for the operation that was cancelled.
On a managed domain host controller, the equivalent resource is in the host=<hostname> portion of the
management resource tree:
[domain@localhost:9990 /]
/host=host-a/core-service=management/service=management-operations:cancel-non-progressing-operation{
"outcome" => "success",
"result" => "2156877946"
}
[domain@localhost:9990 /]
/host=host-a/server=server-one/core-service=management/service=management-operations:cancel-non-progressing-op
"outcome" => "success",
"result" => "6497786512"
}
An operation is considered to be not proceeding normally if it has been executing with the exclusive
operation lock held for longer than 15 seconds. Read-only operations do not acquire the exclusive operation
lock, so this operation will not cancel read-only operations. Operations blocking waiting for another operation
to release the exclusive lock will also not be cancelled.
If there isn't any operation that is failing to proceed normally, there will be a failure response:
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:cancel-non-progressing-operation
{
"outcome" => "failed",
"failure-description" => "WFLYDM0089: No operation was found that has been holding the
operation execution write lock for long than [15] seconds",
"rolled-back" => true
}
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:find-non-progressing-operation
{
"outcome" => "success",
"result" => "-1155777943"
}
If there is no non-progressing operation, the outcome will still be success but the result will be undefined.
Once the id of the operation is known, the management resource for the operation can be examined to learn
more about its status.
[standalone@localhost:9990 /]
/core-service=management/service=management-operations/active-operation=-1155777943:read-resource(include-runt
"outcome" => "success",
"result" => {
"access-mechanism" => "undefined",
"address" => [
("deployment" => "example")
],
"caller-thread" => "management-handler-thread - 24",
"cancelled" => false,
"exclusive-running-time" => 101918273645L,
"execution-status" => "awaiting-stability",
"operation" => "deploy",
"running-time" => 101918279999L
}
}
WildFly 9
Field
Meaning
access-mechanism
The mechanism used to submit a request to the server. NATIVE, JMX, HTTP
address
The address of the resource targeted by the operation. The value in the final
element of the address will be '<hidden>' if the caller is not authorized to address
the operation's target resource.
caller-thread
cancelled
exclusive-running-time Amount of time in nanoseconds the operation has been executing with the
exclusive operation execution lock held, or -1 if the operation does not hold the
exclusive execution lock.
execution-status
operation
The name of the operation, or '<hidden>' if the caller is not authorized to address
the operation's target resource.
running-time
Meaning
executing
awaiting-other-operation The caller thread is blocking waiting for another operation to release the
exclusive execution lock
awaiting-stability
The caller thread has made changes to the service container and is waiting for
the service container to stabilize
completing
rolling-back
All currently executing operations can be viewed in one request using the read-children-resources
operation:
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:read-children-resources(child-type=active-operation){
"outcome" => "success",
"result" => {"-1155777943" => {
"access-mechanism" => "undefined",
"address" => [
("deployment" => "example")
],
"caller-thread" => "management-handler-thread - 24",
"cancelled" => false,
"exclusive-running-time" => 101918273645L,
"execution-status" => "awaiting-stability",
"operation" => "deploy",
"running-time" => 101918279999L
},
{"-1246693202" => {
"access-mechanism" => "undefined",
"address" => [
("core-service" => "management"),
("service" => "management-operations")
],
"caller-thread" => "management-handler-thread - 30",
"cancelled" => false,
"exclusive-running-time" => -1L,
"execution-status" => "executing",
"operation" => "read-children-resources",
"running-time" => 3356000L
}}
}
[standalone@localhost:9990 /]
/core-service=management/service=management-operations/active-operation=-1155777943:cancel
{
"outcome" => "success",
"result" => undefined
}
WildFly 9
Note the blocking timeout is not a guaranteed maximum execution time for an operation. If it only a timeout
that will be enforced at various points during operation execution.
WildFly 9
Within standalone_xml_history itself following a successful first time boot we end up with three new
files:
*standalone.initial.xml - This contains the original configuration that was used the first time we
successfully booted. This file will never be overwritten. You may of course delete the history directory and
any files in it at any stage.
*standalone.boot.xml - This contains the original configuration that was used for the last successful
boot of the server. This gets overwritten every time we boot the server successfully.
*standalone.last.xml - At this stage the contents will be identical to standalone.boot.xml.
This
file gets overwritten each time the server successfully writes the
configuration, if there was an unexpected failure writing the configuration this
file is the last known successful write.
standalone_xml_history contains a directory called current which should be empty. Now if we
execute a management operation that modifies the model, for example adding a new system property using
the CLI:
[standalone@localhost:9999 /] /system-property=test:add(value="test123")
{"outcome" => "success"}
Snapshots
In addition to the backups taken by the server as described above you can manually take take snapshots
which will be stored in the snapshot folder under the _xml_history folder, the automatic backups
described above are subject to automatic house keeping so will eventually be automatically removed, the
snapshots on the other hand can be entirely managed by the administrator.
You may also take your own snapshots using the CLI:
[standalone@localhost:9999 /] :take-snapshot
{
"outcome" => "success",
"result" => {"name" =>
"/Users/kabir/jboss-7.0.0.CR1/standalone/configuration/standalone_xml_history/snapshot/20110630-172258657stand
WildFly 9
You can also use the CLI to list all the snapshots
[standalone@localhost:9999 /] :list-snapshots
{
"outcome" => "success",
"result" => {
"directory" =>
"/Users/kabir/jboss-7.0.0.CR1/standalone/configuration/standalone_xml_history/snapshot",
"names" => [
"20110630-165714239standalone.xml",
"20110630-165821795standalone.xml",
"20110630-170113581standalone.xml",
"20110630-171411463standalone.xml",
"20110630-171908397standalone.xml",
"20110630-172258657standalone.xml"
]
}
}
[standalone@localhost:9999 /] :delete-snapshot(name="20110630-165714239standalone.xml")
{"outcome" => "success"}
[standalone@localhost:9999 /] :delete-snapshot(name="all")
{"outcome" => "success"}
In domain mode executing the snapshot operations against the root node will work against the domain
model. To do this for a host model you need to navigate to the host in question:
[domain@localhost:9999 /] /host=master:list-snapshots
{
"outcome" => "success",
"result" => {
"domain-results" => {"step-1" => {
"directory" =>
"/Users/kabir/jboss-7.0.0.CR1/domain/configuration/host_xml_history/snapshot",
"names" => [
"20110630-141129571host.xml",
"20110630-172522225host.xml"
]
}},
"server-operations" => undefined
}
}
WildFly 9
Subsequent Starts
For subsequent server starts it may be desirable to take the state of the server back to one of the previously
known states, for a number of items an abbreviated reverence to the file can be used: Abreviation Parameter
initial
Description
--server-config=initial This will start the server using the initial configuration first
used to start the server.
boot
--server-config=boot
This will use the configuration from the last successful boot
of the server.
last
--server-config=last
v?
--server-config=v?
???? -
--server-config=???? -
?????
?????
In addition to this the --server-config parameter can always be used to specify a configuration relative
to the jboss.server.config.dir and finally if no matching configuration is found an attempt to locate
the configuration as an absolute path will be made.
Deployment Commands
Distributing deployment binaries involves two steps: uploading the deployment to the repository the domain
controller will use to distribute its contents, and then assigning the deployment to one or more server groups.
You can do this in one sweep with the CLI:
WildFly 9
After you've uploaded the binary using the deploy command, it will be available to the domain controller,
and assigned to a server group:
[domain@localhost:9999 /] :read-children-names(child-type=deployment)
{
"outcome" => "success",
"result" => [
"mysql-connector-java-5.1.15.jar",
"test-application.war"
]
}
[domain@localhost:9999 /]
/server-group=main-server-group/deployment=test-application.war:read-resource
{
"outcome" => "success",
"result" => {
"enabled" => true,
"name" => "test-application.war",
"runtime-name" => "test-application.war"
}
}
You can remove binaries from server groups with the undeploy command:
Managing deployments through the web interface provides an alternate, sometimes simpler
approach.
WildFly 9
Content Repository
Deployments are referenced in the domain configuration file, and co-located with the domain controller:
[...]
<deployments>
<deployment name="test-application.war"
runtime-name="test-application.war">
<content sha1="dda9881fa7811b22f1424b4c5acccb13c71202bd"/>
</deployment>
</deployments>
[...]
<server-groups>
<server-group name="main-server-group" profile="default">
[...]
<deployments>
<deployment name="test-application.war" runtime-name="test-application.war"/>
</deployments>
</server-group>
</server-groups>
[...]
(See domain/configuration/domain.xml)
ls domain/content/
|---/47
|-----95cc29338b5049e238941231b36b3946952991
|---/dd
|-----a9881fa7811b22f1424b4c5acccb13c71202bd
Standalone Server
Deployments on a standalone server work in a similar way to those on managed domains. The main
difference is that there are no server group associations.
Deployment Commands
The same CLI commands used for managed domains work for standalone servers when deploying and
removing an application:
WildFly 9
Users are encouraged to use the WildFly 8 management APIs to upload and deploy deployment
content instead of relying on the deployment scanner that periodically scans the directory,
particularly if running production systems.
Deployment Modes
The WildFly 8 filesystem deployment scanner operates in one of two different modes, depending on whether
it will directly monitor the deployment content in order to decide to deploy or redeploy it.
Auto-deploy mode:
The scanner will directly monitor the deployment content, automatically deploying new content and
redeploying content whose timestamp has changed. This is similiar to the behavior of previous AS releases,
although there are differences:
A change in any file in an exploded deployment triggers redeploy. Because EE 6 applications do not
require deployment descriptors,
there is no attempt to monitor deployment descriptors and only redeploy when a deployment
descriptor changes.
The scanner will place marker files in this directory as an indication of the status of its attempts to
deploy or undeploy content. These are detailed below.
Manual deploy mode:
The scanner will not attempt to directly monitor the deployment content and decide if or when the end user
wishes the content to be deployed. Instead, the scanner relies on a system of marker files, with the user's
addition or removal of a marker file serving as a sort of command telling the scanner to deploy, undeploy or
redeploy content.
Auto-deploy mode and manual deploy mode can be independently configured for zipped deployment content
and exploded deployment content. This is done via the "auto-deploy" attribute on the deployment-scanner
element in the standalone.xml configuration file:
By default, auto-deploy of zipped content is enabled, and auto-deploy of exploded content is disabled.
Manual deploy mode is strongly recommended for exploded content, as exploded content is inherently
vulnerable to the scanner trying to auto-deploy partially copied content.
Marker Files
WildFly 9
The marker files always have the same name as the deployment content to which they relate, but with an
additional file suffix appended. For example, the marker file to indicate the example.war file should be
deployed is named example.war.dodeploy. Different marker file suffixes have different meanings.
The relevant marker file types are:
WildFly 9
File
Purpose
.dodeploy
.skipdeploy
.isdeploying
.deployed
.failed
.pending
Basic workflows:
All examples assume variable $JBOSS_HOME points to the root of the WildFly 8 distribution.
WildFly 9
A) Add new zipped content and deploy it:
1. cp target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
B) Add new unzipped content and deploy it:
1. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
C) Undeploy currently deployed content:
1. rm $JBOSS_HOME/standalone/deployments/example.war.deployed
D) Auto-deploy mode only: Undeploy currently deployed content:
1. rm $JBOSS_HOME/standalone/deployments/example.war
E) Replace currently deployed zipped content with a new version and deploy it:
1. cp target/example.war/ $JBOSS_HOME/standalone/deployments
2. (Manual mode only) touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
F) Manual mode only: Replace currently deployed unzipped content with a new version and deploy it:
1. rm $AS/standalone/deployments/example.war.deployed
2. wait for $JBOSS_HOME/standalone/deployments/example.war.undeployed file to appear
3. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
4. touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
G) Auto-deploy mode only: Replace currently deployed unzipped content with a new version and deploy it:
1. touch $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
2. cp -r target/example.war/ $JBOSS_HOME/standalone/deployments
3. rm $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
H) Manual mode only: Live replace portions of currently deployed unzipped content without redeploying:
1. cp -r target/example.war/foo.html $JBOSS_HOME/standalone/deployments/example.war
I) Auto-deploy mode only: Live replace portions of currently deployed unzipped content without redeploying:
1. touch $JBOSS_HOME/standalone/deployments/example.war.skipdeploy
2. cp -r target/example.war/foo.html $JBOSS_HOME/standalone/deployments/example.war
J) Manual or auto-deploy mode: Redeploy currently deployed content (i.e. bounce it with no content change):
1. touch $JBOSS_HOME/standalone/deployments/example.war.dodeploy
K) Auto-deploy mode only: Redeploy currently deployed content (i.e. bounce it with no content change):
WildFly 9
1. touch $JBOSS_HOME/standalone/deployments/example.war
The above examples use Unix shell commands. Windows equivalents are:
cp src dest --> xcopy /y src dest
cp -r src dest --> xcopy /e /s /y src dest
rm afile --> del afile
touch afile --> echo>> afile
Note that the behavior of 'touch' and 'echo' are different but the differences are not relevant to the
usages in the examples above.
<management>
<security-realms>
...
</security-realms>
<audit-log>
<formatters>
<json-formatter name="json-formatter"/>
</formatters>
<handlers>
<file-handler name="file" formatter="json-formatter" path="audit-log.log"
relative-to="jboss.server.data.dir"/>
</handlers>
<logger log-boot="true" log-read-only="true" enabled="false">
<handlers>
<handler name="file"/>
</handlers>
</logger>
</audit-log>
...
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/access=audit:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"file-handler" => {"file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.server.data.dir"
}},
"json-formatter" => {"json-formatter" => {
"compact" => false,
"date-format" => "yyyy-MM-dd HH:mm:ss",
"date-separator" => " - ",
"escape-control-characters" => false,
"escape-new-line" => false,
"include-date" => true
}},
"logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"file" => {}}
}},
"syslog-handler" => undefined
}
}
The audit logging subsystem has a lot of internal dependencies, and it logs operations changing,
enabling and disabling its components. When configuring or changing things at runtime it is a good
idea to make these changes as part of a CLI batch. For example if you are adding a syslog handler
you need to add the handler and its information as one step. Similarly if you are using a file
handler, and want to change its path and relative-to attributes, that needs to happen as one
step.
JSON Formatter
The first thing that needs configuring is the formatter, we currently support outputting log records as JSON.
You can define several formatters, for use with different handlers. A log record has the following format, and
it is the formatter's job to format the data presented:
WildFly 9
2013-08-12 11:01:12 - {
"type" : "core",
"r/o" : false,
"booting" : false,
"version" : "8.0.0.Alpha4",
"user" : "$local",
"domainUUID" : null,
"access" : "NATIVE",
"remote-address" : "127.0.0.1/127.0.0.1",
"success" : true,
"ops" : [JMX|WFLY8:JMX subsystem configuration],
"operation" : "write-attribute",
"name" : "enabled",
"value" : true,
"operation-headers" : {"caller-type" : "user"}
}]
}
It includes an optional timestamp and then the following information in the json record
WildFly 9
Field name
Description
type
This can have the values core, meaning it is a management operation, or jmx
meaning it comes from the jmx subsystem (see the jmx subsystem for configuration of
the jmx subsystem's audit logging)
r/o
true if the operation does not change the management model, false otherwise
booting
true if the operation was executed during the bootup process, false if it was
executed once the server is up and running
version
user
The username of the authenticated user. In this case the operation has been logged
via the CLI on the same machine as the running server, so the special $local user
is used
domainUUID
An ID to link together all operations as they are propagated from the Doman
Controller to it servers, slave Host Controllers, and slave Host Controller servers
access
ops
The operations being executed. This is a list of the operations serialized to JSON. At
boot this will be all the operations resulting from parsing the xml. Once booted the list
will typically just contain a single entry
WildFly 9
Attribute
Description
include-date
date-separator
A string containing characters to separate the date and the rest of the
formatted log message. Will be ignored if include-date=false
date-format
compact
If true will format the JSON on one line. There may still be values
containing new lines, so if having the whole record on one line is
important, set escape-new-line or escape-control-characters to true
escape-control-characters If true it will escape all control characters (ascii entries with a decimal
value < 32) with the ascii code in octal, e.g. a new line becomes '#012'.
If this is true, it will override escape-new-line=false
escape-new-line
If true it will escape all new lines with the ascii code in octal, e.g.
"#012".
Handlers
A handler is responsible for taking the formatted data and logging it to a location. There are currently two
types of handlers, File and Syslog. You can configure several of each type of handler and use them to log
information.
WildFly 9
File handler
The file handlers log the audit log records to a file on the server. The attributes for the file handler are
Attribute
Description
Read
Only
formatter
false
path
false
relative-to
false
true
max-failure-count
false
handler
disabled-due-to-failure true if this handler was disabled due to logging failures
true
Syslog handler
The default configuration does not have syslog audit logging set up. Syslog is a better choice for audit
logging since you can log to a remote syslog server, and secure the authentication to happen over TLS with
client certificate authentication. Syslog servers vary a lot in their capabilities so not all settings in this section
apply to all syslog servers. We have tested with rsyslog.
The address for the syslog handler is
/core-service=management/access=audit/syslog-handler=* and just like file handlers you can
add as many syslog entries as you like. The syslog handler resources reference the main RFC's for syslog a
fair bit, for reference they can be found at:
*http://www.ietf.org/rfc/rfc3164.txt
*http://www.ietf.org/rfc/rfc5424.txt
*http://www.ietf.org/rfc/rfc6587.txt
The syslog handler resource has the following attributes:
WildFly 9
formatter
false
failure-count
true
max-failure-count
false
handler
disabled-due-to-failure true if this handler was disabled due to logging failures
syslog-format
true
false
RFC-5424 or RFC-3164
max-length
false
truncate
UDP
Configures the handler to use UDP to communicate with the syslog server. The address of the UDP resource
is /core-service=management/access=audit/syslog-handler=*/protocol=udp. The attributes
of the UDP resource are:
Attribute Description
host
port
The port of the syslog server listening for the udp requests
WildFly 9
TCP
Configures the handler to use TCP to communicate with the syslog server. The address of the TCP resource
is /core-service=management/access=audit/syslog-handler=*/protocol=tcp. The attributes
of the TCP resource are:
Attribute
Description
host
port
The port of the syslog server listening for the tcp requests
message-transfer The message transfer setting as described in section 3.4 of RFC-6587. This can
either be OCTET_COUNTING as described in section 3.4.1 of RFC-6587, or
NON_TRANSPARENT_FRAMING as described in section 3.4.1 of RFC-6587
TLS
Configures the handler to use TLC to communicate securely with the syslog server. The address of the TLS
resource is /core-service=management/access=audit/syslog-handler=*/protocol=tls. The
attributes of the TLS resource are the same as for TCP:
Attribute
Description
host
port
The port of the syslog server listening for the tls requests
message-transfer The message transfer setting as described in section 3.4 of RFC-6587. This can
either be OCTET_COUNTING as described in section 3.4.1 of RFC-6587, or
NON_TRANSPARENT_FRAMING as described in section 3.4.1 of RFC-6587
If the syslog server's TLS certificate is not signed by a certificate signing authority, you will need to set up a
truststore to trust the certificate. The resource for the trust store is a child of the TLS resource, and the full
address is
/core-service=management/access=audit/syslog-handler=*/protocol=tls/authentication=trustst
. The attributes of the truststore resource are:
Attribute
Description
keystore-password
keystore-path
keystore-relative-to The name of another previously named path, or of one of the standard paths
provided by the system. If keystore-relative-to is provided, the value
of the keystore-path attribute is treated as relative to the path specified by
this attribute
WildFly 9
TLS with Client certificate authentication.
If you have set up the syslog server to require client certificate authentication, when creating your handler
you will also need to set up a client certificate store containing the certificate to be presented to the syslog
server. The address of the client certificate store resource is
Description
keystore-password
key-password
keystore-path
keystore-relative-to The name of another previously named path, or of one of the standard paths
provided by the system. If keystore-relative-to is provided, the value
of the keystore-path attribute is treated as relative to the path specified by
this attribute
Logger configuration
The final part that needs configuring is the logger for the management operations. This references one or
more handlers and is configured at /core-service=management/access=audit/logger=audit-log
. The attributes for this resource are:
Attribute
Description
enabled
log-boot
true to log the management operations when booting the server, false otherwise
log-read-only If true all operations will be audit logged, if false only operations that change the
model will be logged
Then which handlers are used to log the management operations are configured as handler=* children of
the logger.
WildFly 9
[domain@localhost:9990 /]
/host=master/core-service=management/access=audit:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"file-handler" => {
"host-file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.domain.data.dir"
},
"server-file" => {
"formatter" => "json-formatter",
"max-failure-count" => 10,
"path" => "audit-log.log",
"relative-to" => "jboss.server.data.dir"
}
},
"json-formatter" => {"json-formatter" => {
"compact" => false,
"date-format" => "yyyy-MM-dd HH:mm:ss",
"date-separator" => " - ",
"escape-control-characters" => false,
"escape-new-line" => false,
"include-date" => true
}},
"logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"host-file" => {}}
}},
"server-logger" => {"audit-log" => {
"enabled" => false,
"log-boot" => true,
"log-read-only" => false,
"handler" => {"server-file" => {}}
}},
"syslog-handler" => undefined
}
}
We now have two file handlers, one called host-file used to configure the file to log management
operations on the host, and one called server-file used to log management operations executed on the
servers. Then logger=audit-log is used to configure the logger for the host controller, referencing the
host-file handler. server-logger=audit-log is used to configure the logger for the managed
servers, referencing the server-file handler. The attributes for server-logger=audit-log are the
same as for server-logger=audit-log in the previous section. Having the host controller and server
loggers configured independently means we can control audit logging for managed servers and the host
controller independently.
WildFly 9
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:cancel-non-progressing-operation
{
"outcome" => "success",
"result" => "-1155777943"
}
The result value is an internal identification number for the operation that was cancelled.
On a managed domain host controller, the equivalent resource is in the host=<hostname> portion of the
management resource tree:
[domain@localhost:9990 /]
/host=host-a/core-service=management/service=management-operations:cancel-non-progressing-operation{
"outcome" => "success",
"result" => "2156877946"
}
[domain@localhost:9990 /]
/host=host-a/server=server-one/core-service=management/service=management-operations:cancel-non-progressing-op
"outcome" => "success",
"result" => "6497786512"
}
An operation is considered to be not proceeding normally if it has been executing with the exclusive
operation lock held for longer than 15 seconds. Read-only operations do not acquire the exclusive operation
lock, so this operation will not cancel read-only operations. Operations blocking waiting for another operation
to release the exclusive lock will also not be cancelled.
If there isn't any operation that is failing to proceed normally, there will be a failure response:
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:cancel-non-progressing-operation
{
"outcome" => "failed",
"failure-description" => "WFLYDM0089: No operation was found that has been holding the
operation execution write lock for long than [15] seconds",
"rolled-back" => true
}
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:find-non-progressing-operation
{
"outcome" => "success",
"result" => "-1155777943"
}
If there is no non-progressing operation, the outcome will still be success but the result will be undefined.
Once the id of the operation is known, the management resource for the operation can be examined to learn
more about its status.
[standalone@localhost:9990 /]
/core-service=management/service=management-operations/active-operation=-1155777943:read-resource(include-runt
"outcome" => "success",
"result" => {
"access-mechanism" => "undefined",
"address" => [
("deployment" => "example")
],
"caller-thread" => "management-handler-thread - 24",
"cancelled" => false,
"exclusive-running-time" => 101918273645L,
"execution-status" => "awaiting-stability",
"operation" => "deploy",
"running-time" => 101918279999L
}
}
WildFly 9
Field
Meaning
access-mechanism
The mechanism used to submit a request to the server. NATIVE, JMX, HTTP
address
The address of the resource targeted by the operation. The value in the final
element of the address will be '<hidden>' if the caller is not authorized to address
the operation's target resource.
caller-thread
cancelled
exclusive-running-time Amount of time in nanoseconds the operation has been executing with the
exclusive operation execution lock held, or -1 if the operation does not hold the
exclusive execution lock.
execution-status
operation
The name of the operation, or '<hidden>' if the caller is not authorized to address
the operation's target resource.
running-time
Meaning
executing
awaiting-other-operation The caller thread is blocking waiting for another operation to release the
exclusive execution lock
awaiting-stability
The caller thread has made changes to the service container and is waiting for
the service container to stabilize
completing
rolling-back
All currently executing operations can be viewed in one request using the read-children-resources
operation:
WildFly 9
[standalone@localhost:9990 /]
/core-service=management/service=management-operations:read-children-resources(child-type=active-operation){
"outcome" => "success",
"result" => {"-1155777943" => {
"access-mechanism" => "undefined",
"address" => [
("deployment" => "example")
],
"caller-thread" => "management-handler-thread - 24",
"cancelled" => false,
"exclusive-running-time" => 101918273645L,
"execution-status" => "awaiting-stability",
"operation" => "deploy",
"running-time" => 101918279999L
},
{"-1246693202" => {
"access-mechanism" => "undefined",
"address" => [
("core-service" => "management"),
("service" => "management-operations")
],
"caller-thread" => "management-handler-thread - 30",
"cancelled" => false,
"exclusive-running-time" => -1L,
"execution-status" => "executing",
"operation" => "read-children-resources",
"running-time" => 3356000L
}}
}
[standalone@localhost:9990 /]
/core-service=management/service=management-operations/active-operation=-1155777943:cancel
{
"outcome" => "success",
"result" => undefined
}
WildFly 9
Note the blocking timeout is not a guaranteed maximum execution time for an operation. If it only a timeout
that will be enforced at various points during operation execution.
System properties
To set a system property, pass its new value using the standard jvm -Dkey=value options:
$JBOSS_HOME/bin/standalone.sh -Djboss.home.dir=some/location/WildFly/jboss-as \
-Djboss.server.config.dir=some/location/WildFly/jboss-as/custom-standalone
This command starts up a standalone server instance using a non-standard AS home directory and a
custom configuration directory. For specific information about system properties, refer to the definitions
below.
Instead of passing the parameters directly, you can put them into a properties file, and pass the properties
file to the script, as in the two examples below.
$JBOSS_HOME/bin/domain.sh --properties=/some/location/jboss.properties
$JBOSS_HOME/bin/domain.sh -P=/some/location/jboss.properties
WildFly 9
Note however, that properties set this way are not processed as part of JVM launch. They are processed
early in the boot process, but this mechanism should not be used for setting properties that control JVM
behavior (e.g. java.net.perferIPv4Stack) or the behavior of the JBoss Modules classloading system.
The syntax for passing in parameters and properties files is the same regardless of whether you are running
the domain.sh, standalone.sh, or the Microsoft Windows scriptsdomain.bat or standalone.bat.
The properties file is a standard Java property file containing key=value pairs:
jboss.home.dir=/some/location/WildFly/jboss-as
jboss.domain.config.dir=/some/location/WildFly/custom-domain
System properties can also be set via the xml configuration files. Note however that for a standalone server
properties set this way will not be set until the xml configuration is parsed and the commands created by the
parser have been executed. So this mechanism should not be used for setting properties whose value needs
to be set before this point.
Standalone
Property name
Usage
Default value
java.ext.dirs
null
jboss.home.dir
Set by standalone.sh to
installation.
$JBOSS_HOME
jboss.home.dir/standalone
jboss.server.base.dir
jboss.server.base.dir
/configuration
jboss.server.data.dir
jboss.server.log.dir
jboss.server.base.dir
file storage.
/data
jboss.server.base.dir/log
server.log file.
jboss.server.temp.dir
jboss.server.base.dir/tmp
storage.
jboss.server.deploy.dir The directory used to store deployed
content
jboss.server.data.dir
/content
WildFly 9
Managed Domain
Property name
Usage
Default value
jboss.home.dir
Set by domain.sh to
installation.
$JBOSS_HOME
jboss.home.dir/domain
jboss.domain.base.dir
content.
jboss.domain.config.dir
jboss.domain.base.dir
/configuration
jboss.domain.data.dir
jboss.domain.log.dir
jboss.domain.base.dir
file storage.
/data
jboss.domain.base.dir
host-controller.log and
/log
process-controller.log files
jboss.domain.temp.dir
jboss.domain.base.dir
storage
/tmp
jboss.domain.servers.dir
jboss.domain.base.dir
content
/content
jboss.domain.base.dir
/servers
--name=value
For example:
$JBOSS_HOME/bin/standalone.sh --server-config=standalone-ha.xml
If the parameter name is a single character, it is prefixed by a single '-' instead of two. Some parameters
have both a long and short option.
-x=value
For example:
WildFly 9
$JBOSS_HOME/bin/standalone.sh -P=/some/location/jboss.properties
For some command line arguments frequently used in previous major releases of WildFly, replacing the "="
in the above examples with a space is supported, for compatibility.
-b 192.168.100.10
If possible, use the -x=value syntax. New parameters will always support this syntax.
The sections below describe the command line parameter names that are available in standalone and
domain mode.
Standalone
Name
Default if
Value
absent
--admin-only
--server-config
-c
--read-only-server-config -
WildFly 9
Managed Domain
Name
Default if
Value
absent
-
--admin-only
--domain-config
-c
--host-config
host.xml
--read-only-host-config
The following parameters take no value and are only usable on slave host controllers (i.e. hosts configured
to connect to a remote domain controller.)
Name
Function
--backup
Causes the slave host controller to create and maintain a local copy of the domain
configuration file
--cached-dc If the slave host controller is unable to contact the master domain controller to get its
configuration at boot, boot from a local copy previously created using --backup. The
slave host controller will not be able make any modifications to the domain configuration,
but it will be able to launch servers.
WildFly 9
Common parameters
These parameters apply in both standalone or managed domain mode:
Name
Function
-b=<value>
--version
Prints the version of WildFly to standard output and exits the JVM.
-v
-V
--help
Prints a help message explaining the options and exits the JVM.
-h
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
</interfaces>
WildFly 9
$JBOSS_HOME/bin/standalone.sh -b=192.168.100.10
In the standard config files, public interfaces are those not associated with server management. Public
interfaces handle normal end-user requests.
Interface names
The interface named "public" is not inherently special. It is provided as a convenience. You can
name your interfaces to suit your environment.
To bind the public interfaces to all IPv4 addresses (the IPv4 wildcard address), use the following syntax:
$JBOSS_HOME/bin/standalone.sh -b=0.0.0.0
$JBOSS_HOME/bin/standalone.sh -bmanagement=192.168.100.10
In the standard config files, management interfaces are those sockets associated with server management,
such as the socket used by the CLI, the HTTP socket used by the admin console, and the JMX connector
socket.
Be Careful
The -b switch only controls the interface bindings because the standard config files that ship with
WildFly sets things up that way. If you change the <interfaces> section in your configuration to
ignore the system properties controlled by -b, then setting -b in your launch command will have no
effect.
For example, this perfectly valid setting for the "public" interface causes -b to have no effect on
the "public" interface:
<interface name="public">
<nic name="eth0"/>
</interface>
The key point is the contents of the configuration files determine the configuration. Settings
like -b are not overrides of the configuration files. They only provide a shorter syntax for
setting a system properties that may or may not be referenced in the configuration files. They are
provided as a convenience, and you can choose to modify your configuration to ignore them.
WildFly 9
$JBOSS_HOME/bin/standalone.sh -u=230.0.1.2
Be Careful
As with the -b switch, the -u switch only controls the multicast address used because the standard
config files that ship with WildFly 8 sets things up that way. If you change the <socket-binding>
sections in your configuration to ignore the system properties controlled by -u, then setting -u in
your launch command will have no effect.
WildFly 9
As mentioned in Command line parameters#parameters the default configuration file can be selected using
a command-line parameter. For a standalone server instance the history of the active standalone.xml is
kept in jboss.server.config.dir/standalone_xml_history (See Command line
parameters#standalone_system_properties for more details). For a domain the active domain.xml and
host.xml histories are kept in jboss.domain.config.dir/domain_xml_history and
jboss.domain.config.dir/host_xml_history.
The rest of this section will only discuss the history for standalone.xml. The concepts are exactly the
same for domain.xml and host.xml.
Within standalone_xml_history itself following a successful first time boot we end up with three new
files:
*standalone.initial.xml - This contains the original configuration that was used the first time we
successfully booted. This file will never be overwritten. You may of course delete the history directory and
any files in it at any stage.
*standalone.boot.xml - This contains the original configuration that was used for the last successful
boot of the server. This gets overwritten every time we boot the server successfully.
*standalone.last.xml - At this stage the contents will be identical to standalone.boot.xml.
This
file gets overwritten each time the server successfully writes the
configuration, if there was an unexpected failure writing the configuration this
file is the last known successful write.
standalone_xml_history contains a directory called current which should be empty. Now if we
execute a management operation that modifies the model, for example adding a new system property using
the CLI:
[standalone@localhost:9999 /] /system-property=test:add(value="test123")
{"outcome" => "success"}
WildFly 9
Snapshots
In addition to the backups taken by the server as described above you can manually take take snapshots
which will be stored in the snapshot folder under the _xml_history folder, the automatic backups
described above are subject to automatic house keeping so will eventually be automatically removed, the
snapshots on the other hand can be entirely managed by the administrator.
You may also take your own snapshots using the CLI:
[standalone@localhost:9999 /] :take-snapshot
{
"outcome" => "success",
"result" => {"name" =>
"/Users/kabir/jboss-7.0.0.CR1/standalone/configuration/standalone_xml_history/snapshot/20110630-172258657stand
You can also use the CLI to list all the snapshots
[standalone@localhost:9999 /] :list-snapshots
{
"outcome" => "success",
"result" => {
"directory" =>
"/Users/kabir/jboss-7.0.0.CR1/standalone/configuration/standalone_xml_history/snapshot",
"names" => [
"20110630-165714239standalone.xml",
"20110630-165821795standalone.xml",
"20110630-170113581standalone.xml",
"20110630-171411463standalone.xml",
"20110630-171908397standalone.xml",
"20110630-172258657standalone.xml"
]
}
}
[standalone@localhost:9999 /] :delete-snapshot(name="20110630-165714239standalone.xml")
{"outcome" => "success"}
[standalone@localhost:9999 /] :delete-snapshot(name="all")
{"outcome" => "success"}
In domain mode executing the snapshot operations against the root node will work against the domain
model. To do this for a host model you need to navigate to the host in question:
WildFly 9
[domain@localhost:9999 /] /host=master:list-snapshots
{
"outcome" => "success",
"result" => {
"domain-results" => {"step-1" => {
"directory" =>
"/Users/kabir/jboss-7.0.0.CR1/domain/configuration/host_xml_history/snapshot",
"names" => [
"20110630-141129571host.xml",
"20110630-172522225host.xml"
]
}},
"server-operations" => undefined
}
}
Subsequent Starts
For subsequent server starts it may be desirable to take the state of the server back to one of the previously
known states, for a number of items an abbreviated reverence to the file can be used: Abreviation Parameter
initial
Description
--server-config=initial This will start the server using the initial configuration first
used to start the server.
boot
--server-config=boot
This will use the configuration from the last successful boot
of the server.
last
--server-config=last
v?
--server-config=v?
???? -
--server-config=???? -
?????
?????
In addition to this the --server-config parameter can always be used to specify a configuration relative
to the jboss.server.config.dir and finally if no matching configuration is found an attempt to locate
the configuration as an absolute path will be made.
WildFly 9
Managed Domain
In a managed domain the JVM settings can be declared at different scopes: For a specific server group, for
a host or for a particular server. If not declared, the settings are inherited from the parent scope. This allows
you to customize or extend the JVM settings within every layer.
Let's take a look at the JVM declaration for a server group:
WildFly 9
<server-groups>
<server-group name="main-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
<server-group name="other-server-group" profile="default">
<jvm name="default">
<heap size="64m" max-size="512m"/>
</jvm>
<socket-binding-group ref="standard-sockets"/>
</server-group>
</server-groups>
(See
domain/configuration/domain.xml)
In this example the server group "main-server-group" declares a heap size of 64m and a maximum heap size
of 512m. Any server that belongs to this group will inherit these settings. You can change these settings for
the group as a whole, or a specific server or host:
<servers>
<server name="server-one" group="main-server-group" auto-start="true">
<jvm name="default"/>
</server>
<server name="server-two" group="main-server-group" auto-start="true">
<jvm name="default">
<heap size="64m" max-size="256m"/>
</jvm>
<socket-binding-group ref="standard-sockets" port-offset="150"/>
</server>
<server name="server-three" group="other-server-group" auto-start="false">
<socket-binding-group ref="standard-sockets" port-offset="250"/>
</server>
</servers>
(See domain/configuration/host.xml)
In this case, server-two, belongs to the main-server-group and inherits the JVM settings named default, but
declares a lower maximum heap size.
[domain@localhost:9999 /] /host=local/server-config=server-two/jvm=default:read-resource
{
"outcome" => "success",
"result" => {
"heap-size" => "64m",
"max-heap-size" => "256m",
}
}
WildFly 9
Standalone Server
For a standalone sever you have to pass in the JVM settings either as command line arguments when
executing the $JBOSS_HOME/bin/standalone.sh script, or by declaring them in
$JBOSS_HOME/bin/standalone.conf. (For Windows users, the script to execute is
%JBOSS_HOME%/bin/standalone.bat while the JVM settings can be declared in
%JBOSS_HOME%/bin/standalone.conf.bat.)
[domain@localhost:9999 /] :read-children-names(child-type=host)
{
"outcome" => "success",
"result" => ["local"]
}
[domain@localhost:9999 /] /host=local:read-children-names(child-type=server-config)
{
"outcome" => "success",
"result" => [
"my-server",
"server-one",
"server-three"
]
}
Now that we know, that there are two servers configured on host "local", we can go ahead and check
their status:
WildFly 9
[domain@localhost:9999 /]
/host=local/server-config=server-one:read-resource(include-runtime=true)
{
"outcome" => "success",
"result" => {
"auto-start" => true,
"group" => "main-server-group",
"interface" => undefined,
"name" => "server-one",
"path" => undefined,
"socket-binding-group" => undefined,
"socket-binding-port-offset" => undefined,
"status" => "STARTED",
"system-property" => undefined,
"jvm" => {"default" => undefined}
}
}
You can change the server state through the "start" and "stop" operations
[domain@localhost:9999 /] /host=local/server-config=server-one:stop
{
"outcome" => "success",
"result" => "STOPPING"
}
Navigating through the domain topology is much more simple when you use the web interface.
WildFly 9
WildFly 9
Subsystem Integrations
Suspend/Resume is a service provided by the Wildfly platform that any subsystem may choose to integrate
with. Some subsystems integrate directly with the suspend controller, while others integrate through the
request controller subsystem.
The following subsystems support graceful shutdown. Note that only subsystems that provide an external
entry point to the server need graceful shutdown support, for example the JAX-RS subsystem does not
require suspend/resume support as all access to JAX-RS is through the web connector.
Undertow - Undertow will wait for all requests to finish
mod_cluster - The mod_cluster subsystem will notify the load balancer that the server is suspending
in the PRE_SUSPEND phase.
EJB - EJB will wait for all remote EJB requests and MDB message deliveries to finish. Delivery to
MDB's is stopped in the PRE_SUSPEND phase. EJB timers are suspended, and missed timers will
be activated when the server is resumed.
Batch - The server will wait for Batch jobs to finish.
EE Concurrency - The server will wait for all active jobs to finish.
Standalone Mode
Suspend/Resume can be controlled via the following CLI operations in standalone mode:
:suspend(timeout=z)
Suspends the server. If the timeout is specified it will wait up till the timeout for all requests to finish. If there
is no timeout specified it will wait indefinitely.
:resume
Resumes a previously suspended server. The server should be able to begin serving requests immediately.
:read-attribute(name=suspend-state)
Returns the current suspend state of the server.
:shutdown(timeout=x)
If a timeout parameter is passed to the shutdown command then a graceful shutdown will be performed. The
server will be suspended, and will wait until the timeout for all requests to finish before shutting down.
WildFly 9
Domain Mode
Domain mode has similar commands as standalone mode, however they can be applied at both the global
and server group levels:
Whole Domain
:suspend-servers(timeout=x)
:resume-servers
:stop-servers(timeout=x)
Server Group
/server-group=main-server-group:suspend-servers(timeout=x)
/server-group=main-server-group:resume-servers
/server-group=main-server-group:stop-servers(timeout=x)
Server
/host=master/server-config=server-one:suspend(timeout=x)
/host=master/server-config=server-one:resume
/host=master/server-config=server-one:stop(timeout=x)
WildFly 9
<management>
. . .
<access-control provider="simple">
<role-mapping>
<role name="SuperUser">
<include>
<user name="$local"/>
</include>
</role>
</role-mapping>
</access-control>
</management>
As you can see, the provider is set to "simple" by default. With the "simple" provider, the nested
"role-mapping" section is not actually relevant. It's there to help ensure that if the provider attribute is
switched to "rbac" there will be at least one user mapped to a role that can continue to administer the
system. This default mapping assigns the "$local" user name to the RBAC role that provides all permissions,
the "SuperUser" role. The "$local" user name is the name an administrator will be assigned if he or she uses
the CLI on the same system as the WildFly instance and the "local" authentication scheme is enabled.
WildFly 9
RBAC roles
The seven standard roles are divided into two broad categories, based on whether the role can deal with
items that are considered to be "security sensitive". Resources, attributes and operations that may affect
administrative security (e.g. security realm resources and attributes that contain passwords) are "security
sensitive".
Four roles are not given permissions for "security sensitive" items:
Monitor a read-only role. Cannot modify any resource.
Operator Monitor permissions, plus can modify runtime state, but cannot modify anything that ends
up in the persistent configuration. Could, for example, restart a server.
Maintainer Operator permissions, plus can modify the persistent configuration.
Deployer like a Maintainer, but with permission to modify persistent configuration constrained to
resources that are considered to be "application resources". A deployment is an application resource.
The messaging server is not. Items like datasources and JMS destinations are not considered to be
application resources by default, but this is configurable.
Three roles are granted permissions for security sensitive items:
SuperUser has all permissions. Equivalent to a JBoss AS 7 administrator.
Administrator has all permissions except cannot read or write resources related to the administrative
audit logging system.
Auditor can read anything. Can only modify the resources related to the administrative audit logging
system.
The Auditor and Administrator roles are meant for organizations that want a separation of responsibilities
between those who audit normal administrative actions and those who perform them, with those who
perform most actions (Administrator role) not being able to read or alter the auditing configuration.
WildFly 9
Addressing a resource
As mentioned above, permissions are granted to perform one of three actions, addressing a resource,
reading it, and modifying. The latter two actions are fairly self-explanatory. But what is meant by
"addressing" a resource?
"Addressing" a resource refers to taking an action that allows the user to determine whether a resource at a
given address actually exists. For example, the "read-children-names" operation lets a user determine valid
addresses. Trying to read a resource and getting a "Permission denied" error also gives the user a clue that
there actually is a resource at the requested address.
Some resources may include sensitive information as part of their address. For example, security realm
resources include the realm name as the last element in the address. That realm name is potentially security
sensitive; for example it is part of the data used when creating a hash of a user password. Because some
addresses may contain security sensitive data, a user needs permission to even "address" a resource. If a
user attempts to address a resource and does not have permission, they will not receive a "permission
denied" type error. Rather, the system will respond as if the resource does not even exist, e.g. excluding the
resource from the result of the "read-children-names" operation or responding with a "No such resource"
error instead of "Permission denied" if the user is attempting to read or write the resource.
Another term for "addressing" a resource is "looking up" the resource.
Before changing the provider to "rbac", be sure your configuration has a user who will be mapped
to one of the RBAC roles, preferably with at least one in the Administrator or SuperUser role.
Otherwise your installation will not be manageable except by shutting it down and editing the xml
configuration. If you have started with one of the standard xml configurations shipped with WildFly,
the "$local" user will be mapped to the "SuperUser" role and the "local" authentication scheme will
be enabled. This will allow a user running the CLI on the same system as the WildFly process to
have full administrative permissions. Remote CLI users and web-based admin console users will
have no permissions.
We recommend mapping at least one user besides "$local" before switching the provider to "rbac".
You can do all of the configuration associated with the "rbac" provider even when the provider is
set to "simple"
WildFly 9
[standalone@localhost:9990 /] cd core-service=management/access=authorization
[standalone@localhost:9990 access=authorization] :write-attribute(name=provider,value=rbac)
{
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}
[standalone@localhost:9990 access=authorization] reload
In a managed domain, the access control configuration is part of the domain wide configuration, so the
resource address is the same as above:
[domain@localhost:9990 /] cd core-service=management/access=authorization
[domain@localhost:9990 access=authorization] :write-attribute(name=provider,value=rbac)
{
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
},
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}},
"server-two" => {"response" => {
"outcome" => "success",
"response-headers" => {
"operation-requires-reload" => true,
"process-state" => "reload-required"
}
}}
}}}}
}
[domain@localhost:9990 access=authorization] reload --host=master
As with a standalone server, a reload is required for the change to take effect. In this case, all hosts and
servers in the domain will need to be restarted, so be sure to plan well before making this change.
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator:add
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
Once this is done, map a user to the role:
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=user-jsmith:add(name=jsmith,t
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Now if user jsmith authenticates to any security realm associated with the management interface they are
using, he will be mapped to the Administrator role.
To restrict the mapping to a particular security realm, change the realm attribute to the realm name. This
might be useful if different realms are associated with different management interfaces, and the goal is to
limit a user to a particular interface.
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=user-mjones:add(name=mjones,t
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
User groups
A "group" is an arbitrary collection of users that may exist in the end user environment. They can be named
whatever the end user organization wants and can contain whatever users the end user organization wants.
Some of the authentication store types supported by WildFly security realms include the ability to access
information about what groups a user is a member of and associate this information with the Subject
produced when the user is authenticated. This is currently supported for the following authentication store
types:
properties file (via the <realm_name>-groups.properties file)
LDAP (via directory-server-specific configuration)
Groups are convenient when it comes to associating a user with a role, since entire groups can be
associated with a role in a single mapping.
WildFly 9
Navigate to the "Administration" tab and the "Groups" subtab. From there group mappings can be added,
removed, or edited.
The CLI can also be used to map groups to roles. The only difference to individual user mapping is the value
of the type attribute should be GROUP instead of USER.
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=group-SeniorAdmins:add(name=S
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
As with individual user mappings, the mapping can be restricted to users authenticating via a particular
security realm:
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Administrator/include=group-PowerAdmins:add(name=Po
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
A user who can authenticate to the management security realm but who does not map to a role will
not be able to perform any administrative functions, not even reads.
In the web based admin console, navigate to the "Administration" tab, "Roles" subtab, highlight the relevant
role, click the "Edit" button and click on the "Include All" checkbox:
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Monitor:write-attribute(name=include-all,value=true
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
In the CLI, excludes are identical to includes, except the resource address has exclude instead of
include as the key for the last address element:
[domain@localhost:9990 /]
/core-service=management/access=authorization/role-mapping=Monitor/exclude=group-Temps:add(name=Temps,type=GRO
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
[standalone@localhost:9990 /] cd core-service=management/access=authorization
[standalone@localhost:9990 access=authorization]
:write-attribute(name=permission-combination-policy,value=rejecting)
{"outcome" => "success"}
[standalone@localhost:9990 /] cd core-service=management/access=authorization
[standalone@localhost:9990 access=authorization]
:write-attribute(name=permission-combination-policy,value=permissive)
{"outcome" => "success"}
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/server-group-scoped-role=MainGroupAdmins:add(base-role=Administr
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Once the role is created, users or groups can be mapped to it the same as with the seven standard roles.
WildFly 9
[domain@localhost:9990 /]
/core-service=management/access=authorization/host-scoped-role=MasterOperators:add(base-role=Operator,hosts=[m
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Once the role is created, users or groups can be mapped to it the same as with the seven standard roles.
WildFly 9
When adding a new scoped role, use the dialogue's "Type" pull down to choose between a host scoped role
and a server-group scoped role. Then place the names of the relevant hosts or server groups in the "Scope"
text are.
WildFly 9
WildFly 9
Configuring sensitivity
"Sensitivity" constraints are about restricting access to security-sensitive data. Different organizations may
have different opinions about what is security sensitive, so WildFly provides configuration options to allow
users to tailor these constraints.
[domain@localhost:9990 /] cd
core-service=management/access=authorization/constraint=sensitivity-classification/type=core/classification=so
classification=socket-config] ls -l
ATTRIBUTE
VALUE
TYPE
configured-requires-addressable undefined BOOLEAN
configured-requires-read
undefined BOOLEAN
configured-requires-write
undefined BOOLEAN
default-requires-addressable
false
BOOLEAN
default-requires-read
false
BOOLEAN
default-requires-write
true
BOOLEAN
CHILD
MIN-OCCURS MAX-OCCURS
applies-to n/a
n/a
The various default-requires-... attributes indicate whether a user must be in a role that allows
security sensitive actions in order to perform the action. In the socket-config example above,
default-requires-write is true, while the others are false. So, by default modifying a setting involving
socket configuration is considered sensitive, while addressing those resources or doing reads is not
sensitive.
The default-requires-... attributes are read-only. The configured-requires-... attributes
however can be modified to override the default settings with ones appropriate for your organization. For
example, if your organization doesn't regard modifying socket configuration settings to be security sensitive,
you can change that setting:
WildFly 9
[domain@localhost:9990 classification=socket-config]
:write-attribute(name=configured-requires-write,value=false)
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
Administrators can also read the management model to see to which resources, attributes and operations a
particular sensitivity classification applies:
[domain@localhost:9990 classification=socket-config]
:read-children-resources(child-type=applies-to)
{
"outcome" => "success",
"result" => {
"/host=master" => {
"address" => "/host=master",
"attributes" => [],
"entire-resource" => false,
"operations" => ["resolve-internet-address"]
},
"/host=master/core-service=host-environment" => {
"address" => "/host=master/core-service=host-environment",
"attributes" => [
"host-controller-port",
"host-controller-address",
"process-controller-port",
"process-controller-address"
],
"entire-resource" => false,
"operations" => []
},
"/host=master/core-service=management/management-interface=http-interface" => {
"address" =>
"/host=master/core-service=management/management-interface=http-interface",
"attributes" => [
"port",
"secure-interface",
"secure-port",
"interface"
],
"entire-resource" => false,
"operations" => []
},
"/host=master/core-service=management/management-interface=native-interface" => {
"address" =>
"/host=master/core-service=management/management-interface=native-interface",
"attributes" => [
"port",
"interface"
WildFly 9
],
"entire-resource" => false,
"operations" => []
},
"/host=master/interface=*" => {
"address" => "/host=master/interface=*",
"attributes" => [],
"entire-resource" => true,
"operations" => ["resolve-internet-address"]
},
"/host=master/server-config=*/interface=*" => {
"address" => "/host=master/server-config=*/interface=*",
"attributes" => [],
"entire-resource" => true,
"operations" => []
},
"/interface=*" => {
"address" => "/interface=*",
"attributes" => [],
"entire-resource" => true,
"operations" => []
},
"/profile=*/subsystem=messaging/hornetq-server=*/broadcast-group=*" => {
"address" => "/profile=*/subsystem=messaging/hornetq-server=*/broadcast-group=*",
"attributes" => [
"group-address",
"group-port",
"local-bind-address",
"local-bind-port"
],
"entire-resource" => false,
"operations" => []
},
"/profile=*/subsystem=messaging/hornetq-server=*/discovery-group=*" => {
"address" => "/profile=*/subsystem=messaging/hornetq-server=*/discovery-group=*",
"attributes" => [
"group-address",
"group-port",
"local-bind-address"
],
"entire-resource" => false,
"operations" => []
},
"/profile=*/subsystem=transactions" => {
"address" => "/profile=*/subsystem=transactions",
"attributes" => ["process-id-socket-max-ports"],
"entire-resource" => false,
"operations" => []
},
"/server-group=*" => {
"address" => "/server-group=*",
"attributes" => ["socket-binding-port-offset"],
"entire-resource" => false,
"operations" => []
},
"/socket-binding-group=*" => {
"address" => "/socket-binding-group=*",
"attributes" => [],
WildFly 9
"entire-resource" => true,
"operations" => []
}
}
}
There will be a separate child for each address to which the classification applies. The entire-resource
attribute will be true if the classification applies to the entire resource. Otherwise, the attributes and
operations attributes will include the names of attributes or operations to which the classification applies.
Description
credential
security-domain-ref An attribute whose value is the name of a security domain. By default sensitive for
both reads and writes
security-realm-ref
An attribute whose value is the name of a security realm. By default sensitive for both
reads and writes
socket-binding-ref
An attribute whose value is the name of a socket binding. By default not sensitive for
any action
socket-config
[domain@localhost:9990 /] cd
core-service=management/access=authorization/constraint=vault-expression
[domain@localhost:9990 constraint=vault-expression] ls -l
ATTRIBUTE
VALUE
TYPE
configured-requires-read undefined BOOLEAN
configured-requires-write undefined BOOLEAN
default-requires-read
true
BOOLEAN
default-requires-write
true
BOOLEAN
WildFly 9
The various default-requires-... attributes indicate whether a user must be in a role that allows
security sensitive actions in order to perform the action. So, by default both reading and writing attributes
whose values include vault expressions requires a user to be in one of the roles with sensitive data
permissions.
The default-requires-... attributes are read-only. The configured-requires-... attributes
however can be modified to override the default settings with settings appropriate for your organization. For
example, if your organization doesn't regard reading vault expressions to be security sensitive, you can
change that setting:
[domain@localhost:9990 constraint=vault-expression]
:write-attribute(name=configured-requires-read,value=false)
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
This vault-expression constraint overlaps somewhat with the core "credential" sensitivity
classification in that the most typical uses of a vault expression are in attributes that contain a user
name or password, and those will typically be annotated with the "credential" sensitivity
classification. So, if you change the settings for the "credential" sensitivity classification you may
also need to make a corresponding change to the vault-expression constraint settings, or your
change will not have full effect.
Be aware though, that vault expressions can be used in any attribute that supports expressions,
not just in credential-type attributes. So it is important to be familiar with where and how your
organization uses vault expressions before changing these settings.
WildFly 9
[domain@localhost:9990 /] cd
/core-service=management/access=authorization/constraint=application-classification/type=mail/classification=m
classification=mail-session] ls -l
ATTRIBUTE
VALUE
TYPE
configured-application undefined BOOLEAN
default-application
false
BOOLEAN
CHILD
MIN-OCCURS MAX-OCCURS
applies-to n/a
n/a
[domain@localhost:9990 classification=mail-session]
:read-children-resources(child-type=applies-to)
{
"outcome" => "success",
"result" => {"/profile=*/subsystem=mail/mail-session=*" => {
"address" => "/profile=*/subsystem=mail/mail-session=*",
"attributes" => [],
"entire-resource" => true,
"operations" => []
}}
}
This indicates that this classification, intuitively enough, only applies to mail subsystem mail-session
resources.
To make resources with this classification writeable by users in the Deployer role, set the
configured-application attribute to true.
[domain@localhost:9990 classification=mail-session]
:write-attribute(name=configured-application,value=true)
{
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {"master" => {
"server-one" => {"response" => {"outcome" => "success"}},
"server-two" => {"response" => {"outcome" => "success"}}
}}}}
}
WildFly 9
Classification
datasources
data-source
datasources
jdbc-driver
datasources
xa-data-source
logging
logger
logging
logging-profile
mail-session
messaging
jms-queue
messaging
jms-topic
messaging
queue
messaging
security-setting
naming
binding
resource-adapters resource-adapter
security
security-domain
In each case the classification applies to the resources you would expect, given its name.
Admin console
The admin console takes great pains to provide a good user experience even when the user has reduced
permissions. Resources the user is not permitted to see will simply not be shown, or if appropriate will be
replaced in the UI with an indication that the user is not authorized. Interaction units like "Add" and "Remove"
buttons and "Edit" links will be suppressed if the user has no write permissions.
WildFly 9
CLI
The CLI is a much more unconstrained tool than the admin console is, allowing users to try to execute
whatever operations they wish, so it's more likely that users who attempt to do things for which they lack
necessary permissions will receive failure messages. For example, a user in the Monitor role cannot read
passwords:
[domain@localhost:9990 /]
/profile=default/subsystem=datasources/data-source=ExampleDS:read-attribute(name=password)
{
"outcome" => "failed",
"result" => undefined,
"failure-description" => "WFLYCTL0313: Unauthorized to execute operation 'read-attribute'
for resource '[
(\"profile\" => \"default\"),
(\"subsystem\" => \"datasources\"),
(\"data-source\" => \"ExampleDS\")
]' -- \"WFLYCTL0332: Permission denied\"",
"rolled-back" => true
}
If the user isn't even allowed to address the resource then the response would be as if the resource doesn't
exist, even though it actually does:
[domain@localhost:9990 /]
/profile=default/subsystem=security/security-domain=other:read-resource
{
"outcome" => "failed",
"failure-description" => "WFLYCTL0216: Management resource '[
(\"profile\" => \"default\"),
(\"subsystem\" => \"security\"),
(\"security-domain\" => \"other\")
]' not found",
"rolled-back" => true
}
This prevents unauthorized users fishing for sensitive data in resource addresses by checking for
"Permission denied" type failures.
Users who use the read-resource operation may ask for data, some of which they are allowed to see and
some of which they are not. If this happens, the request will not fail, but inaccessible data will be elided and
a response header will be included advising on what was not included. Here we show the effect of a Monitor
trying to recursively read the security subsystem configuration:
WildFly 9
[domain@localhost:9990 /] /profile=default/subsystem=security:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"deep-copy-subject-mode" => undefined,
"security-domain" => undefined,
"vault" => undefined
},
"response-headers" => {"access-control" => [{
"absolute-address" => [
("profile" => "default"),
("subsystem" => "security")
],
"relative-address" => [],
"filtered-attributes" => ["deep-copy-subject-mode"],
"filtered-children-types" => ["security-domain"]
}]}
}
The response-headers section includes access control data in a list with one element per relevant
resource. (In this case there's just one.) The absolute and relative address of the resource is shown, along
with the fact that the value of the deep-copy-subject-mode attribute has been filtered (i.e. undefined is
shown as the value, which may not be the real value) as well as the fact that child resources of type
security-domain have been filtered.
WildFly 9
[domain@localhost:9990 /] cd /profile=default/subsystem=mail/mail-session=default/server=smtp
[domain@localhost:9990 server=smtp] :read-resource-description(access-control=trim-descriptions)
{
"outcome" => "success",
"result" => {
"description" => undefined,
"access-constraints" => {"application" => {"mail-session" => {"type" => "mail"}}},
"attributes" => undefined,
"operations" => undefined,
"children" => {},
"access-control" => {
"default" => {
"read" => true,
"write" => false,
"attributes" => {
"outbound-socket-binding-ref" => {
"read" => true,
"write" => false
},
"username" => {
"read" => false,
"write" => false
},
"tls" => {
"read" => true,
"write" => false
},
"ssl" => {
"read" => true,
"write" => false
},
"password" => {
"read" => false,
"write" => false
}
}
},
"exceptions" => {}
}
}
}
Because trim-descriptions was used as the value for the access-control parameter, the typical
"description", "attributes", "operations" and "children" data is largely suppressed. (For more on this, see
below.) The access-constraints field indicates that this resource is annotated with an application
constraint. The access-control field includes information about the permissions the current caller has for
this resource. The default section shows the default settings for resources of this type. The read and
write fields directly under default show that the caller can, in general, read this resource but cannot write
it. The attributes section shows the individual attribute settings. Note that Monitor cannot read the
username and password attributes.
WildFly 9
There are three valid values for the access-control parameter to read-resource-description and
read-operation-description:
none do not include access control information in the response. This is the default behavior if no
parameter is included.
trim-descriptions remove the normal description details, as shown in the example above
combined-descriptions include both the normal output and the access control data
CLI users should use the whoami operation with the verbose attribute set:
[domain@localhost:9990 /] :whoami(verbose=true)
{
"outcome" => "success",
"result" => {
"identity" => {
"username" => "aadams",
"realm" => "ManagementRealm"
},
"mapped-roles" => [
"Maintainer"
]
}
}
WildFly 9
CLI run-as
With the CLI, run-as capability is on a per-request basis. It is done by using the "roles" operation header, the
value of which can be the name of a single role or a bracket-enclosed, comma-delimited list of role names.
Example with a low level operation:
[standalone@localhost:9990 /] :whoami(verbose=true){roles=[Operator,Auditor]}
{
"outcome" => "success",
"result" => {
"identity" => {
"username" => "$local",
"realm" => "ManagementRealm"
},
"mapped-roles" => [
"Auditor",
"Operator"
]
}
}
Here we show the effect of switching to a role that isn't granted the necessary permission.
WildFly 9
The console will need to be restarted in order for the change to take effect.
WildFly 9
WildFly 9
<security-realm name="ManagementRealm">
<plug-ins></plug-ins>
<server-identities></server-identities>
<authentication></authentication>
<authorization></authorization>
</security-realm>
plug-ins - This is an optional element that is used to define modules what will be searched for
security realm PlugInProviders to extend the capabilities of the security realms.
server-identities - An optional element to define the identity of the server as visible to the
outside world, this applies to both inbound connection to a resource secured by the realm and to
outbound connections also associated with the realm.
One example is the SSL identity of the server, for inbound connections this will control the identity of the
server as the SSL connection is established, for outbound connections this same identity can be used where
CLIENT-CERT style authentication is being performed.
A second example is where the server is establishing an outbound connection that requires username /
password authentication - this element can be used to define that password.
authentication - This is probably the most important element that will be used within a security
realm definition and mostly applies to inbound connections to the server, this element defines which
backing stores will be used to provide the verification of the inbound connection.
This element is optional as there are some scenarios where it will not be required such as if a realm is being
defined for an outbound connection using a username and password.
authorization - This is the final optional element and is used to define how roles are loaded for an
authenticated identity. At the moment this is more applicable for realms used for access to EE
deployments such as web applications or EJBs but this will also become relevant as we add role
based authorization checks to the management model.
WildFly 9
Inbound Connections
Management Interfaces
Either within the standalone.xml or host.xml configurations the security realms can be associated with
the management interfaces as follows: -
<native-interface security-realm="ManagementRealm">...</native-interface>
<http-interface security-realm="ManagementRealm">...</http-interface>
If the security-realm attribute is omitted or removed from the interface definition it means that access to
that interface will be unsecured
By default we do bind these interfaces to the loopback address so that the interfaces are not
accessible remotely out of the box, however do be aware that if these interfaces are then
unsecured any other local user will be able to control and administer the WildFly 8 installation.
Also do note that the security-realm attribute is defined on each interface independently, this
means that you could define a different security realm for each - this may be applicable if say you
want the administrators to only access over the HTTP interface and leave only local users to
access the native interface.
Remoting Subsystem
The Remoting subsystem exposes a connector to allow for inbound comunications with JNDI and the EJB
subsystem by default we associate the ApplicationRealm with this connection.
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<connector name="remoting-connector" socket-binding="remoting"
security-realm="ApplicationRealm"/>
</subsystem>
WildFly 9
Outbound Connections
Remoting Subsystem
Outbound connections can also be defined within the Remoting subsystem, these are typically used for
remote EJB invocations from one AS server to another, in this scenario the security realm is used to obtain
the server identity either it's password for X.509 certificate and possibly a trust store to verify the certificate of
the remote host.
Even if the referenced realm contains username and password authentication configuration the
client side of the connection will NOT use this to verify the remote server.
<remote-outbound-connection name="remote-ejb-connection"
outbound-socket-binding-ref="binding-remote-ejb-connection"
username="user1"
security-realm="PasswordRealm">
The security realm is only used to obtain the password for this example, as you can see here the
username is specified separately.
<domain-controller>
<remote host="${jboss.domain.master.address}" port="${jboss.domain.master.port:9999}"
security-realm="ManagementRealm"/>
</domain-controller>
By default when a slave host controller authenticates against the master domain controller it uses
its configured name as its username. If you want to override the username used for authentication
a username attribute can be added to the <remote /> element.
WildFly 9
5.20.3 Authentication
One of the primary functions of the security realms is to define the user stores that will be used to verify the
identity of inbound connections, the actual approach taken at the transport level is based on the capabilities
of these backing store definitions. The security realms are used to secure inbound connections for both the
http management interface and for inbound remoting connections for both the native management interface
and to access other services exposed over remoting - because of this there are some small differences
between how the realm is used for each of these.
At the transport level we support the following authentication mechanisms.
HTTP
Remoting (SASL)
None
Anonymous
N/A
Digest
Digest
Basic
Plain
WildFly 9
The HTTP Basic / SASL Plain mechanism is made available for times that Digest can not be used but
effectively this means that the users password will be sent over the network in the clear unless SSL is
enabled.
The final mechanism Client-Cert allows X.509 certificates to be used to verify the identity of the remote
client.
One point bearing in mind is that it is possible that an association with a realm can mean that a
single incoming connection has the ability to choose between one or more authentication
mechanisms. As an example it is possible that an incoming remoting connection could choose
between 'Client Cert', A username password mechanism or 'JBoss Local User' for authentication this would allow say a local user to use the local mechanism, a remote user to supply their
username and password whilst a remote script could make a call and authenticate using a
certificate.
5.20.4 Authorization
The actual security realms are not involved in any authorization decisions however they can be configured to
load a users roles which will subsequently be used to make authorization decisions - when references to
authorization are seen in the context of security realms it is this loading of roles that is being referred to.
For the loading of roles the process is split out to occur after the authentication step so after a user has been
authenticated a second step will occur to load the roles based on the username they used to authenticate
with.
The examples here are taken from the standalone configuration however the descriptions are
equally applicable to domain mode, one point worth noting is that all security realms defined in the
host.xml are available to be referenced within the domain configuration for the servers running
on that host controller.
WildFly 9
Management Realm
<security-realm name="ManagementRealm">
<authentication>
<local default-user="$local"/>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
</security-realm>
The realm ManagementRealm is the simplest realm within the default configuration, this realm simply
enables two authentication mechanisms, the local mechanism and username/password authentication which
will be using Digest authentication.
local
When using the local mechanism it is optional for remote clients to send a username to the server, this
configuration specifies that where clients do not send a username it will be assumed that the clients
username is $local - the <local /> element can also be configured to allow other usernames to be
specified by remote clients however for the default configuration this is not enabled so is not supported.
properties
For username / password authentication the users details will be loaded from the file
mgmt-users.properties which is located in {jboss.home}/standalone/configuration or {
jboss.home}/domain/configuration depending on the running mode of the server.
Each user is represented on their own line and the format of each line is username=HASH where HASH is a
pre-prepared hash of the users password along with their username and the name of the realm which in this
case is ManagementRealm.
You do not need to worry about generating the entries within the properties file as we provide a
utility add-user.sh or add-user.bat to add the users, this utility is described in more detail
below.
By pre-hashing the passwords in the properties file it does mean that if the user has used the same
password on different realms then the contents of the file falling into the wrong hands does not
nescesarily mean all accounts are compromised. HOWEVER the contents of the files do still need
to be protected as they can be used to access any server where the realm name is the same and
the user has the same username and password pair.
WildFly 9
Application Realm
<security-realm name="ApplicationRealm">
<authentication>
<local default-user="$local" allowed-users="*"/>
<properties path="application-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
<authorization>
<properties path="application-roles.properties" relative-to="jboss.server.config.dir"/>
</authorization>
</security-realm>
The realm ApplicationRealm is a slightly more complex realm as this is used for both
Authentication
The authentication configuration is very similar to the ManagementRealm in that it enabled both the local
mechanism and a username/password based Digest mechanism.
local
The local configuration is similar to the ManagementRealm in that where the remote user does not supply a
username it will be assumed that the username is $local, however in addition to this there is now an
allowed-users attribute with a value of '*' - this means that the remote user can specify any username
and it will be accepted over the local mechanism provided that the local verification is a success.
To restrict the usernames that can be specified by the remote user a comma separated list of
usernames can be specified instead within the allowed-users attribute.
properties
The properties definition works in exactly the same way as the definition for ManagementRealm except now
the properties file is called application-users.properties.
WildFly 9
Authorization
The contents of the Authorization element are specific to the ApplicationRealm, in this case a
properties file is used to load a users roles.
The properties file is called application-roles.properties and is located in {
jboss.home}/standalone/configuration or {jboss.home}/domain/configuration depending
on the running mode of the server. The format of this file is username=ROLES where ROLES is a comma
separated list of the users roles.
As the loading of a users roles is a second step this is where it may be desirable to restrict which
users can use the local mechanism so that some users still require username and password
authentication for their roles to be loaded.
WildFly 9
When applications are deployed to the application server they are associated with a security domain within
the security subsystem, the other security domain is provided to work with the ApplicationRealm, this
domain is defined with a pair of login modules Remoting and RealmDirect.
Remoting
The Remoting login module is used to check if the request currently being authenticated is a request
received over a Remoting connection, if so the identity that was created during the authentication process is
used and associated with the current request.
If the request did not arrive over a Remoting connection this module does nothing and allows the JAAS
based login to continue to the next module.
RealmDirect
The RealmDirect login module makes use of a security realm to authenticate the current request if that did
not occur in the Remoting login module and then use the realm to load the users roles, by default this login
module assumes the realm to use is called ApplicationRealm although other names can be overridden
using the "realm" module-option.
The advantage of this approach is that all of the backing store configuration can be left within the realm with
the security domain just delegating to the realm.
5.20.6 user.sh
For use with the default configuration we supply a utility add-user which can be used to manage the
properties files for the default realms used to store the users and their roles.
The add-user utility can be used to manage both the users in the ManagementRealm and the users in the
ApplicationRealm, changes made apply to the properties file used both for domain mode and standalone
mode.
WildFly 9
After you have installed your application server and decided if you are going to run in standalone
mode or domain mode you can delete the parent folder for the mode you are not using, the
add-user utility will then only be managing the properties file for the mode in use.
The add-user utility is a command line utility however it can be run in both interactive and non-interactive
mode. Depending on your platform the script to run the add-user utility is either add-user.sh or
add-user.bat which can be found in {jboss.home}/bin.
This guide now contains a couple of examples of this utility in use to accomplish the most common tasks.
Adding a User
Adding users to the properties files is the primary purpose of this utility.
The server caches the contents of the properties files in memory, however the server does check
the modified time of the properties files on each authentication request and re-load if the time has
been updated - this means all changes made by this utility are immediately applied to any running
server.
A Management User
The default name of the realm for management users is ManagementRealm, when the utility
prompts for the realm name just accept the default unless you have switched to a different realm.
WildFly 9
Interactive Mode
Here we have added a new Management User called adminUser, as you can see some of the questions
offer default responses so you can just press enter without repeating the default value.
For now just answer n or no to the final question, adding users to be used by processes is described in more
detail in the domain management chapter.
WildFly 9
Interactive Mode
To add a user in non-interactive mode the command ./add-user.sh {username} {password} can be
used.
If you add users using this approach there is a risk that any other user that can view the list of
running process may see the arguments including the password of the user being added, there is
also the risk that the username / password combination will be cached in the history file of the shell
you are currently using.
An Application User
When adding application users in addition to adding the user with their pre-hashed password it is also now
possible to define the roles of the user.
WildFly 9
Interactive Mode
Here a new user called appUser has been added, in this case a comma separated list of roles has also
been specified.
As with adding a management user just answer n or no to the final question until you know you are adding a
user that will be establishing a connection from one server to another.
Interactive Mode
To add an application user non-interactively use the command ./add-user.sh -a {username}
{password}.
Non-interactive mode does not support defining a list of users, to associate a user with a set of
roles you will need to manually edit the application-roles.properties file by hand.
WildFly 9
Updating a User
Within the add-user utility it is also possible to update existing users, in interactive mode you will be
prompted to confirm if this is your intention.
A Management User
Interactive Mode
Interactive Mode
In non-interactive mode if a user already exists the update is automatic with no confirmation prompt.
WildFly 9
An Application User
Interactive Mode
On updating a user with roles you will need to re-enter the list of roles assigned to the user.
Interactive Mode
In non-interactive mode if a user already exists the update is automatic with no confirmation prompt.
Community Contributions
There are still a few features to add to the add-user utility such as removing users or adding application
users with roles in non-interactive mode, if you are interested in contributing to WildFly development the
add-user utility is a good place to start as it is a stand alone utility, however it is a part of the AS build so you
can become familiar with the AS development processes without needing to delve straight into the internals
of the application server.
WildFly 9
<native-interface security-realm="ManagementRealm">...</native-interface>
<subsystem xmlns="urn:jboss:domain:jmx:1.1">
...
<remoting-connector/>
</subsystem>
With this configuration remote access to JMX is provided over the native management interface, this is
secured using the realm ManagementRealm, this means that any user that can connect to the native
interface can also use this interface to access the MBeanServer - to disable this just remove the
<remoting-connector /> element.
In domain mode it is slightly more complicates as the native interface is exposed by the host controller
process however each application server is running in it's own process so by default remote access to JMX
is disabled.
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<connector name="remoting-connector" socket-binding="remoting"
security-realm="ApplicationRealm"/>
</subsystem>
<subsystem xmlns="urn:jboss:domain:jmx:1.1">
...
<!--<remoting-connector use-management-endpoint="false"/>-->
</subsystem>
To enable remote access to JMX uncomment the <remoting-connector /> element however be aware
that this will make the MBeanServer accessible over the same Remoting connector used for remote JNDI
and EJB access - this means that any user that can authenticate against the realm ApplicationRealm will
be able to access the MBeanServer.
The following Jira issue is currently outstanding to allow access to the individual MBeanServers by
proxying through the host controllers native interface AS7-4009, if this is a feature you would use
please add your vote to the issue.
WildFly 9
<server-identities />
The server identities section of a realm definition is used to define how a server appears to the outside
world, currently this element can be used to configure a password to be used when establishing a remote
outbound connection and also how to load a X.509 key which can be used for both inbound and outbound
SSL connections.
<ssl />
<server-identities>
<ssl protocol="...">
<keystore path="..." relative-to="..." keystore-password="..." alias="..."
key-password="..." />
</ssl>
</server-identities>
protocol - By default this is set to TLS and in general does not need to be set.
The SSL element then contains the nested <keystore /> element, this is used to define how to load the
key from the file based (JKS) keystore.
path (mandatory) - This is the path to the keystore, this can be an absolute path or relative to the next
attribute.
relative-to (optional) - The name of a service representing a path the keystore is relative to.
keystore-password (mandatory) - The password required to open the keystore.
alias (optional) - The alias of the entry to use from the keystore - for a keystore with multiple entries in
practice the first usable entry is used but this should not be relied on and the alias should be set to
guarantee which entry is used.
key-password (optional) - The password to load the key entry, if omitted the keystore-password will
be used instead.
If you see the error UnrecoverableKeyException: Cannot recover key the most likely
cause that you need to specify a key-password and possible even an alias as well to ensure
only one key is loaded.
WildFly 9
<secret />
<server-identities>
<secret value="..." />
</server-identities>
value (mandatory) - The password to use for outbound connections encoded as Base64, this field
also supports a vault expression should stronger protection be required.
The username for the outbound connection is specified at the point the outbound connection is
defined.
<authentication />
The authentication element is predominantly used to configure the authentication that is performed on an
inbound connection, however there is one exception and that is if a trust store is defined - on negotiating an
outbound SSL connection the trust store will be used to verify the remote server.
<authentication>
<truststore />
<local />
<jaas />
<ldap />
<properties />
<users />
<plug-in />
</authentication>
An authentication definition can have zero or one <truststore />, it can also have zero or one <local
/> and it can also have one of <jaas />, <ldap />, <properties />, <users />, and <plug-in />
i.e. the local mechanism and a truststore for certificate verification can be independent switched on and off
and a single username / password store can be defined.
WildFly 9
<truststore />
<authentication>
<truststore path="..." relative-to="..." keystore-password="..."/>
</authentication>
This element is used to define how to load a key store file that can be used as the trust store within the
SSLContext we create internally, the store is then used to verify the certificates of the remote side of the
connection be that inbound or outbound.
path (mandatory) - This is the path to the keystore, this can be an absolute path or relative to the next
attribute.
relative-to (optional) - The name of a service representing a path the keystore is relative to.
keystore-password (mandatory) - The password required to open the keystore.
Although this is a definition of a trust store the attribute for the password is keystore-password,
this is because the underlying file being opened is still a key store.
<local />
<authentication>
<local default-user="..." allowed-users="..." />
</authentication>
This element switches on the local authentication mechanism that allows clients to the server to verify that
they are local to the server, at the protocol level it is optional for the remote client to send a user name in the
authentication response.
default-user (optional) - If the client does not pass in a username this is the assumed username, this
value is also automatically added to the list of allowed-users.
allowed-users (optional) - This attribute is used to specify a comma separated list of users allowed to
authenticate using the local mechanism, alternatively '*' can be specified to allow any username to be
specified.
WildFly 9
<jaas />
<authentication>
<jaas name="..." />
</authentication>
The jaas element is used to enable username and password based authentication where the supplied
username and password are verified by making use of a configured jaas domain.
name (mandatory) - The name of the jaas domain to use to verify the supplied username and
password.
As JAAS authentication works by taking a username and password and verifying these the use of
this element means that at the transport level authentication will be forced to send the password in
plain text, any interception of the messages exchanged between the client and server without SSL
enabled will reveal the users password.
WildFly 9
<ldap />
<authentication>
<ldap connection="..." base-dn="..." recursive="..." user-dn="...">
<username-filter attribute="..." />
<advanced-filter filter="..." />
</ldap>
</authentication>
The ldap element is used to define how LDAP searches will be used to authenticate a user, this works by
first connecting to LDAP and performing a search using the supplied user name to identity the distinguished
name of the user and then a subsequent connection is made to the server using the password supplied by
the user - if this second connection is a success then authentication succeeds.
Due to the verification approach used this configuration causes the authentication mechanisms
selected for the protocol to cause the password to be sent from the client in plain text, the following
Jira issue is to investigating proxying a Digest authentication with the LDAP server so no plain text
password is needed AS7-4195.
<username-filter />
This element is used for a simple filter to match the username specified by the remote user against a single
attribute, as an example with Active Directory the match is most likely to be against the ' sAMAccountName'
attribute.
attribute (mandatory) - The name of the field to match the users supplied username against.
<advanced-filter />
This element is used where a more advanced filter is required, one example use of this filter is to exclude
certain matches by specifying some additional criteria for the filter.
filter (mandatory) - The filter to execute to locate the user, this filter should contain '{ 0}' as a place
holder for the username supplied by the user authenticating.
WildFly 9
<properties />
<authentication>
<properties path="..." relative-to="..." plain-text="..." />
</authentication>
The properties element is used to reference a properties file to load to read a users password or
pre-prepared digest for the authentication process.
path (mandatory) - The path to the properties file, either absolute or relative to the path referenced by
the relative-to attribute.
relative-to (optional) - The name of a path service that the defined path will be relative to.
plain-text (optional) - Setting to specify if the passwords are stored as plain text within the properties
file, defaults to false.
By default the properties files are expected to store a pre-prepared hash of the users password in
the form HEX( MD5( username ':' realm ':' password))
<users />
<authentication>
<users>
<user username="...">
<password>...</password>
</user>
</users>
</authentication>
This is a very simple store of a username and password that stores both of these within the domain model,
this is only really provided for the provision of simple examples.
username (mandatory) - A users username.
The <password/> element is then used to define the password for the user.
WildFly 9
<authorization />
The authorization element is used to define how a users roles can be loaded after the authentication process
completes, these roles may then be used for subsequent authorization decisions based on the service being
accessed. At the moment only a properties file approach or a custom plug-in are supported - support for
loading roles from LDAP or from a database are planned for a subsequent release.
<authorization>
<properties />
<plug-in />
</authorization>
<properties />
<authorization>
<properties path="..." relative-to="..." />
</authorization>
The format of the properties file is username={ROLES} where {ROLES} is a comma separated list of the
users roles.
path (mandatory) - The path to the properties file, either absolute or relative to the path referenced by
the relative-to attribute.
relative-to (optional) - The name of a path service that the defined path will be relative to.
WildFly 9
<outbound-connection />
Strictly speaking these are not a part of the security realm definition, however at the moment they are only
used by security realms so the definition of outbound connection is described here.
<management>
<security-realms />
<outbound-connections>
<ldap />
</outbound-connections>
</management>
<ldap />
At the moment we only support outbound connections to ldap servers for the authentication process - this
will later be expanded when we add support for database based authentication.
<outbound-connections>
<ldap name="..." url="..." search-dn="..." search-credential="..."
initial-context-factory="..." />
</outbound-connections>
The outbound connections are defined in this section and then referenced by name from the configuration
that makes use of them.
name (mandatory) - The unique name used to reference this connection.
url (mandatory) - The URL use to establish the LDAP connection.
search-dn (mandatory) - The distinguished name of the user to authenticate as to perform the
searches.
search-credential (mandatory) - The password required to connect to LDAP as the search-dn.
initial-context-factory (optional) - Allows overriding the initial context factory, defaults to '
com.sun.jndi.ldap.LdapCtxFactory'
WildFly 9
Previously to allow the addition of custom user stores we have added an option to the realms to call out to a
JAAS domain to validate a users username and password, the problem with this approach is that to call
JAAS we need the remote user to send in their plain text username and password so that a JAAS
LoginModule can perform the validation, this forces us down to use either the HTTP Basic authentication
mechanism or the SASL Plain mechanism depending on the transport used which is undesirable as we can
not longer use Digest.
To overcome this we now support plugging in custom user stores to support loading a users password, hash
and roles from a custom store to allow different stores to be implemented without forcing the authentication
back to plain text variant, this article describes the requirements for a plug in and shows a simple example
plug-in for use with WildFly 8.
When implementing a plug in there are two steps to the authentication process, the first step is to load the
users identity and credential from the relevant store - this is then used to verify the user attempting to
connect is valid. After the remote user is validated we then load the users roles in a second step. For this
reason the support for plug-ins is split into the two stages, when providing a plug-in either of these two steps
can be implemented but there is no requirement to implement the other side.
When implementing a plug-in the following interfaces are the bare minimum that need to be implemented so
depending on if a plug-in to load a users identity or a plug-in to load a users roles is being implemented you
will be implementing one of these interfaces.
Note - All classes and interfaces of the SPI to be implemented are in the
'org.jboss.as.domain.management.plugin' package which is a part of the 'org.jboss.as.domain-management'
module but for simplicity for the rest of this section only the short names will be shown.
AuthenticationPlugIn
To implement an AuthenticationPlugIn the following interface needs to be implemened: -
During the authentication process this method will be called with the user name supplied by the remote user
and the name of the realm they are authenticating against, this method call represents that an authentication
attempt is occurring but it is the Identity instance that is returned that will be used for the actual
authentication to verify the remote user.
The Identity interface is also an interface you will implement: -
WildFly 9
Additional information can be contained within the Identity implementation although it will not currently be
used, the key piece of information here is the Credential that will be returned - this needs to be one of the
following: -
PasswordCredential
public final class PasswordCredential implements Credential {
public PasswordCredential(final char[] password);
public char[] getPassword();
void clear();
}
The PasswordCredential is already implemented so use this class if you have the plain text password of
the remote user, by using this the secured interfaces will be able to continue using the Digest mechanism for
authentication.
DigestCredential
public final class DigestCredential implements Credential {
public DigestCredential(final String hash);
public String getHash();
}
This class is also already implemented and should be returned if instead of the plain text password you
already have a pre-prepared hash of the username, realm and password.
ValidatePasswordCredential
public interface ValidatePasswordCredential extends Credential {
boolean validatePassword(final char[] password);
}
This is a special Credential type to use when it is not possible to obtain either a plain text representation of
the password or a pre-prepared hash - this is an interface as you will need to provide an implementation to
verify a supplied password. The down side of using this type of Credential is that the authentication
mechanism used at the transport level will need to drop down from Digest to either HTTP Basic or SASL
Plain which will now mean that the remote client is sending their credential across the network in the clear.
If you use this type of credential be sure to force the mechanism choice to Plain as described in the
configuration section below.
WildFly 9
AuthorizationPlugIn
If you are implementing a custom mechanism to load a users roles you need to implement the
AuthorizationPlugIn
As with the AuthenticationPlugIn this has a single method that takes a users userName and realm the return type is an array of Strings with each entry representing a role the user is a member of.
PlugInConfigurationSupport
In addition to the specific interfaces above there is an additional interface that a plug-in can implement to
receive configuration information before the plug-in is used and also to receive a Map instance that can be
used to share state between the plug-in instance used for the authentication step of the call and the plug-in
instance used for the authorization step.
<security-realm name="PlugInRealm">
<plug-ins>
<plug-in module="org.jboss.as.sample.plugin"/>
</plug-ins>
<authentication>
<plug-in name="Sample">
<properties>
<property name="darranl.password" value="dpd"/>
<property name="darranl.roles" value="Admin,Banker,User"/>
</properties>
</plug-in>
</authentication>
<authorization>
<plug-in name="Delegate" />
</authorization>
</security-realm>
WildFly 9
Before looking closely at the packaging and configuration there is one more interface to implement and that
is the PlugInProvider interface, that interface is responsible for making PlugIn instances available at
runtime to handle the requests.
PlugInProvider
public interface PlugInProvider {
AuthenticationPlugIn<Credential> loadAuthenticationPlugIn(final String name);
AuthorizationPlugIn loadAuthorizationPlugIn(final String name);
}
These methods are called with the name that is supplied in the plug-in elements that are contained within the
authentication and authorization elements of the configuration, based on the sample configuration above the
loadAuthenticationPlugIn method will be called with a parameter of 'Sample' and the loadAuthorizationPlugIn
method will be called with a parameter of 'Delegate'.
Multiple plug-in providers may be available to the application server so if a PlugInProvider
implementation does not recognise a name then it should just return null and the server will continue
searching the other providers. If a PlugInProvider does recognise a name but fails to instantiate the
PlugIn then a RuntimeException can be thrown to indicate the failure.
As a server could have many providers registered it is recommended that a naming convention including
some form of hierarchy is used e.g. use package style names to avoid conflicts.
For the example the implementation is as follows: -
The load methods are called for each authentication attempt but it will be an implementation detail of the
provider if it decides to return a new instance of the provider each time - in this scenario as we also use
configuration and shared state then new instances of the implementations make sense.
WildFly 9
To load the provider use a ServiceLoader so within the META-INF/services folder of the jar this project adds
a file called 'org.jboss.as.domain.management.plugin.PlugInProvider' - this contains a single
entry which is the fully qualified class name of the PlugInProvider implementation class.
org.jboss.as.sample.SamplePluginProvider
Package as a Module
To make the PlugInProvider available to the application it is bundled as a module and added to the
modules already shipped with WildFly 8.
To add as a module we first need a module.xml: -
<plug-ins>
<plug-in module="org.jboss.as.sample.plugin"/>
</plug-ins>
This element is used to list the modules that should be searched for plug-ins. As plug-ins are loaded during
the server start up this search is a lazy search so don't expect a definition to a non existant module or to a
module that does not contain a plug-in to report an error.
The AuthenticationPlugIn
The example AuthenticationPlugIn is implemented as: -
WildFly 9
WildFly 9
As you can see from this implementation there is also an additional class being extended AbstractPlugIn
- that is simply an abstract class that implements the AuthenticationPlugIn, AuthorizationPlugIn,
and PlugInConfigurationSupport interfaces already. The properties that were defined in the
configuration are passed in as a Map and importantly for this sample the plug-in adds itself to the shared
state map.
The AuthorizationPlugIn
The example implementation of the authentication plug in is as follows: -
This plug-in illustrates how two plug-ins can work together, by the AuthenticationPlugIn placing itself in
the shared state map it is possible for the authorization plug-in to make use of it for the loadRoles
implementation.
Another option to consider to achieve similar behaviour could be to provide an Identity implementation that
also contains the roles and place this in the shared state map - the AuthorizationPlugIn can retrieve
this and return the roles.
<authentication>
<plug-in name="Sample" mechanism="PLAIN">
WildFly 9
LDAP Authentication
The following example demonstrates an example configuration making use of Active Directory to verify the
users username and password.
<management>
<security-realms>
<security-realm name="ManagementRealm">
<authentication>
<ldap connection="EC2" base-dn="CN=Users,DC=darranl,DC=jboss,DC=org">
<username-filter attribute="sAMAccountName" />
</ldap>
</authentication>
</security-realm>
</security-realms>
<outbound-connections>
<ldap name="EC2" url="ldap://127.0.0.1:9797"
search-dn="CN=wf8,CN=Users,DC=darranl,DC=jboss,DC=org" search-credential="password"/>
</outbound-connections>
...
</management>
For simplicity the <local/> configuration has been removed from this example, however there it
is fine to leave that in place for local authentication to remain possible.
WildFly 9
Enable SSL
The first step is the creation of the key, by default this is going to be used for both the native management
interface and the http management interface - to create the key we can use the keyTool, the following
example will create a key valid for one year.
Open a terminal window in the folder {jboss.home}/standalone/configuration and enter the
following command: keytool -genkey -alias server -keyalg RSA -keystore server.keystore -validity
365
Of all of the questions asked this is the most important and should match the host name that will be
entered into the web browser to connect to the admin console.
Answer the remaining questions as you see fit and at the end for the purpose of this example I set the key
password to 'key_password'.
The following example shows how this newly created keystore will be referenced to enable SSL.
<security-realm name="ManagementRealm">
<server-identities>
<ssl>
<keystore path="server.keystore" relative-to="jboss.server.config.dir"
keystore-password="keystore_password" alias="server" key-password="key_password" />
</ssl>
</server-identities>
<authentication>
...
</authentication>
</security-realm>
The contents of the <authentication /> have not been changed in this example so authentication still
occurs using either the local mechanism or username/password authentication using Digest.
WildFly 9
<security-realm name="ManagementRealm">
<server-identities>
<ssl>
<keystore path="server.keystore" relative-to="jboss.server.config.dir"
keystore-password="keystore_password" alias="server" key-password="key_password" />
</ssl>
</server-identities>
<authentication>
<truststore path="server.truststore" relative-to="jboss.server.config.dir"
keystore-password="truststore_password" />
<local default-user="$local"/>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
</security-realm>
In this scenario if Client-Cert authentication does not occur clients can fall back to use either the local
mechanism or username/password authentication. To make Client-Cert based authentication mandatory just
remove the <local /> and <properties /> elements.
After you have installed your application server and decided if you are going to run in standalone
mode or domain mode you can delete the parent folder for the mode you are not using, the
add-user utility will then only be managing the properties file for the mode in use.
The add-user utility is a command line utility however it can be run in both interactive and non-interactive
mode. Depending on your platform the script to run the add-user utility is either add-user.sh or
add-user.bat which can be found in {jboss.home}/bin.
This guide now contains a couple of examples of this utility in use to accomplish the most common tasks.
WildFly 9
Adding a User
Adding users to the properties files is the primary purpose of this utility.
The server caches the contents of the properties files in memory, however the server does check
the modified time of the properties files on each authentication request and re-load if the time has
been updated - this means all changes made by this utility are immediately applied to any running
server.
A Management User
The default name of the realm for management users is ManagementRealm, when the utility
prompts for the realm name just accept the default unless you have switched to a different realm.
Interactive Mode
Here we have added a new Management User called adminUser, as you can see some of the questions
offer default responses so you can just press enter without repeating the default value.
For now just answer n or no to the final question, adding users to be used by processes is described in more
detail in the domain management chapter.
WildFly 9
Interactive Mode
To add a user in non-interactive mode the command ./add-user.sh {username} {password} can be
used.
If you add users using this approach there is a risk that any other user that can view the list of
running process may see the arguments including the password of the user being added, there is
also the risk that the username / password combination will be cached in the history file of the shell
you are currently using.
An Application User
When adding application users in addition to adding the user with their pre-hashed password it is also now
possible to define the roles of the user.
WildFly 9
Interactive Mode
Here a new user called appUser has been added, in this case a comma separated list of roles has also
been specified.
As with adding a management user just answer n or no to the final question until you know you are adding a
user that will be establishing a connection from one server to another.
Interactive Mode
To add an application user non-interactively use the command ./add-user.sh -a {username}
{password}.
Non-interactive mode does not support defining a list of users, to associate a user with a set of
roles you will need to manually edit the application-roles.properties file by hand.
WildFly 9
Updating a User
Within the add-user utility it is also possible to update existing users, in interactive mode you will be
prompted to confirm if this is your intention.
A Management User
Interactive Mode
Interactive Mode
In non-interactive mode if a user already exists the update is automatic with no confirmation prompt.
WildFly 9
An Application User
Interactive Mode
On updating a user with roles you will need to re-enter the list of roles assigned to the user.
Interactive Mode
In non-interactive mode if a user already exists the update is automatic with no confirmation prompt.
Community Contributions
There are still a few features to add to the add-user utility such as removing users or adding application
users with roles in non-interactive mode, if you are interested in contributing to WildFly development the
add-user utility is a good place to start as it is a stand alone utility, however it is a part of the AS build so you
can become familiar with the AS development processes without needing to delve straight into the internals
of the application server.
WildFly 9
Within a security realm definition there are four optional elements <plug-ins />, <server-identities
/>, <authentication />, and <authorization />, as mentioned above plug-ins is defined within it's
own section below so we will begin by looking at the <server-identities /> element.
<server-identities />
The server identities section of a realm definition is used to define how a server appears to the outside
world, currently this element can be used to configure a password to be used when establishing a remote
outbound connection and also how to load a X.509 key which can be used for both inbound and outbound
SSL connections.
<ssl />
<server-identities>
<ssl protocol="...">
<keystore path="..." relative-to="..." keystore-password="..." alias="..."
key-password="..." />
</ssl>
</server-identities>
protocol - By default this is set to TLS and in general does not need to be set.
The SSL element then contains the nested <keystore /> element, this is used to define how to load the
key from the file based (JKS) keystore.
path (mandatory) - This is the path to the keystore, this can be an absolute path or relative to the next
attribute.
relative-to (optional) - The name of a service representing a path the keystore is relative to.
keystore-password (mandatory) - The password required to open the keystore.
alias (optional) - The alias of the entry to use from the keystore - for a keystore with multiple entries in
practice the first usable entry is used but this should not be relied on and the alias should be set to
guarantee which entry is used.
key-password (optional) - The password to load the key entry, if omitted the keystore-password will
be used instead.
If you see the error UnrecoverableKeyException: Cannot recover key the most likely
cause that you need to specify a key-password and possible even an alias as well to ensure
only one key is loaded.
WildFly 9
<secret />
<server-identities>
<secret value="..." />
</server-identities>
value (mandatory) - The password to use for outbound connections encoded as Base64, this field
also supports a vault expression should stronger protection be required.
The username for the outbound connection is specified at the point the outbound connection is
defined.
<authentication />
The authentication element is predominantly used to configure the authentication that is performed on an
inbound connection, however there is one exception and that is if a trust store is defined - on negotiating an
outbound SSL connection the trust store will be used to verify the remote server.
<authentication>
<truststore />
<local />
<jaas />
<ldap />
<properties />
<users />
<plug-in />
</authentication>
An authentication definition can have zero or one <truststore />, it can also have zero or one <local
/> and it can also have one of <jaas />, <ldap />, <properties />, <users />, and <plug-in />
i.e. the local mechanism and a truststore for certificate verification can be independent switched on and off
and a single username / password store can be defined.
WildFly 9
<truststore />
<authentication>
<truststore path="..." relative-to="..." keystore-password="..."/>
</authentication>
This element is used to define how to load a key store file that can be used as the trust store within the
SSLContext we create internally, the store is then used to verify the certificates of the remote side of the
connection be that inbound or outbound.
path (mandatory) - This is the path to the keystore, this can be an absolute path or relative to the next
attribute.
relative-to (optional) - The name of a service representing a path the keystore is relative to.
keystore-password (mandatory) - The password required to open the keystore.
Although this is a definition of a trust store the attribute for the password is keystore-password,
this is because the underlying file being opened is still a key store.
<local />
<authentication>
<local default-user="..." allowed-users="..." />
</authentication>
This element switches on the local authentication mechanism that allows clients to the server to verify that
they are local to the server, at the protocol level it is optional for the remote client to send a user name in the
authentication response.
default-user (optional) - If the client does not pass in a username this is the assumed username, this
value is also automatically added to the list of allowed-users.
allowed-users (optional) - This attribute is used to specify a comma separated list of users allowed to
authenticate using the local mechanism, alternatively '*' can be specified to allow any username to be
specified.
WildFly 9
<jaas />
<authentication>
<jaas name="..." />
</authentication>
The jaas element is used to enable username and password based authentication where the supplied
username and password are verified by making use of a configured jaas domain.
name (mandatory) - The name of the jaas domain to use to verify the supplied username and
password.
As JAAS authentication works by taking a username and password and verifying these the use of
this element means that at the transport level authentication will be forced to send the password in
plain text, any interception of the messages exchanged between the client and server without SSL
enabled will reveal the users password.
WildFly 9
<ldap />
<authentication>
<ldap connection="..." base-dn="..." recursive="..." user-dn="...">
<username-filter attribute="..." />
<advanced-filter filter="..." />
</ldap>
</authentication>
The ldap element is used to define how LDAP searches will be used to authenticate a user, this works by
first connecting to LDAP and performing a search using the supplied user name to identity the distinguished
name of the user and then a subsequent connection is made to the server using the password supplied by
the user - if this second connection is a success then authentication succeeds.
Due to the verification approach used this configuration causes the authentication mechanisms
selected for the protocol to cause the password to be sent from the client in plain text, the following
Jira issue is to investigating proxying a Digest authentication with the LDAP server so no plain text
password is needed AS7-4195.
<username-filter />
This element is used for a simple filter to match the username specified by the remote user against a single
attribute, as an example with Active Directory the match is most likely to be against the ' sAMAccountName'
attribute.
attribute (mandatory) - The name of the field to match the users supplied username against.
<advanced-filter />
This element is used where a more advanced filter is required, one example use of this filter is to exclude
certain matches by specifying some additional criteria for the filter.
filter (mandatory) - The filter to execute to locate the user, this filter should contain '{ 0}' as a place
holder for the username supplied by the user authenticating.
WildFly 9
<properties />
<authentication>
<properties path="..." relative-to="..." plain-text="..." />
</authentication>
The properties element is used to reference a properties file to load to read a users password or
pre-prepared digest for the authentication process.
path (mandatory) - The path to the properties file, either absolute or relative to the path referenced by
the relative-to attribute.
relative-to (optional) - The name of a path service that the defined path will be relative to.
plain-text (optional) - Setting to specify if the passwords are stored as plain text within the properties
file, defaults to false.
By default the properties files are expected to store a pre-prepared hash of the users password in
the form HEX( MD5( username ':' realm ':' password))
<users />
<authentication>
<users>
<user username="...">
<password>...</password>
</user>
</users>
</authentication>
This is a very simple store of a username and password that stores both of these within the domain model,
this is only really provided for the provision of simple examples.
username (mandatory) - A users username.
The <password/> element is then used to define the password for the user.
WildFly 9
<authorization />
The authorization element is used to define how a users roles can be loaded after the authentication process
completes, these roles may then be used for subsequent authorization decisions based on the service being
accessed. At the moment only a properties file approach or a custom plug-in are supported - support for
loading roles from LDAP or from a database are planned for a subsequent release.
<authorization>
<properties />
<plug-in />
</authorization>
<properties />
<authorization>
<properties path="..." relative-to="..." />
</authorization>
The format of the properties file is username={ROLES} where {ROLES} is a comma separated list of the
users roles.
path (mandatory) - The path to the properties file, either absolute or relative to the path referenced by
the relative-to attribute.
relative-to (optional) - The name of a path service that the defined path will be relative to.
WildFly 9
<outbound-connection />
Strictly speaking these are not a part of the security realm definition, however at the moment they are only
used by security realms so the definition of outbound connection is described here.
<management>
<security-realms />
<outbound-connections>
<ldap />
</outbound-connections>
</management>
<ldap />
At the moment we only support outbound connections to ldap servers for the authentication process - this
will later be expanded when we add support for database based authentication.
<outbound-connections>
<ldap name="..." url="..." search-dn="..." search-credential="..."
initial-context-factory="..." />
</outbound-connections>
The outbound connections are defined in this section and then referenced by name from the configuration
that makes use of them.
name (mandatory) - The unique name used to reference this connection.
url (mandatory) - The URL use to establish the LDAP connection.
search-dn (mandatory) - The distinguished name of the user to authenticate as to perform the
searches.
search-credential (mandatory) - The password required to connect to LDAP as the search-dn.
initial-context-factory (optional) - Allows overriding the initial context factory, defaults to '
com.sun.jndi.ldap.LdapCtxFactory'
5.20.13 Examples
This section of the document contains a couple of examples for the most common scenarios likely to be
used with the security realms, please feel free to raise Jira issues requesting additional scenarios or if you
have configured something not covered here please feel free to add your own examples - this document is
editable after all
At the moment these examples are making use of the 'ManagementRealm' however the same can apply to
the 'ApplicationRealm' or any custom realm you create for yourselves.
WildFly 9
LDAP Authentication
The following example demonstrates an example configuration making use of Active Directory to verify the
users username and password.
<management>
<security-realms>
<security-realm name="ManagementRealm">
<authentication>
<ldap connection="EC2" base-dn="CN=Users,DC=darranl,DC=jboss,DC=org">
<username-filter attribute="sAMAccountName" />
</ldap>
</authentication>
</security-realm>
</security-realms>
<outbound-connections>
<ldap name="EC2" url="ldap://127.0.0.1:9797"
search-dn="CN=wf8,CN=Users,DC=darranl,DC=jboss,DC=org" search-credential="password"/>
</outbound-connections>
...
</management>
For simplicity the <local/> configuration has been removed from this example, however there it
is fine to leave that in place for local authentication to remain possible.
WildFly 9
Enable SSL
The first step is the creation of the key, by default this is going to be used for both the native management
interface and the http management interface - to create the key we can use the keyTool, the following
example will create a key valid for one year.
Open a terminal window in the folder {jboss.home}/standalone/configuration and enter the
following command: keytool -genkey -alias server -keyalg RSA -keystore server.keystore -validity
365
Of all of the questions asked this is the most important and should match the host name that will be
entered into the web browser to connect to the admin console.
Answer the remaining questions as you see fit and at the end for the purpose of this example I set the key
password to 'key_password'.
The following example shows how this newly created keystore will be referenced to enable SSL.
<security-realm name="ManagementRealm">
<server-identities>
<ssl>
<keystore path="server.keystore" relative-to="jboss.server.config.dir"
keystore-password="keystore_password" alias="server" key-password="key_password" />
</ssl>
</server-identities>
<authentication>
...
</authentication>
</security-realm>
The contents of the <authentication /> have not been changed in this example so authentication still
occurs using either the local mechanism or username/password authentication using Digest.
WildFly 9
<security-realm name="ManagementRealm">
<server-identities>
<ssl>
<keystore path="server.keystore" relative-to="jboss.server.config.dir"
keystore-password="keystore_password" alias="server" key-password="key_password" />
</ssl>
</server-identities>
<authentication>
<truststore path="server.truststore" relative-to="jboss.server.config.dir"
keystore-password="truststore_password" />
<local default-user="$local"/>
<properties path="mgmt-users.properties" relative-to="jboss.server.config.dir"/>
</authentication>
</security-realm>
In this scenario if Client-Cert authentication does not occur clients can fall back to use either the local
mechanism or username/password authentication. To make Client-Cert based authentication mandatory just
remove the <local /> and <properties /> elements.
WildFly 9
When implementing a plug in there are two steps to the authentication process, the first step is to load the
users identity and credential from the relevant store - this is then used to verify the user attempting to
connect is valid. After the remote user is validated we then load the users roles in a second step. For this
reason the support for plug-ins is split into the two stages, when providing a plug-in either of these two steps
can be implemented but there is no requirement to implement the other side.
When implementing a plug-in the following interfaces are the bare minimum that need to be implemented so
depending on if a plug-in to load a users identity or a plug-in to load a users roles is being implemented you
will be implementing one of these interfaces.
Note - All classes and interfaces of the SPI to be implemented are in the
'org.jboss.as.domain.management.plugin' package which is a part of the 'org.jboss.as.domain-management'
module but for simplicity for the rest of this section only the short names will be shown.
AuthenticationPlugIn
To implement an AuthenticationPlugIn the following interface needs to be implemened: -
During the authentication process this method will be called with the user name supplied by the remote user
and the name of the realm they are authenticating against, this method call represents that an authentication
attempt is occurring but it is the Identity instance that is returned that will be used for the actual
authentication to verify the remote user.
The Identity interface is also an interface you will implement: -
Additional information can be contained within the Identity implementation although it will not currently be
used, the key piece of information here is the Credential that will be returned - this needs to be one of the
following: -
WildFly 9
PasswordCredential
public final class PasswordCredential implements Credential {
public PasswordCredential(final char[] password);
public char[] getPassword();
void clear();
}
The PasswordCredential is already implemented so use this class if you have the plain text password of
the remote user, by using this the secured interfaces will be able to continue using the Digest mechanism for
authentication.
DigestCredential
public final class DigestCredential implements Credential {
public DigestCredential(final String hash);
public String getHash();
}
This class is also already implemented and should be returned if instead of the plain text password you
already have a pre-prepared hash of the username, realm and password.
ValidatePasswordCredential
public interface ValidatePasswordCredential extends Credential {
boolean validatePassword(final char[] password);
}
This is a special Credential type to use when it is not possible to obtain either a plain text representation of
the password or a pre-prepared hash - this is an interface as you will need to provide an implementation to
verify a supplied password. The down side of using this type of Credential is that the authentication
mechanism used at the transport level will need to drop down from Digest to either HTTP Basic or SASL
Plain which will now mean that the remote client is sending their credential across the network in the clear.
If you use this type of credential be sure to force the mechanism choice to Plain as described in the
configuration section below.
WildFly 9
AuthorizationPlugIn
If you are implementing a custom mechanism to load a users roles you need to implement the
AuthorizationPlugIn
As with the AuthenticationPlugIn this has a single method that takes a users userName and realm the return type is an array of Strings with each entry representing a role the user is a member of.
PlugInConfigurationSupport
In addition to the specific interfaces above there is an additional interface that a plug-in can implement to
receive configuration information before the plug-in is used and also to receive a Map instance that can be
used to share state between the plug-in instance used for the authentication step of the call and the plug-in
instance used for the authorization step.
<security-realm name="PlugInRealm">
<plug-ins>
<plug-in module="org.jboss.as.sample.plugin"/>
</plug-ins>
<authentication>
<plug-in name="Sample">
<properties>
<property name="darranl.password" value="dpd"/>
<property name="darranl.roles" value="Admin,Banker,User"/>
</properties>
</plug-in>
</authentication>
<authorization>
<plug-in name="Delegate" />
</authorization>
</security-realm>
WildFly 9
Before looking closely at the packaging and configuration there is one more interface to implement and that
is the PlugInProvider interface, that interface is responsible for making PlugIn instances available at
runtime to handle the requests.
PlugInProvider
public interface PlugInProvider {
AuthenticationPlugIn<Credential> loadAuthenticationPlugIn(final String name);
AuthorizationPlugIn loadAuthorizationPlugIn(final String name);
}
These methods are called with the name that is supplied in the plug-in elements that are contained within the
authentication and authorization elements of the configuration, based on the sample configuration above the
loadAuthenticationPlugIn method will be called with a parameter of 'Sample' and the loadAuthorizationPlugIn
method will be called with a parameter of 'Delegate'.
Multiple plug-in providers may be available to the application server so if a PlugInProvider
implementation does not recognise a name then it should just return null and the server will continue
searching the other providers. If a PlugInProvider does recognise a name but fails to instantiate the
PlugIn then a RuntimeException can be thrown to indicate the failure.
As a server could have many providers registered it is recommended that a naming convention including
some form of hierarchy is used e.g. use package style names to avoid conflicts.
For the example the implementation is as follows: -
The load methods are called for each authentication attempt but it will be an implementation detail of the
provider if it decides to return a new instance of the provider each time - in this scenario as we also use
configuration and shared state then new instances of the implementations make sense.
WildFly 9
To load the provider use a ServiceLoader so within the META-INF/services folder of the jar this project adds
a file called 'org.jboss.as.domain.management.plugin.PlugInProvider' - this contains a single
entry which is the fully qualified class name of the PlugInProvider implementation class.
org.jboss.as.sample.SamplePluginProvider
Package as a Module
To make the PlugInProvider available to the application it is bundled as a module and added to the
modules already shipped with WildFly 8.
To add as a module we first need a module.xml: -
<plug-ins>
<plug-in module="org.jboss.as.sample.plugin"/>
</plug-ins>
This element is used to list the modules that should be searched for plug-ins. As plug-ins are loaded during
the server start up this search is a lazy search so don't expect a definition to a non existant module or to a
module that does not contain a plug-in to report an error.
The AuthenticationPlugIn
The example AuthenticationPlugIn is implemented as: -
WildFly 9
WildFly 9
As you can see from this implementation there is also an additional class being extended AbstractPlugIn
- that is simply an abstract class that implements the AuthenticationPlugIn, AuthorizationPlugIn,
and PlugInConfigurationSupport interfaces already. The properties that were defined in the
configuration are passed in as a Map and importantly for this sample the plug-in adds itself to the shared
state map.
The AuthorizationPlugIn
The example implementation of the authentication plug in is as follows: -
This plug-in illustrates how two plug-ins can work together, by the AuthenticationPlugIn placing itself in
the shared state map it is possible for the authorization plug-in to make use of it for the loadRoles
implementation.
Another option to consider to achieve similar behaviour could be to provide an Identity implementation that
also contains the roles and place this in the shared state map - the AuthorizationPlugIn can retrieve
this and return the roles.
<authentication>
<plug-in name="Sample" mechanism="PLAIN">
WildFly 9
Schema Location
The configuration schemas can found in $JBOSS_HOME/docs/schema.
WildFly 9
name="default"
jndi-name="java:jboss/ee/concurrency/context/default"
use-transaction-setup-provider="true" />
</context-services>
<managed-thread-factories>
<managed-thread-factory
name="default"
jndi-name="java:jboss/ee/concurrency/factory/default"
context-service="default"
priority="1" />
</managed-thread-factories>
<managed-executor-services>
<managed-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
max-threads="25"
keepalive-time="5000"
queue-length="1000000"
reject-policy="RETRY_ABORT" />
</managed-executor-services>
<managed-scheduled-executor-services>
<managed-scheduled-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/scheduler/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
keepalive-time="5000"
reject-policy="RETRY_ABORT" />
</managed-scheduled-executor-services>
</concurrent>
<default-bindings
context-service="java:jboss/ee/concurrency/context/default"
datasource="java:jboss/datasources/ExampleDS"
jms-connection-factory="java:jboss/DefaultJMSConnectionFactory"
managed-executor-service="java:jboss/ee/concurrency/executor/default"
managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default"
managed-thread-factory="java:jboss/ee/concurrency/factory/default" />
</subsystem>
WildFly 9
Global Modules
Global modules is a set of JBoss Modules that will be added as dependencies to the JBoss Module of every
Java EE deployment. Such dependencies allows Java EE deployments to see the classes exported by the
global modules.
Each global module is defined through the module resource, an example of its XML configuration:
<global-modules>
<module name="org.jboss.logging" slot="main"/>
<module name="org.apache.log4j" annotations="true" meta-inf="true" services="false" />
</global-modules>
The only mandatory attribute is the JBoss Module name, the slot attribute defaults to main, and both
define the JBoss Module ID to reference.
The optional annotations attribute, which defaults to false, indicates if a pre-computed annotation index
should be imported from META-INF/jandex.idx
The optional services attribute indicates if any services exposed in META-INF/services should be made
available to the deployments class loader, and defaults to false.
The optional meta-inf attribute, which defaults to true, indicates if the Module's META-INF path should
be available to the deployment's class loader.
WildFly 9
<ear-subdeployments-isolated>true</ear-subdeployments-isolated>
For example:
myapp.ear
|
|--- web.war
|
|--- ejb1.jar
|
|--- ejb2.jar
If the ear-subdeployments-isolated is set to false, then the classes in web.war can access classes
belonging to ejb1.jar and ejb2.jar. Similarly, classes from ejb1.jar can access classes from
ejb2.jar (and vice-versa).
This flag has no effect on the isolated classloader of the .war file(s), i.e. irrespective of whether
this flag is set to true or false, the .war within a .ear will have a isolated classloader, and
other subdeployments within that .ear will not be able to access classes from that .war. This is
as per spec.
WildFly 9
Property Replacement
The EE subsystem configuration includes flags to configure whether system property replacement will be
done on XML descriptors and Java Annotations, included in Java EE deployments.
System properties etc are resolved in the security context of the application server itself, not the
deployment that contains the file. This means that if you are running with a security manager and
enable this property, a deployment can potentially access system properties or environment entries
that the security manager would have otherwise prevented.
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>false</jboss-descriptor-property-replacement>
<annotation-property-replacement>false</annotation-property-replacement>
EE Concurrency Utilities
EE Concurrency Utilities (JSR 236) were introduced with Java EE 7, to ease the task of writing multithreaded
Java EE applications. Instances of these utilities are managed by WildFly, and the related configuration
provided by the EE subsystem.
WildFly 9
Context Services
The Context Service is a concurrency utility which creates contextual proxies from existent objects. WildFly
Context Services are also used to propagate the context from a Java EE application invocation thread, to the
threads internally used by the other EE Concurrency Utilities. Context Service instances may be created
using the subsystem XML configuration:
<context-services>
<context-service
name="default"
jndi-name="java:jboss/ee/concurrency/context/default"
use-transaction-setup-provider="true" />
</context-services>
The name attribute is mandatory, and it's value should be a unique name within all Context Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Context Service should be
placed.
The optional use-trasaction-setup-provider attribute indicates if the contextual proxies built by the
Context Service should suspend transactions in context, when invoking the proxy objects, and its value
defaults to true.
Management clients, such as the WildFly CLI, may also be used to configure Context Service instances. An
example to add and remove one named other:
/subsystem=ee/context-service=other:add(jndi-name=java\:jboss\/ee\/concurrency\/other)
/subsystem=ee/context-service=other:remove
WildFly 9
<managed-thread-factories>
<managed-thread-factory
name="default"
jndi-name="java:jboss/ee/concurrency/factory/default"
context-service="default"
priority="1" />
</managed-thread-factories>
The name attribute is mandatory, and it's value should be a unique name within all Managed Thread
Factories.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Thread Factory
should be placed.
The optional context-service references an existent Context Service by its name. If specified then
thread created by the factory will propagate the invocation context, present when creating the thread.
The optional priority indicates the priority for new threads created by the factory, and defaults to 5.
Management clients, such as the WildFly CLI, may also be used to configure Managed Thread Factory
instances. An example to add and remove one named other:
/subsystem=ee/managed-thread-factory=other:add(jndi-name=java\:jboss\/ee\/factory\/other)
/subsystem=ee/managed-thread-factory=other:remove
WildFly 9
<managed-executor-services>
<managed-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
max-threads="25"
keepalive-time="5000"
queue-length="1000000"
reject-policy="RETRY_ABORT" />
</managed-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Executor
Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Executor Service
should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional queue-length indicates the number of tasks that can be stored in the input queue. The
default value is 0, which means the queue capacity is unlimited.
The executors task queue is based on the values of the attributes core-threads and queue-length:
If queue-length is 0, or queue-length is Integer.MAX_VALUE (2147483647) and
core-threads is 0, direct handoff queuing strategy will be used and a synchronous queue will be
created.
If queue-length is Integer.MAX_VALUE but core-threads is not 0, an unbounded queue will
be used.
For any other valid value for queue-length, a bounded queue wil be created.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
WildFly 9
The optional max-threads defines the the maximum number of threads used by the executor, which
defaults to Integer.MAX_VALUE (2147483647).
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, or RETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Executor Service
instances. An example to add and remove one named other:
/subsystem=ee/managed-executor-service=other:add(jndi-name=java\:jboss\/ee\/executor\/other,
core-threads=2)
/subsystem=ee/managed-executor-service=other:remove
<managed-scheduled-executor-services>
<managed-scheduled-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/scheduler/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
keepalive-time="5000"
reject-policy="RETRY_ABORT" />
</managed-scheduled-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Scheduled
Executor Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Scheduled
Executor Service should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
WildFly 9
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, orRETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Scheduled Executor
Service instances. An example to add and remove one named other:
/subsystem=ee/managed-scheduled-executor-service=other:add(jndi-name=java\:jboss\/ee\/scheduler\/other,
core-threads=2)
/subsystem=ee/managed-scheduled-executor-service=other:remove
WildFly 9
Default EE Bindings
The Java EE Specification mandates the existence of a default instance for each of the following resources:
Context Service
Datasource
JMS Connection Factory
Managed Executor Service
Managed Scheduled Executor Service
Managed Thread Factory
The EE subsystem looks up the default instances from JNDI, using the names in the default bindings
configuration, before placing those in the standard JNDI names, such as
java:comp/DefaultManagedExecutorService:
<default-bindings
context-service="java:jboss/ee/concurrency/context/default"
datasource="java:jboss/datasources/ExampleDS"
jms-connection-factory="java:jboss/DefaultJMSConnectionFactory"
managed-executor-service="java:jboss/ee/concurrency/executor/default"
managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default"
managed-thread-factory="java:jboss/ee/concurrency/factory/default" />
The default bindings are optional, if the jndi name for a default binding is not configured then the
related resource will not be available to Java EE applications.
WildFly 9
5.21.2 Naming
Overview
The Naming subsystem provides the JNDI implementation on WildFly, and its configuration allows to:
bind entries in global JNDI namespaces
turn off/on the remote JNDI interface
The subsystem name is naming and this document covers Naming subsystem version 2.0, which XML
namespace within WildFly XML configurations is urn:jboss:domain:naming:2.0. The path for the
subsystem's XML schema, within WildFly's distribution, is docs/schema/jboss-as-naming_2_0.xsd.
Subsystem XML configuration example with all elements and attributes specified:
<subsystem xmlns="urn:jboss:domain:naming:2.0">
<bindings>
<simple name="java:global/a" value="100" type="int" />
<simple name="java:global/jboss.org/docs/url" value="https://docs.jboss.org"
type="java.net.URL" />
<object-factory name="java:global/foo/bar/factory" module="org.foo.bar"
class="org.foo.bar.ObjectFactory" />
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
<lookup name="java:global/c" lookup="java:global/b" />
</bindings>
<remote-naming/>
</subsystem>
WildFly 9
If WildFly is to be used as a Java EE application server, then it's recommended to opt for
java:global, since it is a standard (i.e. portable) namespace.
<bindings>
<simple name="java:global/a" value="100" type="int" />
<object-factory name="java:global/foo/bar/factory" module="org.foo.bar"
class="org.foo.bar.ObjectFactory" />
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
<lookup name="java:global/c" lookup="java:global/b" />
</bindings>
WildFly 9
Simple Bindings
A simple binding is a primitive or java.net.URL entry, and it is defined through the simple XML element. An
example of its XML configuration:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The value attribute is mandatory and defines the entry's value.
The optional type attribute, which defaults to java.lang.String, specifies the type of the entry's value.
Besides java.lang.String, allowed types are all the primitive types and their corresponding object wrapper
classes, such as int or java.lang.Integer, and java.net.URL.
Management clients, such as the WildFly CLI, may be used to configure simple bindings. An example to add
and remove the one in the XML example above:
WildFly 9
Object Factories
The Naming subsystem configuration allows the binding of javax.naming.spi.ObjectFactory entries,
through the object-factory XML element, for instance:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The class attribute is mandatory and defines the object factory's Java type.
The module attribute is mandatory and specifies the JBoss Module ID where the object factory Java class
may be loaded from.
The optional environment child element may be used to provide a custom environment to the object
factory.
Management clients, such as the WildFly CLI, may be used to configure object factory bindings. An example
to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:add(binding-type=object-factory,
module=org.foo.bar, class=org.foo.bar.ObjectFactory, environment=[p1=v1, p2=v2])
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:remove
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
The name attribute is mandatory and specifies the target JNDI name for the entry.
WildFly 9
The class attribute is mandatory and indicates the Java initial naming context type used to create the
federated context. Note that such type must have a constructor with a single environment map argument.
The optional module attribute specifies the JBoss Module ID where any classes required by the external
JNDI context may be loaded from.
The optional cache attribute, which value defaults to false, indicates if the external context instance
should be cached.
The optional environment child element may be used to provide the custom environment needed to
lookup the external context.
Management clients, such as the WildFly CLI, may be used to configure external context bindings. An
example to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:add(binding-type=external-context,
cache=true, class=javax.naming.directory.InitialDirContext,
environment=[java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory,
java.naming.provider.url=ldap\:\/\/ldap.example.com\:389,
java.naming.security.authentication=simple,
java.naming.security.principal=uid\=admin\,ou\=system, java.naming.security.credentials=
secret])
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:remove
Some JNDI providers may fail when their resources are looked up if they do not implement properly the
lookup(Name) method. Their errors would look like:
11:31:49,047 ERROR org.jboss.resource.adapter.jms.inflow.JmsActivation (default-threads
-1) javax.naming.InvalidNameException: Only support CompoundName names
at com.tibco.tibjms.naming.TibjmsContext.lookup(TibjmsContext.java:504)
at javax.naming.InitialContext.lookup(InitialContext.java:421)
To work around their shortcomings, the org.jboss.as.naming.lookup.by.string property can be
specified in the external-context's environment to use instead the lookup(String) method (with a performance
degradation):
Binding Aliases
The Naming subsystem configuration allows the binding of existent entries into additional names, i.e.
aliases. Binding aliases are specified through the lookup XML element. An example of its XML
configuration:
WildFly 9
The name attribute is mandatory and specifies the target JNDI name for the entry.
The lookup attribute is mandatory and indicates the source JNDI name.
Management clients, such as the WildFly CLI, may be used to configure binding aliases. An example to add
and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/c:add(binding-type=lookup, lookup=java\:global\/b)
/subsystem=naming/binding=java\:global\/c:remove
Only entries within the java:jboss/exported context are accessible over remote JNDI.
In the subsystem's XML configuration, remote JNDI access bindings are configured through the
<remote-naming /> XML element:
<remote-naming />
Management clients, such as the WildFly CLI, may be used to add/remove the remote JNDI interface. An
example to add and remove the one in the XML example above:
/subsystem=naming/service=remote-naming:add
/subsystem=naming/service=remote-naming:remove
WildFly 9
For a detailed explanation how to deploy JDBC 4 compliant driver jar, please refer to the chapter "
Application Deployment".
Datasource Definitions
The datasource itself is defined within the subsystem datasources:
WildFly 9
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
<driver>h2</driver>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<xa-datasource jndi-name="java:jboss/datasources/ExampleXADS" pool-name="ExampleXADS">
<driver>h2</driver>
<xa-datasource-property name="URL">jdbc:h2:mem:test</xa-datasource-property>
<xa-pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</xa-pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</xa-datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
(See
standalone/configuration/standalone.xml)
As you can see the datasource references a driver by it's logical name.
You can easily query the same information through the CLI:
WildFly 9
[standalone@localhost:9999 /] /subsystem=datasources:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"data-source" => {"java:/H2DS" => {
"connection-url" => "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1",
"jndi-name" => "java:/H2DS",
"driver-name" => "h2",
"pool-name" => "H2DS",
"use-java-context" => true,
"enabled" => true,
"jta" => true,
"pool-prefill" => true,
"pool-use-strict-min" => false,
"user-name" => "sa",
"password" => "sa",
"flush-strategy" => "FailingConnectionOnly",
"background-validation" => false,
"use-fast-fail" => false,
"validate-on-match" => false,
"use-ccm" => true
}},
"xa-data-source" => undefined,
"jdbc-driver" => {"h2" => {
"driver-name" => "h2",
"driver-module-name" => "com.h2database.h2",
"driver-xa-datasource-class-name" => "org.h2.jdbcx.JdbcDataSource"
}}
}
}
[standalone@localhost:9999 /] /subsystem=datasources:installed-drivers-list
{
"outcome" => "success",
"result" => [{
"driver-name" => "h2",
"deployment-name" => undefined,
"driver-module-name" => "com.h2database.h2",
"module-slot" => "main",
"driver-xa-datasource-class-name" => "org.h2.jdbcx.JdbcDataSource",
"driver-class-name" => "org.h2.Driver",
"driver-major-version" => 1,
"driver-minor-version" => 2,
"jdbc-compliant" => true
}]
}
Using the web console or the CLI greatly simplifies the deployment of JDBC drivers and the
creation of datasources.
WildFly 9
[standalone@localhost:9999 /] help
Supported commands:
[...]
data-source
xa-data-source
This feature is primarily intended for development, and thus has a few limitations to be aware
of. It can not be altered in any of the management interfaces (consle, CLI, etc). Only limited runtime
information is available. Also, password vaults and security domains are not deployable, so these
can not be bundled with a datasource deployment.
Component Reference
The datasource subsystem is provided by the IronJacamar project. For a detailed description of the available
configuration properties, please consult the project documentation.
WildFly 9
5.21.4 Messaging
The JMS server configuration is done through the messaging subsystem. In this chapter we are going
outline the frequently used configuration options. For a more detailed explanation please consult the
HornetQ user guide (See "Component Reference").
Connectors
There are three kind of connectors that can be used to connect to WildFly JMS Server
invm-connector can be used by a local client (i.e. one running in the same JVM as the server)
netty-connector can be used by a remote client (and uses Netty over TCP for the
communication)
http-connector can be used by a remote client (and uses Undertow Web Server to upgrade from
a HTTP connection)
WildFly 9
A netty-connector is associated with a socket-binding which tells the client using the
connection-factory where to connect.
A connection-factory referencing a netty-connector is suitable to be used by a remote client
to send messages to or receive messages from the server (assuming the connection-factory has an
appropriately exported entry).
A pooled-connection-factory looked up in JNDI or injected which is referencing a
netty-connector is suitable to be used by a local client to send messages to a remote server
granted the socket-binding references an outbound-socket-binding pointing to the remote
server in question.
A pooled-connection-factory used by an MDB which is referencing a netty-connector is
suitable to consume messages from a remote server granted the socket-binding references an
outbound-socket-binding pointing to the remote server in question.
An in-vm-connector is associated with a server-id which tells the client using the
connection-factory where to connect (since multiple HornetQ servers can run in a single JVM).
A connection-factory referencing an in-vm-connector is suitable to be used by a local client
to either send messages to or receive messages from a local server.
A pooled-connection-factory looked up in JNDI or injected which is referencing an
in-vm-connector is suitable to be used by a local client only to send messages to a local server.
A pooled-connection-factory used by an MDB which is referencing an in-vm-connector is
suitable only to consume messages from a local server.
A http-connector is associated with the socket-binding that represents the HTTP socket (by default,
named http).
A connection-factory referencing a http-connector is suitable to be used by a remote client
to send messages to or receive messages from the server by connecting to its HTTP port before
upgrading to the messaging protocol.
A pooled-connection-factory referencing a http-connector is suitable to be used by a local
client to send messages to a remote server granted the socket-binding references an
outbound-socket-binding pointing to the remote server in question.
A pooled-connection-factory used by an MDB which is referencing a http-connector is
suitable only to consume messages from a remote server granted the socket-binding references
an outbound-socket-binding pointing to the remote server in question.
WildFly 9
The entry declaration of a connection-factory or a pooled-connection-factory specifies the
JNDI name under which the factory will be exposed. Only JNDI names bound in the
"java:jboss/exported" namespace are available to remote clients. If a connection-factory has
an entry bound in the "java:jboss/exported" namespace a remote client would look-up the
connection-factory using the text after "java:jboss/exported". For example, the "
RemoteConnectionFactory" is bound by default to
"java:jboss/exported/jms/RemoteConnectionFactory" which means a remote client would
look-up this connection-factory using "jms/RemoteConnectionFactory". A
pooled-connection-factory should not have any entry bound in the "java:jboss/exported"
namespace because a pooled-connection-factory is not suitable for remote clients.
Since JMS 2.0, a default JMS connection factory is accessible to EE application under the JNDI name
java:comp/DefaultJMSConnectionFactory. WildFly messaging subsystem defines a
pooled-connection-factory that is used to provide this default connection factory. Any parameter
change on this pooled-connection-factory will be take into account by any EE application looking the
default JMS provider under the JNDI name java:comp/DefaultJMSConnectionFactory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<connectors>
<http-connector name="http-connector" socket-binding="http">
<param key="http-upgrade-endpoint" value="http-acceptor"/>
</http-connector>
<http-connector name="http-connector-throughput" socket-binding="http">
<param key="http-upgrade-endpoint" value="http-acceptor-throughput"/>
<param key="batch-delay" value="50"/>
</http-connector>
<in-vm-connector name="in-vm" server-id="0"/>
</connectors>
[...]
<jms-connection-factories>
<connection-factory name="InVmConnectionFactory">
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/ConnectionFactory"/>
</entries>
</connection-factory>
<connection-factory name="RemoteConnectionFactory">
<connectors>
<connector-ref connector-name="http-connector"/>
</connectors>
<entries>
<entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
</entries>
</connection-factory>
<pooled-connection-factory name="hornetq-ra">
<transaction mode="xa"/>
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/JmsXA"/>
<!-- Global JNDI entry used to provide a default JMS Connection factory to EE
application -->
<entry name="java:jboss/DefaultJMSConnectionFactory"/>
</entries>
</pooled-connection-factory>
</jms-connection-factories>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<jms-destinations>
<jms-queue name="testQueue">
<entry name="jms/queue/test"/>
<entry name="java:jboss/exported/jms/queue/test"/>
</jms-queue>
<jms-topic name="testTopic">
<entry name="jms/topic/test"/>
<entry name="java:jboss/exported/jms/topic/test"/>
</jms-topic>
</jms-destinations>
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
[standalone@localhost:9990 /]
/subsystem=messaging/hornetq-server=default/jms-queue=myQueue:read-resource
{
"outcome" => "success",
"result" => {
"durable" => true,
"entries" => ["queues/myQueue"],
"selector" => undefined
}
}
WildFly 9
A number of additional commands to maintain the JMS subsystem are available as well:
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<address-settings>
<address-setting match="#">
<dead-letter-address>jms.queue.DLQ</dead-letter-address>
<expiry-address>jms.queue.ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
[...]
</address-setting>
</address-settings>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<security-settings>
<security-setting match="#">
<permission type="send" roles="guest"/>
<permission type="consume" roles="guest"/>
<permission type="createNonDurableQueue" roles="role1"/>
<permission type="deleteNonDurableQueue" roles="role1 role2"/>
</security-setting>
</security-settings>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<security-domain>mySecurityDomain</security-domain>
[...]
</hornetq-server>
</subsystem>
WildFly 9
Cluster Authentication
If the HornetQ server is configured to be clustered ( <clustered>true</clustered> ), it will use the
<cluster-user> and <cluster-password> attributes to connect to other HornetQ nodes in the cluster.
If you do not change the default value of <cluster-password>, HornetQ will fail to authenticate with the error:
To prevent this error, you must specify a value for <cluster-password>. It is possible to encrypt this
value by following this guide.
Alternatively, you can use the system property jboss.messaging.cluster.password to specify the cluster
password from the command line.
This feature is primarily intended for development as destinations deployed this way can not be
managed with any of the provided management tools (e.g. console, CLI, etc).
JMS Bridge
The function of a JMS bridge is to consume messages from a source JMS destination, and send them to a
target JMS destination. Typically either the source or the target destinations are on different servers.
The bridge can also be used to bridge messages from other non HornetQ JMS servers, as long as they are
JMS 1.1 compliant.
The JMS Bridge is provided by the HornetQ project. For a detailed description of the available configuration
properties, please consult the project documentation.
WildFly 9
modules/
`-- org
`-- acmemq
`-- main
|-- acmemq-1.2.3.jar
|-- mylogapi-0.0.1.jar
`-- module.xml
WildFly 9
<resources>
<!-- insert resources required to connect to the source or target
<!-- messaging brokers if it not another WildFly instance
<resource-root path="acmemq-1.2.3.jar" />
<resource-root path="mylogapi-0.0.1.jar" />
</resources>
<dependencies>
<!-- add the dependencies required by JMS Bridge code
<module name="javax.api" />
<module name="javax.jms.api" />
<module name="javax.transaction.api"/>
<module name="org.jboss.remote-naming"/>
<!-- we depend on org.hornetq module since we will send messages to
<!-- the HornetQ server embedded in the local WildFly instance
<module name="org.hornetq" />
</dependencies>
</module>
-->
-->
-->
-->
-->
WildFly 9
Configuration
A JMS bridge is defined inside a jms-bridge section of the `messaging` subsystem in the XML
configuration files.
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<jms-bridge name="myBridge" module="org.acmemq">
<source>
<connection-factory name="ConnectionFactory"/>
<destination name="sourceQ"/>
<user>user1</user>
<password>pwd1</password>
<context>
<property key="java.naming.factory.initial"
value="org.acmemq.jndi.AcmeMQInitialContextFactory"/>
<property key="java.naming.provider.url"
value="tcp://127.0.0.1:9292"/>
</context>
</source>
<target>
<connection-factory name="/jms/invmTargetCF"/>
<destination name="/jms/targetQ"/>
</target>
<quality-of-service>AT_MOST_ONCE</quality-of-service>
<failure-retry-interval>500</failure-retry-interval>
<max-retries>1</max-retries>
<max-batch-size>500</max-batch-size>
<max-batch-time>500</max-batch-time>
<add-messageID-in-header>true</add-messageID-in-header>
</jms-bridge>
</subsystem>
The source and target sections contain the name of the JMS resource (connection-factory and
destination) that will be looked up in JNDI.
It optionally defines the user and password credentials. If they are set, they will be passed as arguments
when creating the JMS connection from the looked up ConnectionFactory.
It is also possible to define JNDI context properties in the context section. If the context section is
absent, the JMS resources will be looked up in the local WildFly instance (as it is the case in the target
section in the example above).
WildFly 9
Management commands
A JMS Bridge can also be managed using the WildFly command line interface:
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=myBridge/:add(module="org.acmemq",
\
source-destination="sourceQ",
\
source-connection-factory="ConnectionFactory",
\
source-user="user1",
\
source-password="pwd1",
\
source-context={"java.naming.factory.initial" =>
"org.acmemq.jndi.AcmeMQInitialContextFactory", \
"java.naming.provider.url" => "tcp://127.0.0.1:9292"},
\
target-destination="/jms/targetQ",
\
target-connection-factory="/jms/invmTargetCF",
\
quality-of-service=AT_MOST_ONCE,
\
failure-retry-interval=500,
\
max-retries=1,
\
max-batch-size=500,
\
max-batch-time=500,
\
add-messageID-in-header=true)
{"outcome" => "success"}
You can also see the complete JMS Bridge resource description from the CLI:
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=*/:read-resource-description
{
"outcome" => "success",
"result" => [{
"address" => [
("subsystem" => "messaging"),
("jms-bridge" => "*")
],
"outcome" => "success",
"result" => {
"description" => "A JMS bridge instance.",
"attributes" => {
...
}
}]
}
WildFly 9
Component Reference
The messaging subsystem is provided by the HornetQ project. For a detailed description of the available
configuration properties, please consult the project documentation.
There are two main parts to the undertow subsystem, which are server and Servlet container configuration,
as well as some ancillary items. Advanced topics like load balancing and failover are covered on the "High
Availability Guide". The default configuration does is suitable for most use cases and provides reasonable
performance settings.
Required extension:
WildFly 9
<subsystem xmlns="urn:jboss:domain:undertow:1.0">
<buffer-caches>
<buffer-cache name="default" buffer-size="1024" buffers-per-region="1024"
max-regions="10"/>
</buffer-caches>
<server name="default-server">
<http-listener name="default" socket-binding="http" />
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content" />
</host>
</server>
<servlet-container name="default" default-buffer-cache="default"
stack-trace-on-error="local-only" >
<jsp-config/>
<persistent-sessions/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"
directory-listing="true"/>
</handlers>
</subsystem>
<buffer-caches>
<buffer-cache name="default" buffer-size="1024" buffers-per-region="1024" max-regions="10"/>
</buffer-caches>
Attribute
Description
buffer-size
The size of the buffers. Smaller buffers allow space to be utilised more effectively
The maximum number of regions. This controls the maximum amount of memory that
can be used for caching
WildFly 9
Server configuration
A server represents an instance of Undertow. Basically this consists of a set of connectors and some
configured handlers.
Attribute
Description
default-host
the virtual host that will be used if an incoming request as no Host: header
servlet-container the servlet container that will be used by this server, unless is is explicitly overriden by
the deployment
Connector configuration
Undertow provides HTTP, HTTPS and AJP connectors, which are configured per server.
WildFly 9
Common settings
The following settings are common to all connectors:
Attribute
Description
socket-binding
The socket binding to use. This determines the address and port the listener listens
on.
worker
buffer-pool
enabled
max-post-size
buffer-pipelined-data
max-header-size
The maximum size of a HTTP header block that is allowed. Responses with to
much data in their header block will have the request terminated and a bad request
response send.
max-parameters
The maximum number of query or path parameters that are allowed. This limit
exists to prevent hash collision based DOS attacks.
max-headers
The maximum number of headers that are allowed. This limit exists to prevent
hash collision based DOS attacks.
max-cookies
The maximum number of cookies that are allowed. This limit exists to prevent hash
collision based DOS attacks.
allow-encoded-slash
Set this to true if you want the server to decode percent encoded slash characters.
This is probably a bad idea, as it can have security implications, due to different
servers interpreting the slash differently. Only enable this if you have a legacy
application that requires it.
decode-url
If the URL should be decoded. If this is not set to true then percent encoded
characters in the URL will be left as is.
url-charset
always-set-keep-alive If the 'Connection: keep-alive' header should be added to all responses, even if not
required by spec.
WildFly 9
HTTP Connector
<http-listener name="default" socket-binding="http"
/>
Attribute
Description
certificate-forwarding
If this is set to true then the HTTP listener will read a client certificate from the
SSL_CLIENT_CERT header. This allows client cert authentication to be used,
even if the server does not have a direct SSL connection to the end user. This
should only be enabled for servers behind a proxy that has been configured to
always set these headers.
redirect-socket
HTTPS listener
Https listener provides secure access to the server. The most important configuration option is security realm
which defines SSL secure context.
Attribute
Description
security-realm
The security realm to use for the SSL configuration. See Security realm examples
for how to configure it: Examples
verify-client
AJP listener
<ajp-listener name="default" socket-binding="ajp" />
WildFly 9
Host configuration
The host element corresponds to a virtual host.
Attribute
Description
name
alias
default-web-module The name of a deployment that should be used to serve up requests that do not
match anything.
Description
The buffer cache that is used to cache static resources in the default
Servlet.
stack-trace-on-error
Can be either all, none, or local-only. When set to none Undertow will never
display stack traces. When set to All Undertow will always display them (not
recommended for production use). When set to local-only Undertow will
only display them for requests from local addresses, where there are no
headers to indicate that the request has been proxied. Note that this feature
means that the Undertow error page will be displayed instead of the default
error page specified in web.xml.
default-encoding
use-listener-encoding
If this is true then the default encoding will be the same as that used by the
listener that received the request.
JSP configuration
WildFly 9
domain
secure
max-age
Description
path
WildFly 9
Name
Type
Description
modify-wsdl-address
boolean This boolean enables and disables the address rewrite functionality.
When modify-wsdl-address is set to true and the content of
<soap:address> is a valid URL, JBossWS will rewrite the URL using the
values of wsdl-host and wsdl-port or wsdl-secure-port.
When modify-wsdl-address is set to false and the content of
<soap:address> is a valid URL, JBossWS will not rewrite the URL. The
<soap:address> URL will be used.
When the content of <soap:address> is not a valid URL, JBossWS will
rewrite it no matter what the setting of modify-wsdl-address.
If modify-wsdl-address is set to true and wsdl-host is not defined or
explicitly set to 'jbossws.undefined.host' the content of
<soap:address> URL is use. JBossWS uses the requester's host when
rewriting the <soap:address>
When modify-wsdl-address is not defined JBossWS uses a default value
of true.
wsdl-host
string
wsdl-port
int
Set this property to explicitly define the HTTP port that will be used for
rewriting the SOAP address.
Otherwise the HTTP port will be identified by querying the list of installed
HTTP connectors.
wsdl-secure-port
int
Set this property to explicitly define the HTTPS port that will be used for
rewriting the SOAP address.
Otherwise the HTTPS port will be identified by querying the list of
installed HTTPS connectors.
wsdl-uri-scheme
string
This property explicitly sets the URI scheme to use for rewriting
<soap:address> . Valid values are http and https. This
configuration overrides scheme computed by processing the endpoint
(even if a transport guarantee
is specified). The provided values for wsdl-port and
wsdl-secure-port (or their default values) are used depending on
specified scheme.
WildFly 9
wsdl-path-rewrite-rule string
[standalone@localhost:9999 /] /subsystem=webservices:read-resource
{
"outcome" => "success",
"result" => {
"endpoint" => {},
"modify-wsdl-address" => true,
"wsdl-host" => expression "${jboss.bind.address:127.0.0.1}",
"endpoint-config" => {
"Standard-Endpoint-Config" => undefined,
"Recording-Endpoint-Config" => undefined
}
}
}
WildFly 9
Endpoint configs
Endpoint configs are defined using the endpoint-config element. Each endpoint configuration may
include properties and handlers set to the endpoints associated to the configuration.
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config:read-resource
{
"outcome" => "success",
"result" => {
"post-handler-chain" => undefined,
"property" => undefined,
"pre-handler-chain" => {"recording-handlers" => undefined}
}
}
[standalone@localhost:9999 /] /subsystem=webservices/endpoint-config=My-Endpoint-Config:add
{
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
WildFly 9
Handler chains
Each endpoint configuration may be associated with zero or more PRE and POST handler chains. Each
handler chain may include JAXWS handlers. For outbound messages the PRE handler chains are executed
before any handler that is attached to the endpoint using the standard means, such as with annotation
@HandlerChain, and POST handler chains are executed after those objects have executed. For inbound
messages the POST handler chains are executed before any handler that is attached to the endpoint using
the standard means and the PRE handler chains are executed after those objects have executed.
The protocol-binding attribute must be used to set the protocols for which the chain will be triggered.
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers:read-res
"outcome" => "success",
"result" => {
"protocol-bindings" => "##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP
##SOAP12_HTTP_MTOM",
"handler" => {"RecordingHandler" => undefined}
},
"response-headers" => {"process-state" => "restart-required"}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers:add(protocol-bindings
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers:read-resource{
"outcome" => "success",
"result" => {
"handler" => undefined,
"protocol-bindings" => "##SOAP11_HTTP"
},
"response-headers" => {"process-state" => "restart-required"}
}
WildFly 9
Handlers
JAXWS handler can be added in handler chains:
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers/handler=
"outcome" => "success",
"result" => {"class" => "org.jboss.ws.common.invocation.RecordingServerHandler"},
"response-headers" => {"process-state" => "restart-required"}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers/handler=foo-handler:a
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
WildFly 9
Runtime information
Each web service endpoint is exposed through the deployment that provides the endpoint implementation.
Each endpoint can be queried as a deployment resource. For further information please consult the chapter
"Application Deployment". Each web service endpoint specifies a web context and a WSDL Url:
[standalone@localhost:9999 /] /deployment="*"/subsystem=webservices/endpoint="*":read-resource
{
"outcome" => "success",
"result" => [{
"address" => [
("deployment" => "jaxws-samples-handlerchain.war"),
("subsystem" => "webservices"),
("endpoint" => "jaxws-samples-handlerchain:TestService")
],
"outcome" => "success",
"result" => {
"class" => "org.jboss.test.ws.jaxws.samples.handlerchain.EndpointImpl",
"context" => "jaxws-samples-handlerchain",
"name" => "TestService",
"type" => "JAXWS_JSE",
"wsdl-url" => "http://localhost:8080/jaxws-samples-handlerchain?wsdl"
}
}]
}
Component Reference
The web service subsystem is provided by the JBossWS project. For a detailed description of the available
configuration properties, please consult the project documentation.
WildFly 9
5.21.7 Logging
Overview
Attributes
add-logging-api-dependencies
use-deployment-logging-config
Per-deployment Logging
Logging Profiles
Default Log File Locations
Managed Domain
Standalone Server
Filter Expressions
List Log Files and Reading Log Files
List Log Files
Read Log File
FAQ
Why is there a logging.properties file?
WildFly 9
Overview
The overall server logging configuration is represented by the logging subsystem. It consists of four notable
parts: handler configurations, logger, the root logger declarations (aka log categories) and logging
profiles. Each logger does reference a handler (or set of handlers). Each handler declares the log format and
output:
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE" autoflush="true">
<level name="DEBUG"/>
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
</console-handler>
<periodic-rotating-file-handler name="FILE" autoflush="true">
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN"/>
</logger>
[...]
<root-logger>
<level name="DEBUG"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
</subsystem>
Attributes
The root resource contains two notable attributes add-logging-api-dependencies and
use-deployment-logging-config.
logging-api-dependencies
The add-logging-api-dependencies controls whether or not the container adds implicit logging API
dependencies to your deployments. If set to true, the default, all the implicit logging API dependencies are
added. If set to false the dependencies are not added to your deployments.
deployment-logging-config
The use-deployment-logging-config controls whether or not your deployment is scanned for
per-deployment logging. If set to true, the default, per-deployment logging is enabled. Set to false to
disable this feature.
WildFly 9
deployment Logging
Per-deployment logging allows you to add a logging configuration file to your deployment and have the
logging for that deployment configured according to the configuration file. In an EAR the configuration should
be in the META-INF directory. In a WAR or JAR deployment the configuration file can be in either the
META-INF or WEB-INF directories.
The following configuration files are allowed:
logging.properties
jboss-logging.properties
log4j.properties
log4j.xml
jboss-log4j.xml
You can also disable this functionality by changing the use-deployment-logging-config attribute to
false.
Logging Profiles
Logging profiles are like additional logging subsystems. Each logging profile constists of three of the four
notable parts listed above: handler configurations, logger and the root logger declarations.
You can assign a logging profile to a deployment via the deployments manifest. Add a Logging-Profile
entry to the MANIFEST.MF file with a value of the logging profile id. For example a logging profile defined on
/subsystem=logging/logging-profile=ejbs the MANIFEST.MF would look like:
Manifest-Version: 1.0
Logging-Profile: ejbs
A logging profile can be assigned to any number of deployments. Using a logging profile also allows for
runtime changes to the configuration. This is an advantage over the per-deployment logging configuration as
the redeploy is not required for logging changes to take affect.
WildFly 9
Log File
Host Controller
./domain/log/host-controller.log
./domain/servers/server-one/log/server.log
"Server Two"
./domain/servers/server-two/log/server.log
"Server Three"
./domain/servers/server-three/log/server.log
Standalone Server
The default log files for a standalone server can be found in the log subdirectory of the distribution:
Process Log File
Server
./standalone/log/server.log
Filter Expressions
Filter Type
Expression
Description
Parameter(s)
Examples
accept
accept
None
accept
None
deny
Accepts a filter as
The expression
not(match("JBAS"))
an argument and
takes a single
inverts the
returned value.
argument.
messages.
deny
deny
not
not(filterExpression)
WildFly 9
all
all(filterExpressions)
A filter consisting
The expression
all(match("JBAS"),
of several filters in
takes a comma
match("WELD"))
a chain. If any
delimited list of
message to be
argument.
unloggable, the
message will not
be logged and
subsequent filters
will not be
checked.
any
any(filterExpressions)
A filter consisting
The expression
any(match("JBAS"),
of several filters in
takes a comma
match("WELD"))
a chain. If any
delimited list of
message to be
argument.
loggable, the
message will be
logged and the
subsequent filters
will not be
checked.
levelChange levelChange(level)
levels
levels(levels)
A filter which
The expression
levelChange("WARN")
takes a single
level.
A filter which
The expression
levels("DEBUG", "INFO",
includes log
takes a comma
"WARN", "ERROR")
messages with a
delimited list of
string based
WildFly 9
levelRange
The filter
expression uses
a "[" to indicate a
range.
minimum
inclusive level
and a "]" to
than DEBUG
indicate a
maximum
levelRange("ERROR",
inclusive level.
"DEBUG")
or ")" respectively
indicate
exclusive. The
be greater than
the expression is
DEBUG
the minimum
level allowed, the
levelRange["ERROR",
second argument
"DEBUG")
is the maximum
level allowed.
match
match("pattern")
The expression
raw unformatted
argument.
message is used
match("JBAS\d+")
against the
pattern.
substitute
substitute("pattern",
A filter which
The first
"replacement value")
match to the
expression is the
pattern the
replacement
second argument
value.
is the
substitute("JBAS", "EAP")
replacement text.
WildFly 9
substituteAll substituteAll("pattern",
"replacement value")
A filter which
The first
replaces all
matches of the
expression is the
pattern the
replacement
second argument
value.
is the
substituteAll("JBAS", "EAP")
replacement text.
WildFly 9
Description
the number of lines from the file. A value of -1 indicates all lines should be read.
skip
tail
true to read from the end of the file up or false to read top down.
WildFly 9
FAQ
Why is there a logging.properties file?
You may have noticed that there is a logging.properties file in the configuration directory. This is
logging configuration is used when the server boots up until the logging subsystem kicks in. If the logging
subsystem is not included in your configuration, then this would act as the logging configuration for the entire
server.
The logging.properties file is overwritten at boot and with each change to the logging
subsystem. Any changes made to the file are not persisted. Any changes made to the XML
configuration or via management operations will be persisted to the logging.properties file
and used on the next boot.
5.21.8 Security
The security subsystem is the subsystem that brings the security services provided by PicketBox to the
WildFly 8 server instances.
If you are looking to secure the management interfaces for the management of the domain then you should
read the Securing the Management Interfaces chapter as the management interfaces themselves are not
run within a WildFly process so use a custom configuration.
WildFly 9
Authentication Manager
The authentication manager is the component that performs the actual authentication taking the declared
users identity and their credential so that the login context for the security domain can be used to 'login' the
user using the configured login module or modules.
Authorization Manager
The authorization manager is a component which can be obtained by the container from the current security
context to either obtain information about a users roles or to perform an authorization check against a
resource for the currently authenticated user.
Audit Manager
The audit manager from the security context is the component that can be used to log audit events in
relation to the security domain.
Mapping Manager
The mapping manager can be used to assign additional principals, credentials, roles or attributes to the
authenticated subject.
WildFly 9
security-management
subject-factory
security-domains
security-properties
security-management
This element is used to override some of the high level implementation details of the PicketBox
implementation if you have a need to change some of this behaviour.
The element can have any or the following attributes set, all of which are optional.
authentication-manager-class-name Specifies the AuthenticationManager implementation class name to
use.
deep-copy-subject-mode
audit-manager-class-name
identity-trust-manager-class-name
mapping-manager-class-name
subject-factory
The subject factory is responsible for creating subject instances, this also makes use of the authentication
manager to actually verify the caller. It is used mainly by JCA components to establish a subject. It is not
likely this would need to be overridden but if it is required the "subject-factory-class-name" attribute can be
specified on the subject-factory element.
security-domains
This portion of the configuration is where the bulk of the security subsystem configuration will actually take
place for most administrators, the security domains contain the configuration which is specific to a
deployment.
WildFly 9
The security-domains element can contain numerous <security-domain> definitions, a security-domain can
have the following attributes set:
name
extends
cache-type The type of authentication cache to use with this domain. If this attribute is removed no cache
will be used. Allowed values are "default" or "infinispan"
The following elements can then be set within the security-domain to configure the domain behaviour.
authentication
The authentication element is used to hold the list of login modules that will be used for authentication when
this domain is used, the structure of the login-module element is:
The code attribute is used to specify the implementing class of the login module which can either be the full
class name or one of the abbreviated names from the following list:
WildFly 9
Code
Classname
Client
org.jboss.security.ClientLoginModule
Certificate
org.jboss.security.auth.spi.BaseCertLoginModule
CertificateUsers
org.jboss.security.auth.spi.BaseCertLoginModule
CertificateRoles
org.jboss.security.auth.spi.CertRolesLoginModule
Database
org.jboss.security.auth.spi.DatabaseServerLoginModule
DatabaseCertificate org.jboss.security.auth.spi.DatabaseCertLoginModule
DatabaseUsers
org.jboss.security.auth.spi.DatabaseServerLoginModule
Identity
org.jboss.security.auth.spi.IdentityLoginModule
Ldap
org.jboss.security.auth.spi.LdapLoginModule
LdapExtended
org.jboss.security.auth.spi.LdapExtLoginModule
RoleMapping
org.jboss.security.auth.spi.RoleMappingLoginModule
RunAs
org.jboss.security.auth.spi.RunAsLoginModule
Simple
org.jboss.security.auth.spi.SimpleServerLoginModule
ConfiguredIdentity
org.picketbox.datasource.security.ConfiguredIdentityLoginModule
SecureIdentity
org.picketbox.datasource.security.SecureIdentityLoginModule
PropertiesUsers
org.jboss.security.auth.spi.PropertiesUsersLoginModule
SimpleUsers
org.jboss.security.auth.spi.SimpleUsersLoginModule
LdapUsers
org.jboss.security.auth.spi.LdapUsersLoginModule
Kerberos
com.sun.security.auth.module.Krb5LoginModule
SPNEGOUsers
org.jboss.security.negotiation.spnego.SPNEGOLoginModule
AdvancedLdap
org.jboss.security.negotiation.AdvancedLdapLoginModule
AdvancedADLdap
org.jboss.security.negotiation.AdvancedADLoginModule
UsersRoles
org.jboss.security.auth.spi.UsersRolesLoginModule
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The flag attribute is used to specify the JAAS flag for this module and should be one of required, requisite,
sufficient, or optional.
WildFly 9
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
See Authentication Modules for further details on the various modules listed above.
authentication-jaspi
The authentication-jaspi is used to configure a Java Authentication SPI (JASPI) provider as the
authentication mechanism. A security domain can have either a <authentication> or a <authentication-jaspi>
element, but not both. We set up JASPI by configuring one or more login modules inside the
login-module-stack element and setting up an authentication module. Here is the structure of the
authentication-jaspi element:
<login-module-stack name="...">
<login-module code="..." flag="..." module="...">
<module-option name="..." value="..."/>
</login-module>
</login-module-stack>
<auth-module code="..." login-module-stack-ref="...">
<module-option name="..." value="..."/>
</auth-module>
The login-module-stack-ref attribute value must be the name of the login-module-stack element to be used.
The sub-element login-module is configured just like in the authentication part
WildFly 9
authorization
Authorization in the AS container is normally done with RBAC (role based access control) but there are
situations where a more fine grained authorization policy is required. The authorization element allows
definition of different authorization modules to used, such that authorization can be checked with JACC
(Java Authorization Contract for Containers) or XACML (eXtensible Access Control Markup Language). The
structure of the authorization element is:
The code attribute is used to specify the implementing class of the policy module which can either be the full
class name or one of the abbreviated names from the following list:
Code
Classname
DenyAll
org.jboss.security.authorization.modules.AllDenyAuthorizationModule
PermitAll
org.jboss.security.authorization.modules.AllPermitAuthorizationModule
Delegating org.jboss.security.authorization.modules.DelegatingAuthorizationModule
Web
org.jboss.security.authorization.modules.WebAuthorizationModule
JACC
org.jboss.security.authorization.modules.JACCAuthorizationModule
XACML
org.jboss.security.authorization.modules.XACMLAuthorizationModule
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The flag attribute is used to specify the JAAS flag for this module and should be one of required, requisite,
sufficient, or optional.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
WildFly 9
mapping
The mapping element defines additional mapping of principals, credentials, roles and attributes for the
subject. The structure of the mapping element is:
The type attribute reflects the type of mapping of the provider and should be one of principal, credential, role
or attribute. By default "role" is the type used if the attribute is not set.
The code attribute is used to specify the implementing class of the login module which can either be the full
class name or one of the abbreviated names from the following list:
Code
Classname
PropertiesRoles
org.jboss.security.mapping.providers.role.PropertiesRolesMappingProvider
SimpleRoles
org.jboss.security.mapping.providers.role.SimpleRolesMappingProvider
DeploymentRoles org.jboss.security.mapping.providers.DeploymentRolesMappingProvider
DatabaseRoles
org.jboss.security.mapping.providers.role.DatabaseRolesMappingProvider
LdapRoles
org.jboss.security.mapping.providers.role.LdapRolesMappingProvider
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
audit
The audit element can be used to define a custom audit provider. The default implementation used is
org.jboss.security.audit.providers.LogAuditProvider. The structure of the audit element is:
The code attribute is used to specify the implementing class of the provider module.
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
WildFly 9
jsse
The jsse element defines configuration for keystores and truststores that can be used for SSL context
configuration or for certificate storing/retrieving.
The set of attributes (all of them optional) of this element are:
WildFly 9
keystore-password
keystore-type
keystore-url
keystore-provider
Provider of the keystore. The default JDK provider for the keystore
type is used if this attribute is null
keystore-provider-argument
key-manager-factory-algorithm
key-manager-factory-provider
truststore-password
truststore-type
truststore-url
truststore-provider
Provider of the truststore. The default JDK provider for the truststore
type is used if this attribute is null
truststore-provider-argument
client-alias
Alias of the keystore to be used when creating client side SSL sockets
server-alias
Alias of the keystore to be used when creating server side SSL sockets
service-auth-token
client-auth
Flag to indicate if the server side SSL socket should require client
authentication. Default is "false"
cipher-suites
protocols
The optional additional-properties element can be used to include other options. The structure of the jsse
element is:
WildFly 9
security-properties
This element is used to specify additional properties as required by the security subsystem, properties are
specified in the following format:
<security-properties>
<property name="..." value="..."/>
</security-properties>
The property element can be repeated as required for as many properties need to be defined.
Each property specified is set on the java.security.Security class.
5.21.9 JMX
The JMX subsystem registers a service with the Remoting endpoint so that remote access to JMX can be
obtained over the exposed Remoting connector.
This is switched on by default in standalone mode and accessible over port 9990 but in domain mode is
switched off so needs to be enabled - in domain mode the port will be the port of the Remoting connector for
the WildFly 8 instance to be monitored.
To use the connector you can access it in the standard way using a service:jmx URL:
WildFly 9
import
import
import
import
javax.management.MBeanServerConnection;
javax.management.remote.JMXConnector;
javax.management.remote.JMXConnectorFactory;
javax.management.remote.JMXServiceURL;
You also need to set your classpath when running the above example. The following script covers Linux. If
your environment is much different, paste your script when you have it working.
!/bin/bash
# specify your WildFly 8 folder
export YOUR_JBOSS_HOME=~/WildFly8
java -classpath $YOUR_JBOSS_HOME/bin/client/jboss-client.jar:./ JMXExample
If using jconsole use the jconsole.sh and jconsole.bat scripts included in the /bin directory
of the WildFly 8 distribution as these set the classpath as required to connect over Remoting.
In addition to the standard JVM MBeans, the WildFly 8 MBean server contains the following MBeans:
WildFly 9
JMX ObjectName
Description
Audit logging
Audit logging for the JMX MBean server managed by the JMX subsystem. The resource is at
/subsystem=jmx/configuration=audit-log and its attributes are similar to the ones mentioned for
/core-service=management/access=audit/logger=audit-log in Audit logging.
Attribute
Description
enabled
log-boot
true to log the JMX operations when booting the server, false otherwise
log-read-only If true all operations will be audit logged, if false only operations that change the
model will be logged
Then which handlers are used to log the management operations are configured as handler=* children of
the logger. These handlers and their formatters are defined in the global
/core-service=management/access=audit section mentioned in Audit logging.
JSON Formatter
The same JSON Formatter is used as described in Audit logging. However the records for MBean Server
invocations have slightly different fields from those logged for the core management layer.
WildFly 9
2013-08-29 18:26:29 - {
"type" : "jmx",
"r/o" : false,
"booting" : false,
"version" : "8.0.0.Beta1-SNAPSHOT",
"user" : "$local",
"domainUUID" : null,
"access" : "JMX",
"remote-address" : "127.0.0.1/127.0.0.1",
"method" : "invoke",
"sig" : [
"javax.management.ObjectName",
"java.lang.String",
"[Ljava.lang.Object;",
"[Ljava.lang.String;"
],
"params" : [
"java.lang:type=Threading",
"getThreadInfo",
"[Ljava.lang.Object;@5e6c33c",
"[Ljava.lang.String;@4b681c69"
]
}
It includes an optional timestamp and then the following information in the json record
WildFly 9
Field name
Description
type
This will have the value jmx meaning it comes from the jmx subsystem
r/o
booting
true if the operation was executed during the bootup process, false if it was
executed once the server is up and running
version
user
domainUUID
access
sig
params
error
If calling the MBeanServer method resulted in an error, this field will be populated with
Throwable.getMessage()
WildFly 9
<subsystem xmlns="urn:jboss:domain:resource-adapters:1.0">
<resource-adapters>
<resource-adapter>
<archive>eis.rar</archive>
<!-- Resource adapter level config-property -->
<config-property name="Server">localhost</config-property>
<config-property name="Port">19000</config-property>
<transaction-support>XATransaction</transaction-support>
<connection-definitions>
<connection-definition class-name="com.acme.eis.ra.EISManagedConnectionFactory"
jndi-name="java:/eis/AcmeConnectionFactory"
pool-name="AcmeConnectionFactory">
<!-- Managed connection factory level config-property -->
<config-property name="Name">Acme Inc</config-property>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
</pool>
<security>
<application/>
</security>
</connection-definition>
</connection-definitions>
<admin-objects>
<admin-object class-name="com.acme.eis.ra.EISAdminObjectImpl"
jndi-name="java:/eis/AcmeAdminObject">
<config-property name="Threshold">10</config-property>
</admin-object>
</admin-objects>
</resource-adapter>
</resource-adapters>
</subsystem>
Note, that only JNDI bindings under java:/ or java:jboss/ are supported.
(See
standalone/configuration/standalone.xml)
WildFly 9
Component Reference
The resource adapter subsystem is provided by the IronJacamar project. For a detailed description of the
available configuration properties, please consult the project documentation.
IronJacamar homepage: http://www.jboss.org/ironjacamar
Project Documentation: http://www.jboss.org/ironjacamar/docs
Schema description:
http://docs.jboss.org/ironjacamar/userguide/1.0/en-US/html/deployment.html#deployingra_descriptor
<subsystem xmlns="urn:jboss:domain:deployment-scanner:1.0">
<deployment-scanner scan-interval="5000"
relative-to="jboss.server.base.dir" path="deployments" />
</subsystem>
You can define more deployment-scanner entries to scan for deployments from more locations. The
configuration showed will scan the JBOSS_HOME/standalone/deployments directory every five
seconds. The runtime model is shown below, and uses default values for attributes not specified in the xml:
[standalone@localhost:9999 /] /subsystem=deployment-scanner:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"scanner" => {"default" => {
"auto-deploy-exploded" => false,
"auto-deploy-zipped" => true,
"deployment-timeout" => 60L,
"name" => "default",
"path" => "deployments",
"relative-to" => "jboss.server.base.dir",
"scan-enabled" => true,
"scan-interval" => 5000
}}}
}
WildFly 9
Name
Type
Description
name
STRING
path
STRING
relative-to
STRING
scan-enabled
scan-interval
INT
auto-deploy-zipped
LONG
Deployment scanners can be added by modifying standalone.xml before starting up the server or they
can be added and removed at runtime using the CLI
[standalone@localhost:9999 /]
/subsystem=deployment-scanner/scanner=new:add(scan-interval=10000,relative-to="jboss.server.base.dir",path="ot
=> "success"}
[standalone@localhost:9999 /] /subsystem=deployment-scanner/scanner=new:remove
{"outcome" => "success"}
You can also change the attributes at runtime, so for example to turn off scanning you can do
WildFly 9
[standalone@localhost:9999 /]
/subsystem=deployment-scanner/scanner=default:write-attribute(name="scan-enabled",value=false)
{"outcome" => "success"}
[standalone@localhost:9999 /] /subsystem=deployment-scanner:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"scanner" => {"default" => {
"auto-deploy-exploded" => false,
"auto-deploy-zipped" => true,
"deployment-timeout" => 60L,
"name" => "default",
"path" => "deployments",
"relative-to" => "jboss.server.base.dir",
"scan-enabled" => false,
"scan-interval" => 5000
}}}
}
<subsystem
<subsystem
<subsystem
<subsystem
xmlns="urn:jboss:domain:jaxrs:1.0"/>
xmlns="urn:jboss:domain:jdr:1.0"/>
xmlns="urn:jboss:domain:pojo:1.0"/>
xmlns="urn:jboss:domain:sar:1.0"/>
Description
Enables the gathering of diagnostic data for use in remote analysis of error conditions. Although
the data is in a simple format and could be useful to anyone, primarily useful for JBoss EAP
subscribers who would provide the data to Red Hat when requesting support
pojo
sar
Enables the deployment of .SAR archives containing MBean services, as supported by previous
versions of JBoss Application Server
WildFly 9
For a detailed explanation how to deploy JDBC 4 compliant driver jar, please refer to the chapter "
Application Deployment".
Datasource Definitions
The datasource itself is defined within the subsystem datasources:
WildFly 9
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
<driver>h2</driver>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<xa-datasource jndi-name="java:jboss/datasources/ExampleXADS" pool-name="ExampleXADS">
<driver>h2</driver>
<xa-datasource-property name="URL">jdbc:h2:mem:test</xa-datasource-property>
<xa-pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</xa-pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</xa-datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
(See
standalone/configuration/standalone.xml)
As you can see the datasource references a driver by it's logical name.
You can easily query the same information through the CLI:
WildFly 9
[standalone@localhost:9999 /] /subsystem=datasources:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"data-source" => {"java:/H2DS" => {
"connection-url" => "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1",
"jndi-name" => "java:/H2DS",
"driver-name" => "h2",
"pool-name" => "H2DS",
"use-java-context" => true,
"enabled" => true,
"jta" => true,
"pool-prefill" => true,
"pool-use-strict-min" => false,
"user-name" => "sa",
"password" => "sa",
"flush-strategy" => "FailingConnectionOnly",
"background-validation" => false,
"use-fast-fail" => false,
"validate-on-match" => false,
"use-ccm" => true
}},
"xa-data-source" => undefined,
"jdbc-driver" => {"h2" => {
"driver-name" => "h2",
"driver-module-name" => "com.h2database.h2",
"driver-xa-datasource-class-name" => "org.h2.jdbcx.JdbcDataSource"
}}
}
}
[standalone@localhost:9999 /] /subsystem=datasources:installed-drivers-list
{
"outcome" => "success",
"result" => [{
"driver-name" => "h2",
"deployment-name" => undefined,
"driver-module-name" => "com.h2database.h2",
"module-slot" => "main",
"driver-xa-datasource-class-name" => "org.h2.jdbcx.JdbcDataSource",
"driver-class-name" => "org.h2.Driver",
"driver-major-version" => 1,
"driver-minor-version" => 2,
"jdbc-compliant" => true
}]
}
Using the web console or the CLI greatly simplifies the deployment of JDBC drivers and the
creation of datasources.
WildFly 9
[standalone@localhost:9999 /] help
Supported commands:
[...]
data-source
xa-data-source
This feature is primarily intended for development, and thus has a few limitations to be aware
of. It can not be altered in any of the management interfaces (consle, CLI, etc). Only limited runtime
information is available. Also, password vaults and security domains are not deployable, so these
can not be bundled with a datasource deployment.
Component Reference
The datasource subsystem is provided by the IronJacamar project. For a detailed description of the available
configuration properties, please consult the project documentation.
WildFly 9
<subsystem xmlns="urn:jboss:domain:deployment-scanner:1.0">
<deployment-scanner scan-interval="5000"
relative-to="jboss.server.base.dir" path="deployments" />
</subsystem>
You can define more deployment-scanner entries to scan for deployments from more locations. The
configuration showed will scan the JBOSS_HOME/standalone/deployments directory every five
seconds. The runtime model is shown below, and uses default values for attributes not specified in the xml:
[standalone@localhost:9999 /] /subsystem=deployment-scanner:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"scanner" => {"default" => {
"auto-deploy-exploded" => false,
"auto-deploy-zipped" => true,
"deployment-timeout" => 60L,
"name" => "default",
"path" => "deployments",
"relative-to" => "jboss.server.base.dir",
"scan-enabled" => true,
"scan-interval" => 5000
}}}
}
WildFly 9
Name
Type
Description
name
STRING
path
STRING
relative-to
STRING
scan-enabled
scan-interval
INT
auto-deploy-zipped
LONG
Deployment scanners can be added by modifying standalone.xml before starting up the server or they
can be added and removed at runtime using the CLI
[standalone@localhost:9999 /]
/subsystem=deployment-scanner/scanner=new:add(scan-interval=10000,relative-to="jboss.server.base.dir",path="ot
=> "success"}
[standalone@localhost:9999 /] /subsystem=deployment-scanner/scanner=new:remove
{"outcome" => "success"}
You can also change the attributes at runtime, so for example to turn off scanning you can do
WildFly 9
[standalone@localhost:9999 /]
/subsystem=deployment-scanner/scanner=default:write-attribute(name="scan-enabled",value=false)
{"outcome" => "success"}
[standalone@localhost:9999 /] /subsystem=deployment-scanner:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"scanner" => {"default" => {
"auto-deploy-exploded" => false,
"auto-deploy-zipped" => true,
"deployment-timeout" => 60L,
"name" => "default",
"path" => "deployments",
"relative-to" => "jboss.server.base.dir",
"scan-enabled" => false,
"scan-interval" => 5000
}}}
}
WildFly 9
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>false</jboss-descriptor-property-replacement>
<annotation-property-replacement>false</annotation-property-replacement>
<concurrent>
<context-services>
<context-service
name="default"
jndi-name="java:jboss/ee/concurrency/context/default"
use-transaction-setup-provider="true" />
</context-services>
<managed-thread-factories>
<managed-thread-factory
name="default"
jndi-name="java:jboss/ee/concurrency/factory/default"
context-service="default"
priority="1" />
</managed-thread-factories>
<managed-executor-services>
<managed-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
max-threads="25"
keepalive-time="5000"
queue-length="1000000"
reject-policy="RETRY_ABORT" />
</managed-executor-services>
<managed-scheduled-executor-services>
<managed-scheduled-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/scheduler/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
keepalive-time="5000"
reject-policy="RETRY_ABORT" />
</managed-scheduled-executor-services>
</concurrent>
<default-bindings
context-service="java:jboss/ee/concurrency/context/default"
datasource="java:jboss/datasources/ExampleDS"
jms-connection-factory="java:jboss/DefaultJMSConnectionFactory"
managed-executor-service="java:jboss/ee/concurrency/executor/default"
managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default"
managed-thread-factory="java:jboss/ee/concurrency/factory/default" />
</subsystem>
WildFly 9
Global Modules
Global modules is a set of JBoss Modules that will be added as dependencies to the JBoss Module of every
Java EE deployment. Such dependencies allows Java EE deployments to see the classes exported by the
global modules.
Each global module is defined through the module resource, an example of its XML configuration:
<global-modules>
<module name="org.jboss.logging" slot="main"/>
<module name="org.apache.log4j" annotations="true" meta-inf="true" services="false" />
</global-modules>
The only mandatory attribute is the JBoss Module name, the slot attribute defaults to main, and both
define the JBoss Module ID to reference.
The optional annotations attribute, which defaults to false, indicates if a pre-computed annotation index
should be imported from META-INF/jandex.idx
The optional services attribute indicates if any services exposed in META-INF/services should be made
available to the deployments class loader, and defaults to false.
The optional meta-inf attribute, which defaults to true, indicates if the Module's META-INF path should
be available to the deployment's class loader.
WildFly 9
<ear-subdeployments-isolated>true</ear-subdeployments-isolated>
For example:
myapp.ear
|
|--- web.war
|
|--- ejb1.jar
|
|--- ejb2.jar
If the ear-subdeployments-isolated is set to false, then the classes in web.war can access classes
belonging to ejb1.jar and ejb2.jar. Similarly, classes from ejb1.jar can access classes from
ejb2.jar (and vice-versa).
This flag has no effect on the isolated classloader of the .war file(s), i.e. irrespective of whether
this flag is set to true or false, the .war within a .ear will have a isolated classloader, and
other subdeployments within that .ear will not be able to access classes from that .war. This is
as per spec.
WildFly 9
Property Replacement
The EE subsystem configuration includes flags to configure whether system property replacement will be
done on XML descriptors and Java Annotations, included in Java EE deployments.
System properties etc are resolved in the security context of the application server itself, not the
deployment that contains the file. This means that if you are running with a security manager and
enable this property, a deployment can potentially access system properties or environment entries
that the security manager would have otherwise prevented.
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>false</jboss-descriptor-property-replacement>
<annotation-property-replacement>false</annotation-property-replacement>
EE Concurrency Utilities
EE Concurrency Utilities (JSR 236) were introduced with Java EE 7, to ease the task of writing multithreaded
Java EE applications. Instances of these utilities are managed by WildFly, and the related configuration
provided by the EE subsystem.
WildFly 9
Context Services
The Context Service is a concurrency utility which creates contextual proxies from existent objects. WildFly
Context Services are also used to propagate the context from a Java EE application invocation thread, to the
threads internally used by the other EE Concurrency Utilities. Context Service instances may be created
using the subsystem XML configuration:
<context-services>
<context-service
name="default"
jndi-name="java:jboss/ee/concurrency/context/default"
use-transaction-setup-provider="true" />
</context-services>
The name attribute is mandatory, and it's value should be a unique name within all Context Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Context Service should be
placed.
The optional use-trasaction-setup-provider attribute indicates if the contextual proxies built by the
Context Service should suspend transactions in context, when invoking the proxy objects, and its value
defaults to true.
Management clients, such as the WildFly CLI, may also be used to configure Context Service instances. An
example to add and remove one named other:
/subsystem=ee/context-service=other:add(jndi-name=java\:jboss\/ee\/concurrency\/other)
/subsystem=ee/context-service=other:remove
WildFly 9
<managed-thread-factories>
<managed-thread-factory
name="default"
jndi-name="java:jboss/ee/concurrency/factory/default"
context-service="default"
priority="1" />
</managed-thread-factories>
The name attribute is mandatory, and it's value should be a unique name within all Managed Thread
Factories.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Thread Factory
should be placed.
The optional context-service references an existent Context Service by its name. If specified then
thread created by the factory will propagate the invocation context, present when creating the thread.
The optional priority indicates the priority for new threads created by the factory, and defaults to 5.
Management clients, such as the WildFly CLI, may also be used to configure Managed Thread Factory
instances. An example to add and remove one named other:
/subsystem=ee/managed-thread-factory=other:add(jndi-name=java\:jboss\/ee\/factory\/other)
/subsystem=ee/managed-thread-factory=other:remove
WildFly 9
<managed-executor-services>
<managed-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
max-threads="25"
keepalive-time="5000"
queue-length="1000000"
reject-policy="RETRY_ABORT" />
</managed-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Executor
Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Executor Service
should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional queue-length indicates the number of tasks that can be stored in the input queue. The
default value is 0, which means the queue capacity is unlimited.
The executors task queue is based on the values of the attributes core-threads and queue-length:
If queue-length is 0, or queue-length is Integer.MAX_VALUE (2147483647) and
core-threads is 0, direct handoff queuing strategy will be used and a synchronous queue will be
created.
If queue-length is Integer.MAX_VALUE but core-threads is not 0, an unbounded queue will
be used.
For any other valid value for queue-length, a bounded queue wil be created.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
WildFly 9
The optional max-threads defines the the maximum number of threads used by the executor, which
defaults to Integer.MAX_VALUE (2147483647).
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, or RETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Executor Service
instances. An example to add and remove one named other:
/subsystem=ee/managed-executor-service=other:add(jndi-name=java\:jboss\/ee\/executor\/other,
core-threads=2)
/subsystem=ee/managed-executor-service=other:remove
<managed-scheduled-executor-services>
<managed-scheduled-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/scheduler/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
keepalive-time="5000"
reject-policy="RETRY_ABORT" />
</managed-scheduled-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Scheduled
Executor Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Scheduled
Executor Service should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
WildFly 9
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, orRETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Scheduled Executor
Service instances. An example to add and remove one named other:
/subsystem=ee/managed-scheduled-executor-service=other:add(jndi-name=java\:jboss\/ee\/scheduler\/other,
core-threads=2)
/subsystem=ee/managed-scheduled-executor-service=other:remove
WildFly 9
Default EE Bindings
The Java EE Specification mandates the existence of a default instance for each of the following resources:
Context Service
Datasource
JMS Connection Factory
Managed Executor Service
Managed Scheduled Executor Service
Managed Thread Factory
The EE subsystem looks up the default instances from JNDI, using the names in the default bindings
configuration, before placing those in the standard JNDI names, such as
java:comp/DefaultManagedExecutorService:
<default-bindings
context-service="java:jboss/ee/concurrency/context/default"
datasource="java:jboss/datasources/ExampleDS"
jms-connection-factory="java:jboss/DefaultJMSConnectionFactory"
managed-executor-service="java:jboss/ee/concurrency/executor/default"
managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default"
managed-thread-factory="java:jboss/ee/concurrency/factory/default" />
The default bindings are optional, if the jndi name for a default binding is not configured then the
related resource will not be available to Java EE applications.
WildFly 9
Default EE Bindings
The Java EE Specification mandates the existence of a default instance for each of the following resources:
Context Service
Datasource
JMS Connection Factory
Managed Executor Service
Managed Scheduled Executor Service
Managed Thread Factory
The EE subsystem looks up the default instances from JNDI, using the names in the default bindings
configuration, before placing those in the standard JNDI names, such as
java:comp/DefaultManagedExecutorService:
<default-bindings
context-service="java:jboss/ee/concurrency/context/default"
datasource="java:jboss/datasources/ExampleDS"
jms-connection-factory="java:jboss/DefaultJMSConnectionFactory"
managed-executor-service="java:jboss/ee/concurrency/executor/default"
managed-scheduled-executor-service="java:jboss/ee/concurrency/scheduler/default"
managed-thread-factory="java:jboss/ee/concurrency/factory/default" />
The default bindings are optional, if the jndi name for a default binding is not configured then the
related resource will not be available to Java EE applications.
EE Concurrency Utilities
EE Concurrency Utilities (JSR 236) were introduced with Java EE 7, to ease the task of writing multithreaded
Java EE applications. Instances of these utilities are managed by WildFly, and the related configuration
provided by the EE subsystem.
WildFly 9
Context Services
The Context Service is a concurrency utility which creates contextual proxies from existent objects. WildFly
Context Services are also used to propagate the context from a Java EE application invocation thread, to the
threads internally used by the other EE Concurrency Utilities. Context Service instances may be created
using the subsystem XML configuration:
<context-services>
<context-service
name="default"
jndi-name="java:jboss/ee/concurrency/context/default"
use-transaction-setup-provider="true" />
</context-services>
The name attribute is mandatory, and it's value should be a unique name within all Context Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Context Service should be
placed.
The optional use-trasaction-setup-provider attribute indicates if the contextual proxies built by the
Context Service should suspend transactions in context, when invoking the proxy objects, and its value
defaults to true.
Management clients, such as the WildFly CLI, may also be used to configure Context Service instances. An
example to add and remove one named other:
/subsystem=ee/context-service=other:add(jndi-name=java\:jboss\/ee\/concurrency\/other)
/subsystem=ee/context-service=other:remove
WildFly 9
<managed-thread-factories>
<managed-thread-factory
name="default"
jndi-name="java:jboss/ee/concurrency/factory/default"
context-service="default"
priority="1" />
</managed-thread-factories>
The name attribute is mandatory, and it's value should be a unique name within all Managed Thread
Factories.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Thread Factory
should be placed.
The optional context-service references an existent Context Service by its name. If specified then
thread created by the factory will propagate the invocation context, present when creating the thread.
The optional priority indicates the priority for new threads created by the factory, and defaults to 5.
Management clients, such as the WildFly CLI, may also be used to configure Managed Thread Factory
instances. An example to add and remove one named other:
/subsystem=ee/managed-thread-factory=other:add(jndi-name=java\:jboss\/ee\/factory\/other)
/subsystem=ee/managed-thread-factory=other:remove
WildFly 9
<managed-executor-services>
<managed-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/executor/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
max-threads="25"
keepalive-time="5000"
queue-length="1000000"
reject-policy="RETRY_ABORT" />
</managed-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Executor
Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Executor Service
should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional queue-length indicates the number of tasks that can be stored in the input queue. The
default value is 0, which means the queue capacity is unlimited.
The executors task queue is based on the values of the attributes core-threads and queue-length:
If queue-length is 0, or queue-length is Integer.MAX_VALUE (2147483647) and
core-threads is 0, direct handoff queuing strategy will be used and a synchronous queue will be
created.
If queue-length is Integer.MAX_VALUE but core-threads is not 0, an unbounded queue will
be used.
For any other valid value for queue-length, a bounded queue wil be created.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
WildFly 9
The optional max-threads defines the the maximum number of threads used by the executor, which
defaults to Integer.MAX_VALUE (2147483647).
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, or RETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Executor Service
instances. An example to add and remove one named other:
/subsystem=ee/managed-executor-service=other:add(jndi-name=java\:jboss\/ee\/executor\/other,
core-threads=2)
/subsystem=ee/managed-executor-service=other:remove
<managed-scheduled-executor-services>
<managed-scheduled-executor-service
name="default"
jndi-name="java:jboss/ee/concurrency/scheduler/default"
context-service="default"
thread-factory="default"
hung-task-threshold="60000"
core-threads="5"
keepalive-time="5000"
reject-policy="RETRY_ABORT" />
</managed-scheduled-executor-services>
The name attribute is mandatory, and it's value should be a unique name within all Managed Scheduled
Executor Services.
The jndi-name attribute is also mandatory, and defines where in the JNDI the Managed Scheduled
Executor Service should be placed.
The optional context-service references an existent Context Service by its name. If specified then the
referenced Context Service will capture the invocation context present when submitting a task to the
executor, which will then be used when executing the task.
The optional thread-factory references an existent Managed Thread Factory by its name, to handle the
creation of internal threads. If not specified then a Managed Thread Factory with default configuration will be
created and used internally.
WildFly 9
The mandatory core-threads provides the number of threads to keep in the executor's pool, even if they
are idle. A value of 0 means there is no limit.
The optional hung-task-threshold defines a threshold value, in milliseconds, to hung a possibly blocked
task. A value of 0 will never hung a task, and is the default.
The optional long-running-tasks is a hint to optimize the execution of long running tasks, and defaults
to false.
The optional keepalive-time defines the time, in milliseconds, that an internal thread may be idle. The
attribute default value is 60000.
The optional reject-policy defines the policy to use when a task is rejected by the executor. The attribute
value may be the default ABORT, which means an exception should be thrown, orRETRY_ABORT, which
means the executor will try to submit it once more, before throwing an exception.
Management clients, such as the WildFly CLI, may also be used to configure Managed Scheduled Executor
Service instances. An example to add and remove one named other:
/subsystem=ee/managed-scheduled-executor-service=other:add(jndi-name=java\:jboss\/ee\/scheduler\/other,
core-threads=2)
/subsystem=ee/managed-scheduled-executor-service=other:remove
WildFly 9
Global Modules
Global modules is a set of JBoss Modules that will be added as dependencies to the JBoss Module of every
Java EE deployment. Such dependencies allows Java EE deployments to see the classes exported by the
global modules.
Each global module is defined through the module resource, an example of its XML configuration:
<global-modules>
<module name="org.jboss.logging" slot="main"/>
<module name="org.apache.log4j" annotations="true" meta-inf="true" services="false" />
</global-modules>
The only mandatory attribute is the JBoss Module name, the slot attribute defaults to main, and both
define the JBoss Module ID to reference.
The optional annotations attribute, which defaults to false, indicates if a pre-computed annotation index
should be imported from META-INF/jandex.idx
The optional services attribute indicates if any services exposed in META-INF/services should be made
available to the deployments class loader, and defaults to false.
The optional meta-inf attribute, which defaults to true, indicates if the Module's META-INF path should
be available to the deployment's class loader.
WildFly 9
<ear-subdeployments-isolated>true</ear-subdeployments-isolated>
For example:
myapp.ear
|
|--- web.war
|
|--- ejb1.jar
|
|--- ejb2.jar
If the ear-subdeployments-isolated is set to false, then the classes in web.war can access classes
belonging to ejb1.jar and ejb2.jar. Similarly, classes from ejb1.jar can access classes from
ejb2.jar (and vice-versa).
This flag has no effect on the isolated classloader of the .war file(s), i.e. irrespective of whether
this flag is set to true or false, the .war within a .ear will have a isolated classloader, and
other subdeployments within that .ear will not be able to access classes from that .war. This is
as per spec.
WildFly 9
Property Replacement
The EE subsystem configuration includes flags to configure whether system property replacement will be
done on XML descriptors and Java Annotations, included in Java EE deployments.
System properties etc are resolved in the security context of the application server itself, not the
deployment that contains the file. This means that if you are running with a security manager and
enable this property, a deployment can potentially access system properties or environment entries
that the security manager would have otherwise prevented.
<spec-descriptor-property-replacement>false</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>false</jboss-descriptor-property-replacement>
<annotation-property-replacement>false</annotation-property-replacement>
WildFly 9
import
import
import
import
javax.management.MBeanServerConnection;
javax.management.remote.JMXConnector;
javax.management.remote.JMXConnectorFactory;
javax.management.remote.JMXServiceURL;
You also need to set your classpath when running the above example. The following script covers Linux. If
your environment is much different, paste your script when you have it working.
!/bin/bash
# specify your WildFly 8 folder
export YOUR_JBOSS_HOME=~/WildFly8
java -classpath $YOUR_JBOSS_HOME/bin/client/jboss-client.jar:./ JMXExample
If using jconsole use the jconsole.sh and jconsole.bat scripts included in the /bin directory
of the WildFly 8 distribution as these set the classpath as required to connect over Remoting.
In addition to the standard JVM MBeans, the WildFly 8 MBean server contains the following MBeans:
WildFly 9
JMX ObjectName
Description
Audit logging
Audit logging for the JMX MBean server managed by the JMX subsystem. The resource is at
/subsystem=jmx/configuration=audit-log and its attributes are similar to the ones mentioned for
/core-service=management/access=audit/logger=audit-log in Audit logging.
Attribute
Description
enabled
log-boot
true to log the JMX operations when booting the server, false otherwise
log-read-only If true all operations will be audit logged, if false only operations that change the
model will be logged
Then which handlers are used to log the management operations are configured as handler=* children of
the logger. These handlers and their formatters are defined in the global
/core-service=management/access=audit section mentioned in Audit logging.
JSON Formatter
The same JSON Formatter is used as described in Audit logging. However the records for MBean Server
invocations have slightly different fields from those logged for the core management layer.
WildFly 9
2013-08-29 18:26:29 - {
"type" : "jmx",
"r/o" : false,
"booting" : false,
"version" : "8.0.0.Beta1-SNAPSHOT",
"user" : "$local",
"domainUUID" : null,
"access" : "JMX",
"remote-address" : "127.0.0.1/127.0.0.1",
"method" : "invoke",
"sig" : [
"javax.management.ObjectName",
"java.lang.String",
"[Ljava.lang.Object;",
"[Ljava.lang.String;"
],
"params" : [
"java.lang:type=Threading",
"getThreadInfo",
"[Ljava.lang.Object;@5e6c33c",
"[Ljava.lang.String;@4b681c69"
]
}
It includes an optional timestamp and then the following information in the json record
WildFly 9
Field name
Description
type
This will have the value jmx meaning it comes from the jmx subsystem
r/o
booting
true if the operation was executed during the bootup process, false if it was
executed once the server is up and running
version
user
domainUUID
access
sig
params
error
If calling the MBeanServer method resulted in an error, this field will be populated with
Throwable.getMessage()
WildFly 9
WildFly 9
Overview
The overall server logging configuration is represented by the logging subsystem. It consists of four notable
parts: handler configurations, logger, the root logger declarations (aka log categories) and logging
profiles. Each logger does reference a handler (or set of handlers). Each handler declares the log format and
output:
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE" autoflush="true">
<level name="DEBUG"/>
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
</console-handler>
<periodic-rotating-file-handler name="FILE" autoflush="true">
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN"/>
</logger>
[...]
<root-logger>
<level name="DEBUG"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
</subsystem>
Attributes
The root resource contains two notable attributes add-logging-api-dependencies and
use-deployment-logging-config.
logging-api-dependencies
The add-logging-api-dependencies controls whether or not the container adds implicit logging API
dependencies to your deployments. If set to true, the default, all the implicit logging API dependencies are
added. If set to false the dependencies are not added to your deployments.
deployment-logging-config
The use-deployment-logging-config controls whether or not your deployment is scanned for
per-deployment logging. If set to true, the default, per-deployment logging is enabled. Set to false to
disable this feature.
WildFly 9
deployment Logging
Per-deployment logging allows you to add a logging configuration file to your deployment and have the
logging for that deployment configured according to the configuration file. In an EAR the configuration should
be in the META-INF directory. In a WAR or JAR deployment the configuration file can be in either the
META-INF or WEB-INF directories.
The following configuration files are allowed:
logging.properties
jboss-logging.properties
log4j.properties
log4j.xml
jboss-log4j.xml
You can also disable this functionality by changing the use-deployment-logging-config attribute to
false.
Logging Profiles
Logging profiles are like additional logging subsystems. Each logging profile constists of three of the four
notable parts listed above: handler configurations, logger and the root logger declarations.
You can assign a logging profile to a deployment via the deployments manifest. Add a Logging-Profile
entry to the MANIFEST.MF file with a value of the logging profile id. For example a logging profile defined on
/subsystem=logging/logging-profile=ejbs the MANIFEST.MF would look like:
Manifest-Version: 1.0
Logging-Profile: ejbs
A logging profile can be assigned to any number of deployments. Using a logging profile also allows for
runtime changes to the configuration. This is an advantage over the per-deployment logging configuration as
the redeploy is not required for logging changes to take affect.
WildFly 9
Log File
Host Controller
./domain/log/host-controller.log
./domain/servers/server-one/log/server.log
"Server Two"
./domain/servers/server-two/log/server.log
"Server Three"
./domain/servers/server-three/log/server.log
Standalone Server
The default log files for a standalone server can be found in the log subdirectory of the distribution:
Process Log File
Server
./standalone/log/server.log
Filter Expressions
Filter Type
Expression
Description
Parameter(s)
Examples
accept
accept
None
accept
None
deny
Accepts a filter as
The expression
not(match("JBAS"))
an argument and
takes a single
inverts the
returned value.
argument.
messages.
deny
deny
not
not(filterExpression)
WildFly 9
all
all(filterExpressions)
A filter consisting
The expression
all(match("JBAS"),
of several filters in
takes a comma
match("WELD"))
a chain. If any
delimited list of
message to be
argument.
unloggable, the
message will not
be logged and
subsequent filters
will not be
checked.
any
any(filterExpressions)
A filter consisting
The expression
any(match("JBAS"),
of several filters in
takes a comma
match("WELD"))
a chain. If any
delimited list of
message to be
argument.
loggable, the
message will be
logged and the
subsequent filters
will not be
checked.
levelChange levelChange(level)
levels
levels(levels)
A filter which
The expression
levelChange("WARN")
takes a single
level.
A filter which
The expression
levels("DEBUG", "INFO",
includes log
takes a comma
"WARN", "ERROR")
messages with a
delimited list of
string based
WildFly 9
levelRange
The filter
expression uses
a "[" to indicate a
range.
minimum
inclusive level
and a "]" to
than DEBUG
indicate a
maximum
levelRange("ERROR",
inclusive level.
"DEBUG")
or ")" respectively
indicate
exclusive. The
be greater than
the expression is
DEBUG
the minimum
level allowed, the
levelRange["ERROR",
second argument
"DEBUG")
is the maximum
level allowed.
match
match("pattern")
The expression
raw unformatted
argument.
message is used
match("JBAS\d+")
against the
pattern.
substitute
substitute("pattern",
A filter which
The first
"replacement value")
match to the
expression is the
pattern the
replacement
second argument
value.
is the
substitute("JBAS", "EAP")
replacement text.
WildFly 9
substituteAll substituteAll("pattern",
"replacement value")
A filter which
The first
replaces all
matches of the
expression is the
pattern the
replacement
second argument
value.
is the
substituteAll("JBAS", "EAP")
replacement text.
WildFly 9
Description
the number of lines from the file. A value of -1 indicates all lines should be read.
skip
tail
true to read from the end of the file up or false to read top down.
WildFly 9
FAQ
Why is there a logging.properties file?
You may have noticed that there is a logging.properties file in the configuration directory. This is
logging configuration is used when the server boots up until the logging subsystem kicks in. If the logging
subsystem is not included in your configuration, then this would act as the logging configuration for the entire
server.
The logging.properties file is overwritten at boot and with each change to the logging
subsystem. Any changes made to the file are not persisted. Any changes made to the XML
configuration or via management operations will be persisted to the logging.properties file
and used on the next boot.
Handlers
WIP
This is still a work in progress. Please feel free to edit any mistakes you find
Overview
Handlers are used to determine what happens with a log message if the logger determines the message is
loggable.
There are 6 main handlers provided with WildFly and 1 generic handler;
async-handler
console-handler
file-handler
periodic-rotating-file-handler
size-rotating-file-handler
syslog-handler
custom-handler
WildFly 9
async-handler
An async-handler is a handler that asynchronously writes log messages to it's child handlers. This type of
handler is generally used for other handlers that take a substantial time to write logged messages.
Attributes
enabled
filter-spec
level
overflow-action
queue-length
subhandlers
console-handler
A console-handler is a handler that writes log messages to the console. Generally this writes to stdout,
but can be set to write to stderr.
Attributes
autoflush
enabled
encoding
filter-spec
formatter
level
named-formatter
target
file-handler
A file-handler is a handler that writes log messages to the specified file.
Attributes
autoflush
enabled
encoding
filter-spec
formatter
level
named-formatter
file
WildFly 9
periodic-rotating-file-handler
A periodic-rotating-file-handler is a handler that writes log messages to the specified file. The file
rotates on the date pattern specified in the suffix attribute. The suffix must be a valid pattern recognized by
the java.text.SimpleDateFormat and must not rotate on seconds or milliseconds.
The rotate happens before the next message is written by the handler.
Attributes
autoflush
enabled
encoding
filter-spec
formatter
level
named-formatter
file
suffix
size-rotating-file-handler
A size-rotating-file-handler is a handler that writes log messages to the specified file. The file
rotates when the file size is greater than the rotate-size attribute. The rotated file will be kept and the index
appended to the name moving previously rotated file indexes up by 1 until the max-backup-index is reached.
Once the max-backup-index is reached, the indexed files will be overwritten.
The rotate happens before the next message is written by the handler.
Attributes
autoflush
enabled
encoding
filter-spec
formatter
level
named-formatter
file
max-backup-index
rotate-size
rotate-on-boot
WildFly 9
syslog-handler
A syslog-handler is a handler that writes to a syslog server. The handler support RFC3164 or RFC5424
formats.
Attributes
port
app-name
enabled
level
facility
server-address
hostname
syslog-format
The syslog-handler is missing some configuration properties that may be useful in some scenarios
like setting a formatter. Use the org.jboss.logmanager.handlers.SyslogHandler in
module org.jboss.logmanager as a custom-handler to exploit these benefits. Additional
attributes will be added at some point so this will no longer be necessary.
custom-handler
Attributes
autoflush
Description:
Type:
boolean
Default Value:
true
WildFly 9
enabled
Description: If set to true the handler is enabled and functioning as normal, if set to false the handler
is ignored when processing log messages.
Type:
boolean
Default
true
Value:
Allowed
true or false
Values:
encoding
Description:
Type:
string
Default Value:
null
file
Description:
Type:
object
Default
null
Value:
Allowed
An object optionally containing a relative-to property and a path. The path is a required
Values:
WildFly 9
named-formatter
Description:
Type:
string
Default Value:
null
formatter
Description:
Type:
string
Default Value:
filter-spec
Description:
Type:
string
Default Value:
null
WildFly 9
level
Description The log level specifying which message levels will be logged by this logger. Message
:
Type:
string
Default
ALL
Value:
Allowed
ALL
Values:
FINEST
FINER
TRACE
DEBUG
FINE
CONFIG
INFO
WARN
WARNING
ERROR
SEVERE
FATAL
OFF
backup-index
Description:
Type:
integer
Default Value:
WildFly 9
overflow-action
Description:
Type:
string
Default Value:
BLOCK
queue-length
Description:
Type:
integer
Default Value:
rotate-on-boot
Description:
Indicates whether or not the file should be rotated each time the file attribute is
changed.
Type:
boolean
Default Value:
false
Allowed
true or false
Values:
WildFly 9
rotate-size
string
Default
2m
Value:
Allowed
Any positive integer with a size type appended to the end. Valid types are b for bytes, k
Values:
for kilobytes, m for megabytes, g for gigabytes or t for terabytes. Type character is not
case sensitive.
subhandlers
Description:
Type:
list of strings
Default Value:
null
suffix
Description:
Type:
string
Default Value:
null
WildFly 9
target
Description:
Type:
string
Default Value:
System.out
How To
How do I add a log category?
How do I change a log level?
How do I log my applications messages to their own file?
How do I use log4j.properties or log4j.xml instead of using the logging subsystem configuration?
How do I use my own version of log4j?
/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level,value=DEBUG)
/subsystem=logging/logger=com.your.category:write-attribute(name=level,value=ALL)
WildFly 9
/subsystem=logging/file-handler=fh:add(level=INFO,
file={"relative-to"=>"jboss.server.log.dir", "path"=>"fh.log"}, append=false,
autoflush=true)
/subsystem=logging/logger=org.your.company:add(use-parent-handlers=false,handlers=\["fh"\])
Loggers
Overview
Logger Resource
filter-spec
handlers
level
use-parent-handlers
Root Logger Resource
Logger Hierarchy
WildFly 9
WIP
This is still a work in progress. Please feel free to edit any mistakes you find
Overview
Loggers are used to log messages. A logger is defined by a category generally consisting of a package
name or a class name.
A logger is the first step to determining if a messages should be logged or not. If a logger is defined with a
level, the level of the message must be greater than the level defined on the logger. The filter is then
checked next and the rules of the filter will determine whether or not the messages is said to be loggable.
WildFly 9
Logger Resource
A logger resource uses the path subsystem=logging/logger=$category where $category is the of
the logger. For example to a logger named org.wildfly.example would have a resource path of
subsystem=logging/logger=org.wildfly.example.
A logger as 4 writeable attributes;
filter-spec
handlers
level
use-parent-handlers
You may notice that the category and filter attributes are missing. While filter is writable it
may be deprecated and removed in the future. Both attributes are still on the resource for legacy
reasons.
filter-spec
The filter-spec attribute is an expression based string to define filters for the logger.
handlers
The handlers attribute is a list of handler names that should be attached to the logger. If the
use-parent-handlers attribute is set to true and the log messages is determined to be loggable, parent
loggers will continue to be processed.
level
The level attribute allows the minimum level to allow messages to be logged at for the logger.
parent-handlers
The use-parent-handlers attribute is a boolean attribute to determine whether or not parent loggers
should also process the log message.
Logger Hierarchy
A logger hierarchy is defined by it's category. The category is a . (dot) delimited string generally consisting
of the package name or a class name. For example the logger org.wildfly is the parent logger of
org.wildfly.example.
WildFly 9
Connectors
There are three kind of connectors that can be used to connect to WildFly JMS Server
invm-connector can be used by a local client (i.e. one running in the same JVM as the server)
netty-connector can be used by a remote client (and uses Netty over TCP for the
communication)
http-connector can be used by a remote client (and uses Undertow Web Server to upgrade from
a HTTP connection)
WildFly 9
A netty-connector is associated with a socket-binding which tells the client using the
connection-factory where to connect.
A connection-factory referencing a netty-connector is suitable to be used by a remote client
to send messages to or receive messages from the server (assuming the connection-factory has an
appropriately exported entry).
A pooled-connection-factory looked up in JNDI or injected which is referencing a
netty-connector is suitable to be used by a local client to send messages to a remote server
granted the socket-binding references an outbound-socket-binding pointing to the remote
server in question.
A pooled-connection-factory used by an MDB which is referencing a netty-connector is
suitable to consume messages from a remote server granted the socket-binding references an
outbound-socket-binding pointing to the remote server in question.
An in-vm-connector is associated with a server-id which tells the client using the
connection-factory where to connect (since multiple HornetQ servers can run in a single JVM).
A connection-factory referencing an in-vm-connector is suitable to be used by a local client
to either send messages to or receive messages from a local server.
A pooled-connection-factory looked up in JNDI or injected which is referencing an
in-vm-connector is suitable to be used by a local client only to send messages to a local server.
A pooled-connection-factory used by an MDB which is referencing an in-vm-connector is
suitable only to consume messages from a local server.
A http-connector is associated with the socket-binding that represents the HTTP socket (by default,
named http).
A connection-factory referencing a http-connector is suitable to be used by a remote client
to send messages to or receive messages from the server by connecting to its HTTP port before
upgrading to the messaging protocol.
A pooled-connection-factory referencing a http-connector is suitable to be used by a local
client to send messages to a remote server granted the socket-binding references an
outbound-socket-binding pointing to the remote server in question.
A pooled-connection-factory used by an MDB which is referencing a http-connector is
suitable only to consume messages from a remote server granted the socket-binding references
an outbound-socket-binding pointing to the remote server in question.
WildFly 9
The entry declaration of a connection-factory or a pooled-connection-factory specifies the
JNDI name under which the factory will be exposed. Only JNDI names bound in the
"java:jboss/exported" namespace are available to remote clients. If a connection-factory has
an entry bound in the "java:jboss/exported" namespace a remote client would look-up the
connection-factory using the text after "java:jboss/exported". For example, the "
RemoteConnectionFactory" is bound by default to
"java:jboss/exported/jms/RemoteConnectionFactory" which means a remote client would
look-up this connection-factory using "jms/RemoteConnectionFactory". A
pooled-connection-factory should not have any entry bound in the "java:jboss/exported"
namespace because a pooled-connection-factory is not suitable for remote clients.
Since JMS 2.0, a default JMS connection factory is accessible to EE application under the JNDI name
java:comp/DefaultJMSConnectionFactory. WildFly messaging subsystem defines a
pooled-connection-factory that is used to provide this default connection factory. Any parameter
change on this pooled-connection-factory will be take into account by any EE application looking the
default JMS provider under the JNDI name java:comp/DefaultJMSConnectionFactory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<connectors>
<http-connector name="http-connector" socket-binding="http">
<param key="http-upgrade-endpoint" value="http-acceptor"/>
</http-connector>
<http-connector name="http-connector-throughput" socket-binding="http">
<param key="http-upgrade-endpoint" value="http-acceptor-throughput"/>
<param key="batch-delay" value="50"/>
</http-connector>
<in-vm-connector name="in-vm" server-id="0"/>
</connectors>
[...]
<jms-connection-factories>
<connection-factory name="InVmConnectionFactory">
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/ConnectionFactory"/>
</entries>
</connection-factory>
<connection-factory name="RemoteConnectionFactory">
<connectors>
<connector-ref connector-name="http-connector"/>
</connectors>
<entries>
<entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
</entries>
</connection-factory>
<pooled-connection-factory name="hornetq-ra">
<transaction mode="xa"/>
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/JmsXA"/>
<!-- Global JNDI entry used to provide a default JMS Connection factory to EE
application -->
<entry name="java:jboss/DefaultJMSConnectionFactory"/>
</entries>
</pooled-connection-factory>
</jms-connection-factories>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<jms-destinations>
<jms-queue name="testQueue">
<entry name="jms/queue/test"/>
<entry name="java:jboss/exported/jms/queue/test"/>
</jms-queue>
<jms-topic name="testTopic">
<entry name="jms/topic/test"/>
<entry name="java:jboss/exported/jms/topic/test"/>
</jms-topic>
</jms-destinations>
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
[standalone@localhost:9990 /]
/subsystem=messaging/hornetq-server=default/jms-queue=myQueue:read-resource
{
"outcome" => "success",
"result" => {
"durable" => true,
"entries" => ["queues/myQueue"],
"selector" => undefined
}
}
WildFly 9
A number of additional commands to maintain the JMS subsystem are available as well:
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<address-settings>
<address-setting match="#">
<dead-letter-address>jms.queue.DLQ</dead-letter-address>
<expiry-address>jms.queue.ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
[...]
</address-setting>
</address-settings>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
WildFly 9
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<security-settings>
<security-setting match="#">
<permission type="send" roles="guest"/>
<permission type="consume" roles="guest"/>
<permission type="createNonDurableQueue" roles="role1"/>
<permission type="deleteNonDurableQueue" roles="role1 role2"/>
</security-setting>
</security-settings>
[...]
</hornetq-server>
</subsystem>
(See standalone/configuration/standalone-full.xml)
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<hornetq-server>
[...]
<security-domain>mySecurityDomain</security-domain>
[...]
</hornetq-server>
</subsystem>
WildFly 9
Cluster Authentication
If the HornetQ server is configured to be clustered ( <clustered>true</clustered> ), it will use the
<cluster-user> and <cluster-password> attributes to connect to other HornetQ nodes in the cluster.
If you do not change the default value of <cluster-password>, HornetQ will fail to authenticate with the error:
To prevent this error, you must specify a value for <cluster-password>. It is possible to encrypt this
value by following this guide.
Alternatively, you can use the system property jboss.messaging.cluster.password to specify the cluster
password from the command line.
This feature is primarily intended for development as destinations deployed this way can not be
managed with any of the provided management tools (e.g. console, CLI, etc).
JMS Bridge
The function of a JMS bridge is to consume messages from a source JMS destination, and send them to a
target JMS destination. Typically either the source or the target destinations are on different servers.
The bridge can also be used to bridge messages from other non HornetQ JMS servers, as long as they are
JMS 1.1 compliant.
The JMS Bridge is provided by the HornetQ project. For a detailed description of the available configuration
properties, please consult the project documentation.
WildFly 9
modules/
`-- org
`-- acmemq
`-- main
|-- acmemq-1.2.3.jar
|-- mylogapi-0.0.1.jar
`-- module.xml
WildFly 9
<resources>
<!-- insert resources required to connect to the source or target
<!-- messaging brokers if it not another WildFly instance
<resource-root path="acmemq-1.2.3.jar" />
<resource-root path="mylogapi-0.0.1.jar" />
</resources>
<dependencies>
<!-- add the dependencies required by JMS Bridge code
<module name="javax.api" />
<module name="javax.jms.api" />
<module name="javax.transaction.api"/>
<module name="org.jboss.remote-naming"/>
<!-- we depend on org.hornetq module since we will send messages to
<!-- the HornetQ server embedded in the local WildFly instance
<module name="org.hornetq" />
</dependencies>
</module>
-->
-->
-->
-->
-->
WildFly 9
Configuration
A JMS bridge is defined inside a jms-bridge section of the `messaging` subsystem in the XML
configuration files.
<subsystem xmlns="urn:jboss:domain:messaging:2.0">
<jms-bridge name="myBridge" module="org.acmemq">
<source>
<connection-factory name="ConnectionFactory"/>
<destination name="sourceQ"/>
<user>user1</user>
<password>pwd1</password>
<context>
<property key="java.naming.factory.initial"
value="org.acmemq.jndi.AcmeMQInitialContextFactory"/>
<property key="java.naming.provider.url"
value="tcp://127.0.0.1:9292"/>
</context>
</source>
<target>
<connection-factory name="/jms/invmTargetCF"/>
<destination name="/jms/targetQ"/>
</target>
<quality-of-service>AT_MOST_ONCE</quality-of-service>
<failure-retry-interval>500</failure-retry-interval>
<max-retries>1</max-retries>
<max-batch-size>500</max-batch-size>
<max-batch-time>500</max-batch-time>
<add-messageID-in-header>true</add-messageID-in-header>
</jms-bridge>
</subsystem>
The source and target sections contain the name of the JMS resource (connection-factory and
destination) that will be looked up in JNDI.
It optionally defines the user and password credentials. If they are set, they will be passed as arguments
when creating the JMS connection from the looked up ConnectionFactory.
It is also possible to define JNDI context properties in the context section. If the context section is
absent, the JMS resources will be looked up in the local WildFly instance (as it is the case in the target
section in the example above).
WildFly 9
Management commands
A JMS Bridge can also be managed using the WildFly command line interface:
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=myBridge/:add(module="org.acmemq",
\
source-destination="sourceQ",
\
source-connection-factory="ConnectionFactory",
\
source-user="user1",
\
source-password="pwd1",
\
source-context={"java.naming.factory.initial" =>
"org.acmemq.jndi.AcmeMQInitialContextFactory", \
"java.naming.provider.url" => "tcp://127.0.0.1:9292"},
\
target-destination="/jms/targetQ",
\
target-connection-factory="/jms/invmTargetCF",
\
quality-of-service=AT_MOST_ONCE,
\
failure-retry-interval=500,
\
max-retries=1,
\
max-batch-size=500,
\
max-batch-time=500,
\
add-messageID-in-header=true)
{"outcome" => "success"}
You can also see the complete JMS Bridge resource description from the CLI:
[standalone@localhost:9990 /] /subsystem=messaging/jms-bridge=*/:read-resource-description
{
"outcome" => "success",
"result" => [{
"address" => [
("subsystem" => "messaging"),
("jms-bridge" => "*")
],
"outcome" => "success",
"result" => {
"description" => "A JMS bridge instance.",
"attributes" => {
...
}
}]
}
WildFly 9
Component Reference
The messaging subsystem is provided by the HornetQ project. For a detailed description of the available
configuration properties, please consult the project documentation.
WildFly 9
<subsystem xmlns="urn:jboss:domain:naming:2.0">
<bindings>
<simple name="java:global/a" value="100" type="int" />
<simple name="java:global/jboss.org/docs/url" value="https://docs.jboss.org"
type="java.net.URL" />
<object-factory name="java:global/foo/bar/factory" module="org.foo.bar"
class="org.foo.bar.ObjectFactory" />
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
<lookup name="java:global/c" lookup="java:global/b" />
</bindings>
<remote-naming/>
</subsystem>
WildFly 9
If WildFly is to be used as a Java EE application server, then it's recommended to opt for
java:global, since it is a standard (i.e. portable) namespace.
<bindings>
<simple name="java:global/a" value="100" type="int" />
<object-factory name="java:global/foo/bar/factory" module="org.foo.bar"
class="org.foo.bar.ObjectFactory" />
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
<lookup name="java:global/c" lookup="java:global/b" />
</bindings>
WildFly 9
Simple Bindings
A simple binding is a primitive or java.net.URL entry, and it is defined through the simple XML element. An
example of its XML configuration:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The value attribute is mandatory and defines the entry's value.
The optional type attribute, which defaults to java.lang.String, specifies the type of the entry's value.
Besides java.lang.String, allowed types are all the primitive types and their corresponding object wrapper
classes, such as int or java.lang.Integer, and java.net.URL.
Management clients, such as the WildFly CLI, may be used to configure simple bindings. An example to add
and remove the one in the XML example above:
WildFly 9
Object Factories
The Naming subsystem configuration allows the binding of javax.naming.spi.ObjectFactory entries,
through the object-factory XML element, for instance:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The class attribute is mandatory and defines the object factory's Java type.
The module attribute is mandatory and specifies the JBoss Module ID where the object factory Java class
may be loaded from.
The optional environment child element may be used to provide a custom environment to the object
factory.
Management clients, such as the WildFly CLI, may be used to configure object factory bindings. An example
to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:add(binding-type=object-factory,
module=org.foo.bar, class=org.foo.bar.ObjectFactory, environment=[p1=v1, p2=v2])
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:remove
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
The name attribute is mandatory and specifies the target JNDI name for the entry.
WildFly 9
The class attribute is mandatory and indicates the Java initial naming context type used to create the
federated context. Note that such type must have a constructor with a single environment map argument.
The optional module attribute specifies the JBoss Module ID where any classes required by the external
JNDI context may be loaded from.
The optional cache attribute, which value defaults to false, indicates if the external context instance
should be cached.
The optional environment child element may be used to provide the custom environment needed to
lookup the external context.
Management clients, such as the WildFly CLI, may be used to configure external context bindings. An
example to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:add(binding-type=external-context,
cache=true, class=javax.naming.directory.InitialDirContext,
environment=[java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory,
java.naming.provider.url=ldap\:\/\/ldap.example.com\:389,
java.naming.security.authentication=simple,
java.naming.security.principal=uid\=admin\,ou\=system, java.naming.security.credentials=
secret])
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:remove
Some JNDI providers may fail when their resources are looked up if they do not implement properly the
lookup(Name) method. Their errors would look like:
11:31:49,047 ERROR org.jboss.resource.adapter.jms.inflow.JmsActivation (default-threads
-1) javax.naming.InvalidNameException: Only support CompoundName names
at com.tibco.tibjms.naming.TibjmsContext.lookup(TibjmsContext.java:504)
at javax.naming.InitialContext.lookup(InitialContext.java:421)
To work around their shortcomings, the org.jboss.as.naming.lookup.by.string property can be
specified in the external-context's environment to use instead the lookup(String) method (with a performance
degradation):
Binding Aliases
The Naming subsystem configuration allows the binding of existent entries into additional names, i.e.
aliases. Binding aliases are specified through the lookup XML element. An example of its XML
configuration:
WildFly 9
The name attribute is mandatory and specifies the target JNDI name for the entry.
The lookup attribute is mandatory and indicates the source JNDI name.
Management clients, such as the WildFly CLI, may be used to configure binding aliases. An example to add
and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/c:add(binding-type=lookup, lookup=java\:global\/b)
/subsystem=naming/binding=java\:global\/c:remove
Only entries within the java:jboss/exported context are accessible over remote JNDI.
In the subsystem's XML configuration, remote JNDI access bindings are configured through the
<remote-naming /> XML element:
<remote-naming />
Management clients, such as the WildFly CLI, may be used to add/remove the remote JNDI interface. An
example to add and remove the one in the XML example above:
/subsystem=naming/service=remote-naming:add
/subsystem=naming/service=remote-naming:remove
If WildFly is to be used as a Java EE application server, then it's recommended to opt for
java:global, since it is a standard (i.e. portable) namespace.
WildFly 9
Simple
Object Factory
External Context
Lookup
In the subsystem's XML configuration, global bindings are configured through the <bindings /> XML
element, as an example:
<bindings>
<simple name="java:global/a" value="100" type="int" />
<object-factory name="java:global/foo/bar/factory" module="org.foo.bar"
class="org.foo.bar.ObjectFactory" />
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial"
value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
<lookup name="java:global/c" lookup="java:global/b" />
</bindings>
Simple Bindings
A simple binding is a primitive or java.net.URL entry, and it is defined through the simple XML element. An
example of its XML configuration:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The value attribute is mandatory and defines the entry's value.
The optional type attribute, which defaults to java.lang.String, specifies the type of the entry's value.
Besides java.lang.String, allowed types are all the primitive types and their corresponding object wrapper
classes, such as int or java.lang.Integer, and java.net.URL.
Management clients, such as the WildFly CLI, may be used to configure simple bindings. An example to add
and remove the one in the XML example above:
WildFly 9
Object Factories
The Naming subsystem configuration allows the binding of javax.naming.spi.ObjectFactory entries,
through the object-factory XML element, for instance:
The name attribute is mandatory and specifies the target JNDI name for the entry.
The class attribute is mandatory and defines the object factory's Java type.
The module attribute is mandatory and specifies the JBoss Module ID where the object factory Java class
may be loaded from.
The optional environment child element may be used to provide a custom environment to the object
factory.
Management clients, such as the WildFly CLI, may be used to configure object factory bindings. An example
to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:add(binding-type=object-factory,
module=org.foo.bar, class=org.foo.bar.ObjectFactory, environment=[p1=v1, p2=v2])
/subsystem=naming/binding=java\:global\/foo\/bar\/factory:remove
<external-context name="java:global/federation/ldap/example"
class="javax.naming.directory.InitialDirContext" cache="true">
<environment>
<property name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory" />
<property name="java.naming.provider.url" value="ldap://ldap.example.com:389" />
<property name="java.naming.security.authentication" value="simple" />
<property name="java.naming.security.principal" value="uid=admin,ou=system" />
<property name="java.naming.security.credentials" value="secret" />
</environment>
</external-context>
The name attribute is mandatory and specifies the target JNDI name for the entry.
WildFly 9
The class attribute is mandatory and indicates the Java initial naming context type used to create the
federated context. Note that such type must have a constructor with a single environment map argument.
The optional module attribute specifies the JBoss Module ID where any classes required by the external
JNDI context may be loaded from.
The optional cache attribute, which value defaults to false, indicates if the external context instance
should be cached.
The optional environment child element may be used to provide the custom environment needed to
lookup the external context.
Management clients, such as the WildFly CLI, may be used to configure external context bindings. An
example to add and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:add(binding-type=external-context,
cache=true, class=javax.naming.directory.InitialDirContext,
environment=[java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory,
java.naming.provider.url=ldap\:\/\/ldap.example.com\:389,
java.naming.security.authentication=simple,
java.naming.security.principal=uid\=admin\,ou\=system, java.naming.security.credentials=
secret])
/subsystem=naming/binding=java\:global\/federation\/ldap\/example:remove
Some JNDI providers may fail when their resources are looked up if they do not implement properly the
lookup(Name) method. Their errors would look like:
11:31:49,047 ERROR org.jboss.resource.adapter.jms.inflow.JmsActivation (default-threads
-1) javax.naming.InvalidNameException: Only support CompoundName names
at com.tibco.tibjms.naming.TibjmsContext.lookup(TibjmsContext.java:504)
at javax.naming.InitialContext.lookup(InitialContext.java:421)
To work around their shortcomings, the org.jboss.as.naming.lookup.by.string property can be
specified in the external-context's environment to use instead the lookup(String) method (with a performance
degradation):
Binding Aliases
The Naming subsystem configuration allows the binding of existent entries into additional names, i.e.
aliases. Binding aliases are specified through the lookup XML element. An example of its XML
configuration:
WildFly 9
The name attribute is mandatory and specifies the target JNDI name for the entry.
The lookup attribute is mandatory and indicates the source JNDI name.
Management clients, such as the WildFly CLI, may be used to configure binding aliases. An example to add
and remove the one in the XML example above:
/subsystem=naming/binding=java\:global\/c:add(binding-type=lookup, lookup=java\:global\/b)
/subsystem=naming/binding=java\:global\/c:remove
Only entries within the java:jboss/exported context are accessible over remote JNDI.
In the subsystem's XML configuration, remote JNDI access bindings are configured through the
<remote-naming /> XML element:
<remote-naming />
Management clients, such as the WildFly CLI, may be used to add/remove the remote JNDI interface. An
example to add and remove the one in the XML example above:
/subsystem=naming/service=remote-naming:add
/subsystem=naming/service=remote-naming:remove
More information on the OSGi component in WildFly can be found on the JBoss OSGi project
pages.
WildFly 9
<subsystem xmlns="urn:jboss:domain:resource-adapters:1.0">
<resource-adapters>
<resource-adapter>
<archive>eis.rar</archive>
<!-- Resource adapter level config-property -->
<config-property name="Server">localhost</config-property>
<config-property name="Port">19000</config-property>
<transaction-support>XATransaction</transaction-support>
<connection-definitions>
<connection-definition class-name="com.acme.eis.ra.EISManagedConnectionFactory"
jndi-name="java:/eis/AcmeConnectionFactory"
pool-name="AcmeConnectionFactory">
<!-- Managed connection factory level config-property -->
<config-property name="Name">Acme Inc</config-property>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>100</max-pool-size>
</pool>
<security>
<application/>
</security>
</connection-definition>
</connection-definitions>
<admin-objects>
<admin-object class-name="com.acme.eis.ra.EISAdminObjectImpl"
jndi-name="java:/eis/AcmeAdminObject">
<config-property name="Threshold">10</config-property>
</admin-object>
</admin-objects>
</resource-adapter>
</resource-adapters>
</subsystem>
Note, that only JNDI bindings under java:/ or java:jboss/ are supported.
(See
standalone/configuration/standalone.xml)
WildFly 9
Component Reference
The resource adapter subsystem is provided by the IronJacamar project. For a detailed description of the
available configuration properties, please consult the project documentation.
IronJacamar homepage: http://www.jboss.org/ironjacamar
Project Documentation: http://www.jboss.org/ironjacamar/docs
Schema description:
http://docs.jboss.org/ironjacamar/userguide/1.0/en-US/html/deployment.html#deployingra_descriptor
WildFly 9
Authentication Manager
The authentication manager is the component that performs the actual authentication taking the declared
users identity and their credential so that the login context for the security domain can be used to 'login' the
user using the configured login module or modules.
Authorization Manager
The authorization manager is a component which can be obtained by the container from the current security
context to either obtain information about a users roles or to perform an authorization check against a
resource for the currently authenticated user.
Audit Manager
The audit manager from the security context is the component that can be used to log audit events in
relation to the security domain.
Mapping Manager
The mapping manager can be used to assign additional principals, credentials, roles or attributes to the
authenticated subject.
WildFly 9
security-management
subject-factory
security-domains
security-properties
security-management
This element is used to override some of the high level implementation details of the PicketBox
implementation if you have a need to change some of this behaviour.
The element can have any or the following attributes set, all of which are optional.
authentication-manager-class-name Specifies the AuthenticationManager implementation class name to
use.
deep-copy-subject-mode
audit-manager-class-name
identity-trust-manager-class-name
mapping-manager-class-name
subject-factory
The subject factory is responsible for creating subject instances, this also makes use of the authentication
manager to actually verify the caller. It is used mainly by JCA components to establish a subject. It is not
likely this would need to be overridden but if it is required the "subject-factory-class-name" attribute can be
specified on the subject-factory element.
security-domains
This portion of the configuration is where the bulk of the security subsystem configuration will actually take
place for most administrators, the security domains contain the configuration which is specific to a
deployment.
WildFly 9
The security-domains element can contain numerous <security-domain> definitions, a security-domain can
have the following attributes set:
name
extends
cache-type The type of authentication cache to use with this domain. If this attribute is removed no cache
will be used. Allowed values are "default" or "infinispan"
The following elements can then be set within the security-domain to configure the domain behaviour.
authentication
The authentication element is used to hold the list of login modules that will be used for authentication when
this domain is used, the structure of the login-module element is:
The code attribute is used to specify the implementing class of the login module which can either be the full
class name or one of the abbreviated names from the following list:
WildFly 9
Code
Classname
Client
org.jboss.security.ClientLoginModule
Certificate
org.jboss.security.auth.spi.BaseCertLoginModule
CertificateUsers
org.jboss.security.auth.spi.BaseCertLoginModule
CertificateRoles
org.jboss.security.auth.spi.CertRolesLoginModule
Database
org.jboss.security.auth.spi.DatabaseServerLoginModule
DatabaseCertificate org.jboss.security.auth.spi.DatabaseCertLoginModule
DatabaseUsers
org.jboss.security.auth.spi.DatabaseServerLoginModule
Identity
org.jboss.security.auth.spi.IdentityLoginModule
Ldap
org.jboss.security.auth.spi.LdapLoginModule
LdapExtended
org.jboss.security.auth.spi.LdapExtLoginModule
RoleMapping
org.jboss.security.auth.spi.RoleMappingLoginModule
RunAs
org.jboss.security.auth.spi.RunAsLoginModule
Simple
org.jboss.security.auth.spi.SimpleServerLoginModule
ConfiguredIdentity
org.picketbox.datasource.security.ConfiguredIdentityLoginModule
SecureIdentity
org.picketbox.datasource.security.SecureIdentityLoginModule
PropertiesUsers
org.jboss.security.auth.spi.PropertiesUsersLoginModule
SimpleUsers
org.jboss.security.auth.spi.SimpleUsersLoginModule
LdapUsers
org.jboss.security.auth.spi.LdapUsersLoginModule
Kerberos
com.sun.security.auth.module.Krb5LoginModule
SPNEGOUsers
org.jboss.security.negotiation.spnego.SPNEGOLoginModule
AdvancedLdap
org.jboss.security.negotiation.AdvancedLdapLoginModule
AdvancedADLdap
org.jboss.security.negotiation.AdvancedADLoginModule
UsersRoles
org.jboss.security.auth.spi.UsersRolesLoginModule
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The flag attribute is used to specify the JAAS flag for this module and should be one of required, requisite,
sufficient, or optional.
WildFly 9
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
See Authentication Modules for further details on the various modules listed above.
authentication-jaspi
The authentication-jaspi is used to configure a Java Authentication SPI (JASPI) provider as the
authentication mechanism. A security domain can have either a <authentication> or a <authentication-jaspi>
element, but not both. We set up JASPI by configuring one or more login modules inside the
login-module-stack element and setting up an authentication module. Here is the structure of the
authentication-jaspi element:
<login-module-stack name="...">
<login-module code="..." flag="..." module="...">
<module-option name="..." value="..."/>
</login-module>
</login-module-stack>
<auth-module code="..." login-module-stack-ref="...">
<module-option name="..." value="..."/>
</auth-module>
The login-module-stack-ref attribute value must be the name of the login-module-stack element to be used.
The sub-element login-module is configured just like in the authentication part
WildFly 9
authorization
Authorization in the AS container is normally done with RBAC (role based access control) but there are
situations where a more fine grained authorization policy is required. The authorization element allows
definition of different authorization modules to used, such that authorization can be checked with JACC
(Java Authorization Contract for Containers) or XACML (eXtensible Access Control Markup Language). The
structure of the authorization element is:
The code attribute is used to specify the implementing class of the policy module which can either be the full
class name or one of the abbreviated names from the following list:
Code
Classname
DenyAll
org.jboss.security.authorization.modules.AllDenyAuthorizationModule
PermitAll
org.jboss.security.authorization.modules.AllPermitAuthorizationModule
Delegating org.jboss.security.authorization.modules.DelegatingAuthorizationModule
Web
org.jboss.security.authorization.modules.WebAuthorizationModule
JACC
org.jboss.security.authorization.modules.JACCAuthorizationModule
XACML
org.jboss.security.authorization.modules.XACMLAuthorizationModule
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The flag attribute is used to specify the JAAS flag for this module and should be one of required, requisite,
sufficient, or optional.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
WildFly 9
mapping
The mapping element defines additional mapping of principals, credentials, roles and attributes for the
subject. The structure of the mapping element is:
The type attribute reflects the type of mapping of the provider and should be one of principal, credential, role
or attribute. By default "role" is the type used if the attribute is not set.
The code attribute is used to specify the implementing class of the login module which can either be the full
class name or one of the abbreviated names from the following list:
Code
Classname
PropertiesRoles
org.jboss.security.mapping.providers.role.PropertiesRolesMappingProvider
SimpleRoles
org.jboss.security.mapping.providers.role.SimpleRolesMappingProvider
DeploymentRoles org.jboss.security.mapping.providers.DeploymentRolesMappingProvider
DatabaseRoles
org.jboss.security.mapping.providers.role.DatabaseRolesMappingProvider
LdapRoles
org.jboss.security.mapping.providers.role.LdapRolesMappingProvider
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded. Specifying it is not necessary if one of the abbreviated names in the above
list is used.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
audit
The audit element can be used to define a custom audit provider. The default implementation used is
org.jboss.security.audit.providers.LogAuditProvider. The structure of the audit element is:
The code attribute is used to specify the implementing class of the provider module.
The module attribute specifies the name of the JBoss Modules module from which the class specified by the
code attribute should be loaded.
The module-option element can be repeated zero or more times to specify the module options as required
for the login module being configured. It requires the name and value attributes.
WildFly 9
jsse
The jsse element defines configuration for keystores and truststores that can be used for SSL context
configuration or for certificate storing/retrieving.
The set of attributes (all of them optional) of this element are:
WildFly 9
keystore-password
keystore-type
keystore-url
keystore-provider
Provider of the keystore. The default JDK provider for the keystore
type is used if this attribute is null
keystore-provider-argument
key-manager-factory-algorithm
key-manager-factory-provider
truststore-password
truststore-type
truststore-url
truststore-provider
Provider of the truststore. The default JDK provider for the truststore
type is used if this attribute is null
truststore-provider-argument
client-alias
Alias of the keystore to be used when creating client side SSL sockets
server-alias
Alias of the keystore to be used when creating server side SSL sockets
service-auth-token
client-auth
Flag to indicate if the server side SSL socket should require client
authentication. Default is "false"
cipher-suites
protocols
The optional additional-properties element can be used to include other options. The structure of the jsse
element is:
WildFly 9
security-properties
This element is used to specify additional properties as required by the security subsystem, properties are
specified in the following format:
<security-properties>
<property name="..." value="..."/>
</security-properties>
The property element can be repeated as required for as many properties need to be defined.
Each property specified is set on the java.security.Security class.
Authentication Modules
In this section we will describe each login module's options available.
Client
This login module is designed to establish caller identity and credentials when WildFly is acting a client. It
should never be used as part of a security domain used for actual server authentication.
Options
Usage
Description
multi-threaded
optional Set to true if each thread has its own principal and credential storage. Set
to false to indicate that all threads in the VM share the same identity and
credential. Default is false
restore-login-identity optional Set to true if the identity and credential seen at the start of the login()
method should be restored after the logout() method is invoked. Default is
false
password-stacking
optional Set to useFirstPass to indicate that this login module should look for
information stored in the LoginContext to use as the identity. This option
can be used when stacking other login modules with this one. Default is
false
WildFly 9
Database
This login module is designed to be used for authenticating users against a database backend.
Options
Usage
Description
dsJndiName
required JNDI name of the datasource containing the tables for users and roles
principalsQuery
rolesQuery
suspendResume optional A boolean flag that specifies that any existing JTA transaction be suspended
during DB operations. The default is true
Certificate
This login module is designed to authenticate users based on X509Certificates. A use case for this is
CLIENT-CERT authentication of a web application.
Options
Usage
Description
securityDomain optional Name of the security domain that has the jsse configuration for the truststore
holding the trusted certificates
verifier
If there is no verifier set, this login module will try to validate the user's certificate with a public certificate
stored in the truststore. The public certificate must be stored in the truststore using the DN of the certificate
as the truststore alias.
WildFly 9
CertificateRoles
This login module extends the Certificate login module to add role mapping capabilities from a properties file.
It has the same options plus these additional options:
Options
Usage
Description
rolesProperties
optional Name of the resource/file containing the roles to assign to each user.
Default is roles.properties
defaultRolesProperties optional Name of the resource/file to fall back to if the rolesProperties file can't
be found. Default is defaultRoles.properties
roleGroupSeperator
optional Character to use as the role group separator in the role properties file.
Default character is '.' (period)
The role properties file must be in the format username=role1,role2 where the username is the DN of the
certificate, escaping any equals and space characters. Here is an example:
This would assign the JBossAdmin role to an user that presents a certificate with CN=unit-tests-client,
OU=JBoss Inc., O=JBoss Inc., ST=Washington, C=US as the DN.
DatabaseCertificate
This login module extends the Certificate login to add role mapping capabilities from a database table. It has
the same options plus these additional options:
Options
Usage
Description
dsJndiName
required JNDI name of the datasource containing the tables for users
and roles
rolesQuery
suspendResume optional A boolean flag that specifies that any existing JTA transaction
be suspended during DB operations. The default is true
select Role,
RoleGroup
from Roles
where
PrincipalID=?
WildFly 9
<subsystem
<subsystem
<subsystem
<subsystem
xmlns="urn:jboss:domain:jaxrs:1.0"/>
xmlns="urn:jboss:domain:jdr:1.0"/>
xmlns="urn:jboss:domain:pojo:1.0"/>
xmlns="urn:jboss:domain:sar:1.0"/>
Description
Enables the gathering of diagnostic data for use in remote analysis of error conditions. Although
the data is in a simple format and could be useful to anyone, primarily useful for JBoss EAP
subscribers who would provide the data to Red Hat when requesting support
pojo
sar
Enables the deployment of .SAR archives containing MBean services, as supported by previous
versions of JBoss Application Server
WildFly 9
<subsystem xmlns="urn:jboss:domain:threads:1.0">
<thread-factory name="infinispan-factory" priority="1"/>
<bounded-queue-thread-pool name="infinispan-transport">
<core-threads count="1"/>
<queue-length count="100000"/>
<max-threads count="25"/>
<thread-factory name="infinispan-factory"/>
</bounded-queue-thread-pool>
<bounded-queue-thread-pool name="infinispan-listener">
<core-threads count="1"/>
<queue-length count="100000"/>
<max-threads count="1"/>
<thread-factory name="infinispan-factory"/>
</bounded-queue-thread-pool>
<scheduled-thread-pool name="infinispan-eviction">
<max-threads count="1"/>
<thread-factory name="infinispan-factory"/>
</scheduled-thread-pool>
<scheduled-thread-pool name="infinispan-repl-queue">
<max-threads count="1"/>
<thread-factory name="infinispan-factory"/>
</scheduled-thread-pool>
</subsystem>
Infinispan configuration:
WildFly 9
/profile=production/subsystem=threads/bounded-queue-thread-pool=pool1:write-core-threads
(count=0, per-cpu=20)
There are two main parts to the undertow subsystem, which are server and Servlet container configuration,
as well as some ancillary items. Advanced topics like load balancing and failover are covered on the "High
Availability Guide". The default configuration does is suitable for most use cases and provides reasonable
performance settings.
Required extension:
<subsystem xmlns="urn:jboss:domain:undertow:1.0">
<buffer-caches>
<buffer-cache name="default" buffer-size="1024" buffers-per-region="1024"
max-regions="10"/>
</buffer-caches>
<server name="default-server">
<http-listener name="default" socket-binding="http" />
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content" />
</host>
</server>
<servlet-container name="default" default-buffer-cache="default"
stack-trace-on-error="local-only" >
<jsp-config/>
<persistent-sessions/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"
directory-listing="true"/>
</handlers>
</subsystem>
WildFly 9
Dependencies on other subsystems:
IO Subsystem
<buffer-caches>
<buffer-cache name="default" buffer-size="1024" buffers-per-region="1024" max-regions="10"/>
</buffer-caches>
Attribute
Description
buffer-size
The size of the buffers. Smaller buffers allow space to be utilised more effectively
The maximum number of regions. This controls the maximum amount of memory that
can be used for caching
Server configuration
A server represents an instance of Undertow. Basically this consists of a set of connectors and some
configured handlers.
Attribute
Description
default-host
the virtual host that will be used if an incoming request as no Host: header
servlet-container the servlet container that will be used by this server, unless is is explicitly overriden by
the deployment
Connector configuration
Undertow provides HTTP, HTTPS and AJP connectors, which are configured per server.
WildFly 9
Common settings
The following settings are common to all connectors:
Attribute
Description
socket-binding
The socket binding to use. This determines the address and port the listener listens
on.
worker
buffer-pool
enabled
max-post-size
buffer-pipelined-data
max-header-size
The maximum size of a HTTP header block that is allowed. Responses with to
much data in their header block will have the request terminated and a bad request
response send.
max-parameters
The maximum number of query or path parameters that are allowed. This limit
exists to prevent hash collision based DOS attacks.
max-headers
The maximum number of headers that are allowed. This limit exists to prevent
hash collision based DOS attacks.
max-cookies
The maximum number of cookies that are allowed. This limit exists to prevent hash
collision based DOS attacks.
allow-encoded-slash
Set this to true if you want the server to decode percent encoded slash characters.
This is probably a bad idea, as it can have security implications, due to different
servers interpreting the slash differently. Only enable this if you have a legacy
application that requires it.
decode-url
If the URL should be decoded. If this is not set to true then percent encoded
characters in the URL will be left as is.
url-charset
always-set-keep-alive If the 'Connection: keep-alive' header should be added to all responses, even if not
required by spec.
WildFly 9
HTTP Connector
<http-listener name="default" socket-binding="http"
/>
Attribute
Description
certificate-forwarding
If this is set to true then the HTTP listener will read a client certificate from the
SSL_CLIENT_CERT header. This allows client cert authentication to be used,
even if the server does not have a direct SSL connection to the end user. This
should only be enabled for servers behind a proxy that has been configured to
always set these headers.
redirect-socket
HTTPS listener
Https listener provides secure access to the server. The most important configuration option is security realm
which defines SSL secure context.
Attribute
Description
security-realm
The security realm to use for the SSL configuration. See Security realm examples
for how to configure it: Examples
verify-client
AJP listener
<ajp-listener name="default" socket-binding="ajp" />
WildFly 9
Host configuration
The host element corresponds to a virtual host.
Attribute
Description
name
alias
default-web-module The name of a deployment that should be used to serve up requests that do not
match anything.
Description
The buffer cache that is used to cache static resources in the default
Servlet.
stack-trace-on-error
Can be either all, none, or local-only. When set to none Undertow will never
display stack traces. When set to All Undertow will always display them (not
recommended for production use). When set to local-only Undertow will
only display them for requests from local addresses, where there are no
headers to indicate that the request has been proxied. Note that this feature
means that the Undertow error page will be displayed instead of the default
error page specified in web.xml.
default-encoding
use-listener-encoding
If this is true then the default encoding will be the same as that used by the
listener that received the request.
JSP configuration
WildFly 9
domain
secure
max-age
Description
path
WildFly 9
AJP listeners
The AJP listeners are child resources of the subsystem undertow. They are used with mod_jk, mod_proxy
and mod_cluster of the Apache httpd front-end. Each listener does reference a particular socket binding:
[standalone@localhost:9999 /]
/subsystem=undertow/server=default-server:read-children-names(child-type=ajp-listener)
{
"outcome" => "success",
"result" => [
"ajp-listener",
]
}
[standalone@localhost:9999 /]
/subsystem=undertow/server=default-server/ajp-listener=*:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"enabled" => "true",
"scheme" => "http",
"socket-binding" => "ajp",
}
}
Creating a new ajp-listener requires you to declare a new socket binding first:
[standalone@localhost:9999 /]
/socket-binding-group=standard-sockets/socket-binding=ajp:add(port=8009)
The newly created, unused socket binding can then be used to create a new connector configuration:
[standalone@localhost:9999 /]
/subsystem=undertow/server=default-server/ajp-listener=myListener:add(socket-binding=ajp,
scheme=http, enabled=true)
WildFly 9
General Overview
Wildly uses Undertow's proxy capabilities to act as a load balancer. Undertow will connect to the back end
servers using its built in client, and proxies requests.
The following protocols are supported:
http
ajp
http2
h2c (clear text HTTP2)
Of these protocols h2c should give the best performance, if the back end servers support it.
The Undertow proxy uses async IO, the only threads that are involved in the request is the IO thread that is
responsible for the connection. The connection to the back end server is made from the same thread, which
removes the need for any thread safety constructs.
If both the front and back end servers support server push, and HTTP2 is in use then the proxy also
supports pushing responses to the client. In cases where proxy and backend are capable of server push, but
the client does not support it the server will send a X-Disable-Push header to let the backend know that it
should not attempt to push for this request.
/subsystem=undertow/configuration=handler/reverse-proxy=my-handler/host=ajp://sv1.foo.com:
/subsystem=undertow/configuration=handler/reverse-proxy=my-handler/host=ajp://sv2.foo.com:
Now we need to actually add the reverse proxy to a location. I am going to assume we are serving the path
/app:
/subsystem=undertow/server=default-server/host=default-host/location=\/app:add(handler=myThis is all there is to it. If you point your browser to http://localhost:8080/app you should be able to
see the proxied content.
The full details of all configuration options available can be found in the subsystem reference.
WildFly 9
Type
Description
modify-wsdl-address
boolean This boolean enables and disables the address rewrite functionality.
When modify-wsdl-address is set to true and the content of
<soap:address> is a valid URL, JBossWS will rewrite the URL using the
values of wsdl-host and wsdl-port or wsdl-secure-port.
When modify-wsdl-address is set to false and the content of
<soap:address> is a valid URL, JBossWS will not rewrite the URL. The
<soap:address> URL will be used.
When the content of <soap:address> is not a valid URL, JBossWS will
rewrite it no matter what the setting of modify-wsdl-address.
If modify-wsdl-address is set to true and wsdl-host is not defined or
explicitly set to 'jbossws.undefined.host' the content of
<soap:address> URL is use. JBossWS uses the requester's host when
rewriting the <soap:address>
When modify-wsdl-address is not defined JBossWS uses a default value
of true.
wsdl-host
string
WildFly 9
wsdl-port
int
Set this property to explicitly define the HTTP port that will be used for
rewriting the SOAP address.
Otherwise the HTTP port will be identified by querying the list of installed
HTTP connectors.
wsdl-secure-port
int
Set this property to explicitly define the HTTPS port that will be used for
rewriting the SOAP address.
Otherwise the HTTPS port will be identified by querying the list of
installed HTTPS connectors.
wsdl-uri-scheme
string
This property explicitly sets the URI scheme to use for rewriting
<soap:address> . Valid values are http and https. This
configuration overrides scheme computed by processing the endpoint
(even if a transport guarantee
is specified). The provided values for wsdl-port and
wsdl-secure-port (or their default values) are used depending on
specified scheme.
wsdl-path-rewrite-rule string
WildFly 9
[standalone@localhost:9999 /] /subsystem=webservices:read-resource
{
"outcome" => "success",
"result" => {
"endpoint" => {},
"modify-wsdl-address" => true,
"wsdl-host" => expression "${jboss.bind.address:127.0.0.1}",
"endpoint-config" => {
"Standard-Endpoint-Config" => undefined,
"Recording-Endpoint-Config" => undefined
}
}
}
Endpoint configs
Endpoint configs are defined using the endpoint-config element. Each endpoint configuration may
include properties and handlers set to the endpoints associated to the configuration.
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config:read-resource
{
"outcome" => "success",
"result" => {
"post-handler-chain" => undefined,
"property" => undefined,
"pre-handler-chain" => {"recording-handlers" => undefined}
}
}
[standalone@localhost:9999 /] /subsystem=webservices/endpoint-config=My-Endpoint-Config:add
{
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
WildFly 9
Handler chains
Each endpoint configuration may be associated with zero or more PRE and POST handler chains. Each
handler chain may include JAXWS handlers. For outbound messages the PRE handler chains are executed
before any handler that is attached to the endpoint using the standard means, such as with annotation
@HandlerChain, and POST handler chains are executed after those objects have executed. For inbound
messages the POST handler chains are executed before any handler that is attached to the endpoint using
the standard means and the PRE handler chains are executed after those objects have executed.
The protocol-binding attribute must be used to set the protocols for which the chain will be triggered.
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers:read-res
"outcome" => "success",
"result" => {
"protocol-bindings" => "##SOAP11_HTTP ##SOAP11_HTTP_MTOM ##SOAP12_HTTP
##SOAP12_HTTP_MTOM",
"handler" => {"RecordingHandler" => undefined}
},
"response-headers" => {"process-state" => "restart-required"}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers:add(protocol-bindings
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers:read-resource{
"outcome" => "success",
"result" => {
"handler" => undefined,
"protocol-bindings" => "##SOAP11_HTTP"
},
"response-headers" => {"process-state" => "restart-required"}
}
WildFly 9
Handlers
JAXWS handler can be added in handler chains:
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=Recording-Endpoint-Config/pre-handler-chain=recording-handlers/handler=
"outcome" => "success",
"result" => {"class" => "org.jboss.ws.common.invocation.RecordingServerHandler"},
"response-headers" => {"process-state" => "restart-required"}
}
[standalone@localhost:9999 /]
/subsystem=webservices/endpoint-config=My-Endpoint-Config/post-handler-chain=my-handlers/handler=foo-handler:a
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}
WildFly 9
Runtime information
Each web service endpoint is exposed through the deployment that provides the endpoint implementation.
Each endpoint can be queried as a deployment resource. For further information please consult the chapter
"Application Deployment". Each web service endpoint specifies a web context and a WSDL Url:
[standalone@localhost:9999 /] /deployment="*"/subsystem=webservices/endpoint="*":read-resource
{
"outcome" => "success",
"result" => [{
"address" => [
("deployment" => "jaxws-samples-handlerchain.war"),
("subsystem" => "webservices"),
("endpoint" => "jaxws-samples-handlerchain:TestService")
],
"outcome" => "success",
"result" => {
"class" => "org.jboss.test.ws.jaxws.samples.handlerchain.EndpointImpl",
"context" => "jaxws-samples-handlerchain",
"name" => "TestService",
"type" => "JAXWS_JSE",
"wsdl-url" => "http://localhost:8080/jaxws-samples-handlerchain?wsdl"
}
}]
}
Component Reference
The web service subsystem is provided by the JBossWS project. For a detailed description of the available
configuration properties, please consult the project documentation.
WildFly 9
5.22.1 Prerequisites
Before continuing, you should know how to download, install and run WildFly 9. For more information on
these steps, refer here: Getting Started Guide.
WildFly 9
6 Developer Guide
WildFly 8 Developer Guide
Target Audience
Prerequisites
Class loading in WildFly 8
Deployment Module Names
Automatic Dependencies
Class Loading Precedence
WAR Class Loading
EAR Class Loading
Class Path Entries
Global Modules
JBoss Deployment Structure File
Accessing JDK classes
Implicit module dependencies for deployments
What's an implicit module dependency?
How and when is an implicit module dependency added?
Which are the implicit module dependencies?
How do I migrate my application from JBoss AS 5 or AS 6 to WildFly 8?
EJB invocations from a remote standalone client using JNDI
Deploying your EJBs on the server side:
Writing a remote client application for accessing and invoking the EJBs deployed on the server
Setting up EJB client context properties
Using a different file for setting up EJB client context
Setting up the client classpath with the jars that are required to run the client application
Summary
WildFly 9
EJB invocations from a remote server
Application packaging
Beans
Security
Configuring a user on the "Destination Server"
Start the "Destination Server"
Deploying the application
Configuring the "Client Server" to point to the EJB remoting connector on the "Destination
Server"
Start the "Client Server"
Create a security realm on the client server
Create a outbound-socket-binding on the "Client Server"
Create a "remote-outbound-connection" which uses this newly created
"outbound-socket-binding"
Packaging the client application on the "Client Server"
Contents on jboss-ejb-client.xml
Deploy the client application
Client code invoking the bean
Remote EJB invocations via JNDI - Which approach to use?
JBoss EJB 3 reference guide
Resource Adapter for Message Driven Beans
Specification of Resource Adapter using Metadata Annotations
Run-as Principal
Specification of Run-as Principal using Metadata Annotations
Security Domain
Specification of Security Domain using Metadata Annotations
Transaction Timeout
Specification of Transaction Timeout with Metadata Annotations
Specification of Transaction Timeout in the Deployment Descriptor
Example of trans-timeout
Timer service
Single event timer
Recurring timer
Calendar timer
Programmatic calendar timer
Annotated calendar timer
WildFly 9
JPA reference guide
Introduction
Update your Persistence.xml for Hibernate 4.3.0
Entity manager
Application-managed entity manager
Container-managed entity manager
Persistence Context
Transaction-scoped Persistence Context
Extended Persistence Context
Extended Persistence Context Inheritance
Entities
Deployment
Troubleshooting
Background on the Jipijapa project
Packaging persistence providers with your application and which Jipijapa artifacts to include
Using the Hibernate 4.3.x JPA persistence provider
Using the Infinispan second level cache
Replacing the current Hibernate 4.3.x jars with a newer version
Packaging the Hibernate 4.x (or greater) JPA persistence provider with your application
Packaging the Hibernate 3.5 or greater 3.x JPA persistence provider with your application
Sharing the Hibernate 3.5 or greater JPA persistence provider between multiple applications
Using OpenJPA
Using EclipseLink
Using DataNucleus
Using Hibernate OGM
Native Hibernate use
Injection of Hibernate Session and SessionFactoryInjection of Hibernate Session and
SessionFactory
Hibernate properties
Persistence unit properties
Determine the persistence provider module
Binding EntityManagerFactory/EntityManager to JNDI
Community
People who have contributed to the WildFly JPA layer:
OSGi developer guide
WildFly 9
JNDI reference guide
Overview
Local JNDI
Binding entries to JNDI
Using a deployment descriptor
Programatically
Java EE Applications
WildFly Modules and Extensions
Naming Subsystem Configuration
Retrieving entries from JNDI
Resource Injection
Standard Java SE JNDI API
Remote JNDI
remote:
ejb:
Spring applications development and migration guide
Dependencies and Modularity
Persistence usage guide
Native Spring/Hibernate applications
JPA-based applications
Using server-deployed persistence units
Using Spring-managed persistence units
Placement of the persistence unit definitions
Managing dependencies
All WildFly 8 documentation
6.1.2 Prerequisites
WildFly 9
WildFly 9
By default this is set to false, which allows the sub-deployments to see classes belonging to other
sub-deployments within the .ear.
For example, consider the following .ear deployment:
myapp.ear
|
|--- web.war
|
|--- ejb1.jar
|
|--- ejb2.jar
If the ear-subdeployments-isolated is set to false, then the classes in web.war can access classes belonging
to ejb1.jar and ejb2.jar. Similarly, classes from ejb1.jar can access classes from ejb2.jar (and vice-versa).
The ear-subdeployments-isolated element value has no effect on the isolated classloader of the
.war file(s). i.e. irrespective of whether this flag is set to true or false, the .war within a .ear will have
a isolated classloader and other sub-deployments within that .ear will not be able to access classes
from that .war. This is as per spec.
If the ear-subdeployments-isolated is set to true then no automatic module dependencies between the
sub-deployments are set up. User must manually setup the dependency with Class-Path entries, or by
setting up explicit module dependencies.
WildFly 9
Portability
The Java EE specification says that portable applications should not rely on sub deployments
having access to other sub deployments unless an explicit Class-Path entry is set in the
MANIFEST.MF. So portable applications should always use Class-Path entry to explicitly state their
dependencies.
WildFly 9
To generate a MANIFEST.MF entry when using maven put the following in your pom.xml:
pom.xml
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>org.slf4j</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
If your deployment is a jar you must use the maven-jar-plugin rather than the
maven-war-plugin.
WildFly 9
WildFly 9
</exclude-subsystems>
<!-- Exclusions allow you to prevent the server from automatically adding some dependencies
-->
<exclusions>
<module name="org.javassist" />
</exclusions>
<!-- This allows you to define additional dependencies, it is the same as using the
Dependencies: manifest attribute -->
<dependencies>
<module name="deployment.javassist.proxy" />
<module name="deployment.myjavassist" />
<!-- Import META-INF/services for ServiceLoader impls as well -->
<module name="myservicemodule" services="import"/>
</dependencies>
<!-- These add additional classes to the module. In this case it is the same as including
the jar in the EAR's lib directory -->
<resources>
<resource-root path="my-library.jar" />
</resources>
</deployment>
<sub-deployment name="myapp.war">
<!-- This corresponds to the module for a web deployment -->
<!-- it can use all the same tags as the <deployment> entry above -->
<dependencies>
<!-- Adds a dependency on a ejb jar. This could also be done with a Class-Path entry -->
<module name="deployment.myear.ear.myejbjar.jar" />
</dependencies>
<!-- Set's local resources to have the lowest priority -->
<!-- If the same class is both in the sub deployment and in another sub deployment that -->
<!-- is visible to the war, then the Class from the other deployment will be loaded, -->
<!-- rather than the class actually packaged in the war. -->
<!-- This can be used to resolve ClassCastExceptions if the same class is in multiple sub
deployments-->
<local-last value="true" />
</sub-deployment>
<!-- Now we are going to define two additional modules -->
<!-- This one is a different version of javassist that we have packaged -->
<module name="deployment.myjavassist" >
<resources>
<resource-root path="javassist.jar" >
<!-- We want to use the servers version of javassist.util.proxy.* so we filter it out-->
<filter>
<exclude path="javassist/util/proxy" />
</filter>
</resource-root>
</resources>
</module>
<!-- This is a module that re-exports the containers version of javassist.util.proxy -->
<!-- This means that there is only one version of the Proxy classes defined
-->
<module name="deployment.javassist.proxy" >
<dependencies>
<module name="org.javassist" >
<imports>
<include path="javassist/util/proxy" />
<exclude path="/**" />
</imports>
</module>
</dependencies>
WildFly 9
</module>
</jboss-deployment-structure>
https://github.com/wildfly/wildfly/blob/master/build/src/main/resources/docs/schema/jboss-deployment-structure-1_2
WildFly 9
As can be seen, we have a simple @Stateless EJB. When the deployment containing this class is being
processed, the EJB deployment processor will see that the deployment contains a class with the @Stateless
annotation and thus identifies this as a EJB deployment. This is just one of the several ways, various
deployment processors can identify a deployment of some specific type. The EJB deployment
processor will then add an implicit dependency on the Java EE API module, so that all the Java EE API
classes are visible to the deployment.
Some subsystems will always add a API classes, even if the trigger condition is not met. These are
listed separately below.
In the next section, we'll list down the implicit module dependencies that are added to a deployment, by
various deployers within WildFly.
WildFly 9
responsible
added
condition is met
for adding
the implicit
dependency
Core Server
javax.api
sun.jdk
org.jboss.vfs
EE
Subsystem
javaee.api
EJB3
javaee.api
subsystem
JAX-RS
(Resteasy)
javax.xml.bind.api
org.jboss.resteasy.resteasy-atom-provider
org.jboss.resteasy.resteasy-cdi
subsystem
org.jboss.resteasy.resteasy-jaxrs
org.jboss.resteasy.resteasy-jaxb-provider
org.jboss.resteasy.resteasy-jackson-provider
org.jboss.resteasy.resteasy-jsapi
org.jboss.resteasy.resteasy-multipart-provider
org.jboss.resteasy.async-http-servlet-30
JCA
sub-system
javax.resource.api
javax.jms.api
javax.validation.api
org.jboss.logging
org.jboss.ironjacamar.api
org.jboss.ironjacamar.impl
org.hibernate.validator
WildFly 9
JPA
(Hibernate)
javax.persistence.api
javaee.api
org.jboss.as.jpa
subsystem
org.hibernate
Logging
Subsystem
org.jboss.logging
org.apache.commons.logging
org.apache.log4j
org.slf4j
org.jboss.logging.jul-to-slf4j-stub
SAR
org.jboss.logging
Subsystem
org.jboss.modules
Security
Subsystem
org.picketbox
Web
javaee.api
Subsystem
com.sun.jsf-impl
org.hibernate.validator
org.jboss.as.web
org.jboss.logging
Web
Services
org.jboss.ws.api
Subsystem
org.jboss.ws.spi
Weld (CDI)
Subsystem
javax.persistence.api
javaee.api
org.javassist
org.jboss.interceptor
org.jboss.as.weld
org.jboss.logging
org.jboss.weld.core
org.jboss.weld.api
org.jboss.weld.spi
WildFly 9
After you have read this article, do remember to take a look at Remote EJB invocations via JNDI EJB client API or remote-naming project
Before getting into the details, we would like the users to know that we have introduced a new EJB client
API, which is a WildFly-specific API and allows invocation on remote EJBs. This client API isn't based on
JNDI. So remote clients need not rely on JNDI API to invoke on EJBs. A separate document covering the
EJB remote client API will be made available. For now, you can refer to the javadocs of the EJB client
project at http://docs.jboss.org/ejbclient/. In this document, we'll just concentrate on the traditional JNDI
based invocation on EJBs. So let's get started:
As a first step, you'll have to deploy your application containing the EJBs on the AS7 server. If you want
those EJBs to be remotely invocable, then you'll have to expose atleast one remote view for that bean. In
this example, let's consider a simple Calculator stateless bean which exposes a RemoteCalculator remote
business interface. We'll also have a simple stateful CounterBean which exposes a RemoteCounter remote
business interface. Here's the code:
WildFly 9
package org.jboss.as.quickstarts.ejb.remote.stateless;
/**
* @author Jaikiran Pai
*/
public interface RemoteCalculator {
int add(int a, int b);
int subtract(int a, int b);
}
package org.jboss.as.quickstarts.ejb.remote.stateless;
import javax.ejb.Remote;
import javax.ejb.Stateless;
/**
* @author Jaikiran Pai
*/
@Stateless
@Remote(RemoteCalculator.class)
public class CalculatorBean implements RemoteCalculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int subtract(int a, int b) {
return a - b;
}
}
package org.jboss.as.quickstarts.ejb.remote.stateful;
/**
* @author Jaikiran Pai
*/
public interface RemoteCounter {
void increment();
void decrement();
int getCount();
}
WildFly 9
package org.jboss.as.quickstarts.ejb.remote.stateful;
import javax.ejb.Remote;
import javax.ejb.Stateful;
/**
* @author Jaikiran Pai
*/
@Stateful
@Remote(RemoteCounter.class)
public class CounterBean implements RemoteCounter {
private int count = 0;
@Override
public void increment() {
this.count++;
}
@Override
public void decrement() {
this.count--;
}
@Override
public int getCount() {
return this.count;
}
}
Let's package this in a jar (how you package it in a jar is out of scope of this chapter) named
"jboss-as-ejb-remote-app.jar" and deploy it to the server. Make sure that your deployment has been
processed successfully and there aren't any errors.
package org.jboss.as.quickstarts.ejb.remote.client;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
WildFly 9
import java.security.Security;
import java.util.Hashtable;
import
import
import
import
import
org.jboss.as.quickstarts.ejb.remote.stateful.CounterBean;
org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter;
org.jboss.as.quickstarts.ejb.remote.stateless.CalculatorBean;
org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator;
org.jboss.sasl.JBossSaslProvider;
/**
* A sample program which acts a remote client for a EJB deployed on AS7 server.
* This program shows how to lookup stateful and stateless beans via JNDI and then invoke on
them
*
* @author Jaikiran Pai
*/
public class RemoteEJBClient {
public static void main(String[] args) throws Exception {
// Invoke a stateless bean
invokeStatelessBean();
// Invoke a stateful bean
invokeStatefulBean();
}
/**
* Looks up a stateless bean and invokes on it
*
* @throws NamingException
*/
private static void invokeStatelessBean() throws NamingException {
// Let's lookup the remote stateless calculator
final RemoteCalculator statelessRemoteCalculator = lookupRemoteStatelessCalculator();
System.out.println("Obtained a remote stateless calculator for invocation");
// invoke on the remote calculator
int a = 204;
int b = 340;
System.out.println("Adding " + a + " and " + b + " via the remote stateless calculator
deployed on the server");
int sum = statelessRemoteCalculator.add(a, b);
System.out.println("Remote calculator returned sum = " + sum);
if (sum != a + b) {
throw new RuntimeException("Remote stateless calculator returned an incorrect sum "
+ sum + " ,expected sum was " + (a + b));
}
// try one more invocation, this time for subtraction
int num1 = 3434;
int num2 = 2332;
System.out.println("Subtracting " + num2 + " from " + num1 + " via the remote stateless
calculator deployed on the server");
int difference = statelessRemoteCalculator.subtract(num1, num2);
System.out.println("Remote calculator returned difference = " + difference);
if (difference != num1 - num2) {
throw new RuntimeException("Remote stateless calculator returned an incorrect
difference " + difference + " ,expected difference was " + (num1 - num2));
}
}
WildFly 9
/**
* Looks up a stateful bean and invokes on it
*
* @throws NamingException
*/
private static void invokeStatefulBean() throws NamingException {
// Let's lookup the remote stateful counter
final RemoteCounter statefulRemoteCounter = lookupRemoteStatefulCounter();
System.out.println("Obtained a remote stateful counter for invocation");
// invoke on the remote counter bean
final int NUM_TIMES = 20;
System.out.println("Counter will now be incremented " + NUM_TIMES + " times");
for (int i = 0; i < NUM_TIMES; i++) {
System.out.println("Incrementing counter");
statefulRemoteCounter.increment();
System.out.println("Count after increment is " + statefulRemoteCounter.getCount());
}
// now decrementing
System.out.println("Counter will now be decremented " + NUM_TIMES + " times");
for (int i = NUM_TIMES; i > 0; i--) {
System.out.println("Decrementing counter");
statefulRemoteCounter.decrement();
System.out.println("Count after decrement is " + statefulRemoteCounter.getCount());
}
}
/**
* Looks up and returns the proxy to remote stateless calculator bean
*
* @return
* @throws NamingException
*/
private static RemoteCalculator lookupRemoteStatelessCalculator() throws NamingException {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
// The app name is the application name of the deployed EJBs. This is typically the ear
name
// without the .ear suffix. However, the application name could be overridden in the
application.xml of the
// EJB deployment on the server.
// Since we haven't deployed the application as a .ear, the app name for us will be an
empty string
final String appName = "";
// This is the module name of the deployed EJBs on the server. This is typically the jar
name of the
// EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
// In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the
module name is
// jboss-as-ejb-remote-app
final String moduleName = "jboss-as-ejb-remote-app";
// AS7 allows each deployment to have an (optional) distinct name. We haven't specified
a distinct name for
// our EJB deployment, so this is an empty string
final String distinctName = "";
// The EJB name which by default is the simple class name of the bean implementation
class
WildFly 9
final String beanName = CalculatorBean.class.getSimpleName();
// the remote view fully qualified class name
final String viewClassName = RemoteCalculator.class.getName();
// let's do the lookup
return (RemoteCalculator) context.lookup("ejb:" + appName + "/" + moduleName + "/" +
distinctName + "/" + beanName + "!" + viewClassName);
}
/**
* Looks up and returns the proxy to remote stateful counter bean
*
* @return
* @throws NamingException
*/
private static RemoteCounter lookupRemoteStatefulCounter() throws NamingException {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
// The app name is the application name of the deployed EJBs. This is typically the ear
name
// without the .ear suffix. However, the application name could be overridden in the
application.xml of the
// EJB deployment on the server.
// Since we haven't deployed the application as a .ear, the app name for us will be an
empty string
final String appName = "";
// This is the module name of the deployed EJBs on the server. This is typically the jar
name of the
// EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
// In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the
module name is
// jboss-as-ejb-remote-app
final String moduleName = "jboss-as-ejb-remote-app";
// AS7 allows each deployment to have an (optional) distinct name. We haven't specified
a distinct name for
// our EJB deployment, so this is an empty string
final String distinctName = "";
// The EJB name which by default is the simple class name of the bean implementation
class
final String beanName = CounterBean.class.getSimpleName();
// the remote view fully qualified class name
final String viewClassName = RemoteCounter.class.getName();
// let's do the lookup (notice the ?stateful string as the last part of the jndi name
for stateful bean lookup)
return (RemoteCounter) context.lookup("ejb:" + appName + "/" + moduleName + "/" +
distinctName + "/" + beanName + "!" + viewClassName + "?stateful");
}
}
The entire server side and client side code is hosted at the github repo here ejb-remote
The code has some comments which will help you understand each of those lines. But we'll explain here in
more detail what the code does. As a first step in the client code, we'll do a lookup of the EJB using a JNDI
name. In AS7, for remote access to EJBs, you use the ejb: namespace with the following syntax:
WildFly 9
For stateless beans:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>?s
The ejb: namespace identifies it as a EJB lookup and is a constant (i.e. doesn't change) for doing EJB
lookups. The rest of the parts in the jndi name are as follows:
app-name : This is the name of the .ear (without the .ear suffix) that you have deployed on the server and
contains your EJBs.
Java EE 6 allows you to override the application name, to a name of your choice by setting it in the
application.xml. If the deployment uses uses such an override then the app-name used in the JNDI
name should match that name.
EJBs can also be deployed in a .war or a plain .jar (like we did in step 1). In such cases where the
deployment isn't an .ear file, then the app-name must be an empty string, while doing the lookup.
module-name : This is the name of the .jar (without the .jar suffix) that you have deployed on the server and
the contains your EJBs. If the EJBs are deployed in a .war then the module name is the .war name (without
the .war suffix).
Java EE 6 allows you to override the module name, by setting it in the ejb-jar.xml/web.xml of your
deployment. If the deployment uses such an override then the module-name used in the JNDI name
should match that name.
Module name part cannot be an empty string in the JNDI name
distinct-name : This is a WildFly-specific name which can be optionally assigned to the deployments that
are deployed on the server. More about the purpose and usage of this will be explained in a separate
chapter. If a deployment doesn't use distinct-name then, use an empty string in the JNDI name, for
distinct-name
bean-name : This is the name of the bean for which you are doing the lookup. The bean name is typically
the unqualified classname of the bean implementation class, but can be overriden through either ejb-jar.xml
or via annotations. The bean name part cannot be an empty string in the JNDI name.
fully-qualified-classname-of-the-remote-interface : This is the fully qualified class name of the interface
for which you are doing the lookup. The interface should be one of the remote interfaces exposed by the
bean on the server. The fully qualified class name part cannot be an empty string in the JNDI name.
For stateful beans, the JNDI name expects an additional "?stateful" to be appended after the fully qualified
interface name part. This is because for stateful beans, a new session gets created on JNDI lookup and the
EJB client API implementation doesn't contact the server during the JNDI lookup to know what kind of a
bean the JNDI name represents (we'll come to this in a while). So the JNDI name itself is expected to
indicate that the client is looking up a stateful bean, so that an appropriate session can be created.
WildFly 9
Now that we know the syntax, let's see our code and check what JNDI name it uses. Since our stateless
EJB named CalculatorBean is deployed in a jboss-as-ejb-remote-app.jar (without any ear) and since we are
looking up the org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator remote interface, our JNDI
name will be:
ejb:/jboss-as-ejb-remote-app//CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator
That's what the lookupRemoteStatelessCalculator() method in the above client code uses.
For the stateful EJB named CounterBean which is deployed in hte same jboss-as-ejb-remote-app.jar and
which exposes the org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter, the JNDI name will be:
ejb:/jboss-as-ejb-remote-app//CounterBean!org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter?stateful
That's what the lookupRemoteStatefulCounter() method in the above client code uses.
Now that we know of the JNDI name, let's take a look at the following piece of code in the
lookupRemoteStatelessCalculator():
Here we are creating a JNDI InitialContext object by passing it some JNDI properties. The
Context.URL_PKG_PREFIXES is set to org.jboss.ejb.client.naming. This is necessary because we should
let the JNDI API know what handles the ejb: namespace that we use in our JNDI names for lookup. The
"org.jboss.ejb.client.naming" has a URLContextFactory implementation which will be used by the JNDI APIs
to parse and return an object for ejb: namespace lookups. You can either pass these properties to the
constructor of the InitialContext class or have a jndi.properites file in the classpath of the client application,
which (atleast) contains the following property:
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
So at this point, we have setup the InitialContext and also have the JNDI name ready to do the lookup. You
can now do the lookup and the appropriate proxy which will be castable to the remote interface that you
used as the fully qualified class name in the JNDI name, will be returned. Some of you might be wondering,
how the JNDI implementation knew which server address to look, for your deployed EJBs. The answer is in
AS7, the proxies returned via JNDI name lookup for ejb: namespace do not connect to the server unless an
invocation on those proxies is done.
Now let's get to the point where we invoke on this returned proxy:
WildFly 9
We can see here that the proxy returned after the lookup is used to invoke the add(...) method of the bean.
It's at this point that the JNDI implementation (which is backed by the EJB client API) needs to know the
server details. So let's now get to the important part of setting up the EJB client context properties.
endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=10.20.30.40
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=appuser
remote.connection.default.password=apppassword
WildFly 9
This file includes a reference to a default password. Be sure to change this as soon as possible.
The above properties file is just an example. The actual file that was used for this sample program is
available here for reference jboss-ejb-client.properties
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
This is where you define the connections that you want to setup for communication with the remote
server. The "remote.connections" property uses a comma separated value of connection "names".
The connection names are just logical and are used grouping together the connection configuration
properties later on in the properties file. The example above sets up a single remote connection
named "default". There can be more than one connections that are configured. For example:
remote.connections=one, two
Here we are listing 2 connections named "one" and "two". Ultimately, each of the connections will
map to a EJB receiver. So if you have 2 connections, that will setup 2 EJB receivers that will be
added to the EJB client context. Each of these connections will be configured with the connection
specific properties as follows:
WildFly 9
remote.connection.default.host=10.20.30.40
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
As you can see we are using the "remote.connection.<connection-name>." prefix for specifying the
connection specific property. The connection name here is "default" and we are setting the "host"
property of that connection to point to 10.20.30.40. Similarly we set the "port" for that connection to
4447.
By default WildFly uses 8080 as the remoting port. The EJB client API uses the http port, with the
http-upgrade functionality, for communicating with the server for remote invocations, so that's the port we
use in our client programs (unless the server is configured for some other http port)
remote.connection.default.username=appuser
remote.connection.default.password=apppassword
The given user/password must be set by using the command bin/add-user.sh (or.bat).
The user and password must be set because the security-realm is enabled for the subsystem
remoting (see standalone*.xml or domain.xml) by default.
If you do not need the security for remoting you might remove the attribute security-realm in the
configuration.
WildFly 9
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=one, two
remote.connection.one.host=localhost
remote.connection.one.port=6999
remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.two.host=localhost
remote.connection.two.port=7999
remote.connection.two.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
As you can see we setup 2 connections "one" and "two" which both point to "localhost" as the
"host" but different ports. Each of these connections will internally be used to create the EJB
receivers in the EJB client context.
So that's how the jboss-ejb-client.properties file can be setup and placed in the classpath.
Setting up the client classpath with the jars that are required to
run the client application
A jboss-client jar is shipped in the distribution. It's available at
WILDFLY_HOME/bin/client/jboss-client.jar. Place this jar in the classpath of your client application.
If you are using Maven to build the client application, then please follow the instructions in the
WILDFLY_HOME/bin/client/README.txt to add this jar as a Maven dependency.
WildFly 9
6.5.4 Summary
In the above examples, we saw what it takes to invoke a EJB from a remote client. To summarize:
On the server side you need to deploy EJBs which expose the remote views.
On the client side you need a client program which:
Has a jboss-ejb-client.properties in its classpath to setup the server connection information
Either has a jndi.properties to specify the java.naming.factory.url.pkgs property or passes that
as a property to the InitialContext constructor
Setup the client classpath to include the jboss-client jar that's required for remote invocation of
the EJBs. The location of the jar is mentioned above. You'll also need to have your
application's bean interface jars and other jars that are required by your application, in the
client classpath
Note that this chapter deals with the case where the bean is deployed on the "Destination Server"
but not on the "Client Server".
myapp.ear
|
|---- myejb.jar
|
|
|
|---- <org.myapp.ejb.*> // EJB classes
Note that packaging itself isn't really important in the context of this article. You can deploy the
EJBs in any standard way (.ear, .war or .jar).
WildFly 9
6.6.2 Beans
In our example, we'll consider a simple stateless session bean which is as follows:
package org.myapp.ejb;
public interface Greeter {
String greet(String user);
}
package org.myapp.ejb;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless
@Remote (Greeter.class)
public class GreeterBean implements Greeter {
@Override
public String greet(String user) {
return "Hello " + user + ", have a pleasant day!";
}
}
6.6.3 Security
WildFly 8 is secure by default. What this means is that no communication can happen with an
WildFly instance from a remote client (irrespective of whether it is a standalone client or another server
instance) without passing the appropriate credentials. Remember that in this example, our "client server" will
be communicating with the "destination server". So in order to allow this communication to happen
successfully, we'll have to configure user credentials which we will be using during this communication. So
let's start with the necessary configurations for this.
WildFly 9
As you can see in the output above we have now configured a user on the destination server who'll be
allowed to access this server. We'll use this user credentials later on in the client server for communicating
with this server. The important bits to remember are the user we have created in this example is ejb and the
password is test.
Note that you can use any username and password combination you want to.
You do not require the server to be started to add a user using the add-user script.
WildFly 9
./standalone.sh -server-config=standalone-full.xml
It's very important to note that if you are starting both the server instances on the same machine,
then each of those server instances must have a unique jboss.node.name system property.
You can do that by passing an appropriate value for -Djboss.node.name system property to the
startup script:
WildFly 9
While generating the base64 encoded string make sure that you don't have any trailing or leading
spaces for the original password. That can lead to incorrect encoded versions being generated.
With new versions the add-user script will show the base64 password if you type 'y' if you've been
ask
Is this new user going to be used for one AS process to connect to another AS process
e.g. slave domain controller?
Now that we have generated that base64 encoded password, let's use in the in the security realm that we
are going to configure on the "client server". I'll first shutdown the client server and edit the
standlaone-full.xml file to add the following in the <management> section
Now let's create a "security-realm" for the base64 encoded password.
/core-service=management/security-realm=ejb-security-realm:add()
/core-service=management/security-realm=ejb-security-realm/server-identity=secret:add(value=dGVzdA==)
WildFly 9
Notice that the CLI show the message "process-state" => "reload-required", so you have to restart
the server before you can use this change.
upon successful invocation of this command, the following configuration will be created in the management
section:
standalone-full.xml
<management>
<security-realms>
...
<security-realm name="ejb-security-realm">
<server-identities>
<secret value="dGVzdA=="/>
</server-identities>
</security-realm>
</security-realms>
...
As you can see I have created a security realm named "ejb-security-realm" (you can name it anything) with
the base64 encoded password. So that completes the security realm configuration for the client server. Now
let's move on to the next step.
WildFly 9
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-ejb:add(host=localhos
port=8080)
The above command will create a outbound-socket-binding named "remote-ejb" (we can name it anything)
which points to "localhost" as the host and port 8080 as the destination port. Note that the host information
should match the host/IP of the "Destination Server" (in this example we are running on the same machine
so we use "localhost") and the port information should match the http-remoting connector port used by the
EJB subsystem (by default it's 8080). When this command is run successfully, we'll see that the
standalone-full.xml (the file which we used to start the server) was updated with the following
outbound-socket-binding in the socket-binding-group:
/subsystem=remoting/remote-outbound-connection=remote-ejb-connection:add(outbound-socket-binding-ref=remote-ej
protocol=http-remoting, security-realm=ejb-security-realm, username=ejb)
The above command creates a remote-outbound-connection, named "remote-ejb-connection" (we can name
it anything), in the remoting subsystem and uses the previously created "remote-ejb"
outbound-socket-binding (notice the outbound-socket-binding-ref in that command) with the http-remoting
protocol. Furthermore, we also set the security-realm attribute to point to the security-realm that we created
in the previous step. Also notice that we have set the username attribute to use the user name who is
allowed to communicate with the destination server.
WildFly 9
What this step does is, it creates a outbound connection, on the client server, to the remote destination
server and sets up the username to the user who allowed to communicate with that destination server and
also sets up the security-realm to a pre-configured security-realm capable of passing along the user
credentials (in this case the password). This way when a connection has to be established from the client
server to the destination server, the connection creation logic will have the necessary security credentials to
pass along and setup a successful secured connection.
Now let's run the following two operations to set some default connection creation options for the outbound
connection:
/subsystem=remoting/remote-outbound-connection=remote-ejb-connection/property=SASL_POLICY_NOANONYMOUS:add(valu
/subsystem=remoting/remote-outbound-connection=remote-ejb-connection/property=SSL_ENABLED:add(value=false)
Ultimately, upon successful invocation of this command, the following configuration will be created in the
remoting subsystem:
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
....
<outbound-connections>
<remote-outbound-connection name="remote-ejb-connection"
outbound-socket-binding-ref="remote-ejb" protocol="http-remoting"
security-realm="ejb-security-realm" username="ejb">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
</outbound-connections>
</subsystem>
From a server configuration point of view, that's all we need on the "Client Server". Our next step is to deploy
an application on the "Client Server" which will invoke on the bean deployed on the "Destination Server".
WildFly 9
client-app.ear
|
|--- META-INF
|
|
|
|--- jboss-ejb-client.xml
|
|--- web.war
|
|
|
|--- WEB-INF/classes
|
|
|
|
|
|---- <org.myapp.FooServlet> // classes in the web app
In the client application we'll use a servlet which invokes on the bean deployed on the "Destination Server".
We can even invoke the bean on the "Destination Server" from a EJB on the "Client Server". The code
remains the same (JNDI lookup, followed by invocation on the proxy). The important part to notice in this
client application is the file jboss-ejb-client.xml which is packaged in the META-INF folder of a top level
deployment (in this case our client-app.ear). This jboss-ejb-client.xml contains the EJB client configurations
which will be used during the EJB invocations for finding the appropriate destinations (also known as, EJB
receivers). The contents of the jboss-ejb-client.xml are explained next.
If your application is deployed as a top level .war deployment, then the jboss-ejb-client.xml is
expected to be placed in .war/WEB-INF/ folder (i.e. the same location where you place any
web.xml file).
WildFly 9
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0">
<client-context>
<ejb-receivers>
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection"/>
</ejb-receivers>
</client-context>
</jboss-ejb-client>
You'll notice that we have configured the EJB client context (for this application) to use a
remoting-ejb-receiver which points to our earlier created "remote-outbound-connection" named "
remote-ejb-connection". This links the EJB client context to use the "remote-ejb-connection" which ultimately
points to the EJB remoting connector on the "Destination Server".
WildFly 9
import javax.naming.Context;
import java.util.Hashtable;
import javax.naming.InitialContext;
...
public void invokeOnBean() {
try {
final Hashtable props = new Hashtable();
// setup the ejb: namespace URL factory
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
// create the InitialContext
final Context context = new javax.naming.InitialContext(props);
// Lookup the Greeter bean using the ejb: namespace syntax which is explained here
https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
final Greeter bean = (Greeter) context.lookup("ejb:" + "myapp" + "/" + "myejb" + "/"
+ "" + "/" + "GreeterBean" + "!" + org.myapp.ejb.Greeter.class.getName());
// invoke on the bean
final String greeting = bean.greet("Tom");
System.out.println("Received greeting: " + greeting);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
That's it! The above code will invoke on the bean deployed on the "Destination Server" and return the result.
WildFly 9
@MessageDriven(messageListenerInterface = PostmanPat.class)
@ResourceAdapter("ejb3-rar.rar")
6.8.2 as Principal
Whenever a run-as role is specified for a given method invocation the default anonymous principal is used
as the caller principal. This principal can be overridden by specifying a run-as principal.
@RunAs("admin")
@RunAsPrincipal("MyBean")
WildFly 9
@SecurityDomain("other")
New Transactions
Take care that even when transaction attribute REQUIRED is specified, the timeout will only be
applicable if a new transaction is started.
WildFly 9
Example of trans-timeout
jboss-ejb3.xml
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:tx="urn:trans-timeout"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd
urn:trans-timeout http://www.jboss.org/j2ee/schema/trans-timeout-1_0.xsd"
version="3.1"
impl-version="2.0">
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>BeanWithTimeoutValue</ejb-name>
<method-name>*</method-name>
<method-intf>Local</method-intf>
</method>
<tx:trans-timeout>
<tx:timeout>10</tx:timeout>
<tx:unit>Seconds</tx:unit>
</tx:trans-timeout>
</container-transaction>
</assembly-descriptor>
</jboss:ejb-jar>
WildFly 9
A persistent timer will be identified by the name of the EAR, the name of the sub-deployment JAR
and the Bean's name.
If one of those names are changed (e.g. EAR name contain a version) the timer entry became
orphaned and the timer event will not longer be fired.
Recurring timer
The timer will be started at the specified first occurrence and after that point at each time if the interval is
elapsed.
If the timer will be started during the last execution is not finished the execution will be suppressed with a
warning to avoid concurrent execution.
In case of server downtime for a persistent timer, the timeout method will be called only once if one, or more
than one, interval is elapsed.
If the timer is not persistent (since EJB3.1 see 18.2.3) it will not longer be active after the server is restarted
or the application is redeployed.
WildFly 9
Calendar timer
The timer will be started if the schedule expression match. It will be automatically deactivated and removed if
there will be no next expiration possible, i.e. If you set a specific year.
For example:
@Schedule( ... dayOfMonth="1", month="1", year="2012")
// start once at 01-01-2012 00:00:00
WildFly 9
WildFly 9
6.9.1 Introduction
The WildFly 8 JPA subsystem implements the JPA 2.0 container-managed requirements. Deploys the
persistence unit definitions, the persistence unit/context annotations and persistence unit/context references
in the deployment descriptor. JPA Applications use the Hibernate (core) 4.0 persistence provider, that is
included with WildFly. The JPA subsystem uses the standard SPI
(javax.persistence.spi.PersistenceProvider) to access the Hibernate persistence provider and some
additional extensions as well.
During application deployment, JPA use is detected (e.g. persistence.xml or @PersistenceContext/Unit
annotations) and injects Hibernate dependencies into the application deployment. This makes it easy to
deploy JPA applications.
In the remainder of this documentation, entity manager refers to an instance of the
javax.persistence.EntityManager class. Javadoc for the JPA interfaces
http://download.oracle.com/javaee/6/api/javax/persistence/package-summary.html and JPA 2.0 specification.
The index of Hibernate documentationis here.
WildFly 9
WildFly 9
WildFly 9
By default, the current stateful session bean being created, will ( deeply) inherit the extended persistence
context from any stateful session bean executing in the current Java thread. The deep inheritance of
extended persistence context includes walking multiple levels up the stateful bean call stack (inheriting from
parent beans). The deep inheritance of extended persistence context includes sibling beans. For example,
parentA references child beans beanBwithXPC & beanCwithXPC. Even though parentA doesn't have an
extended persistence context, beanBwithXPC & beanCwithXPC will share the same extended persistence
context.
Some other EE application servers, use shallow inheritance, where stateful session bean only inherit from
the parent stateful session bean (if there is a parent bean). Sibling beans do not share the same extended
persistence context unless their (common) parent bean also has the same extended persistence context.
Applications can include a (top-level) jboss-all.xml deployment descriptor that specifies either the (default)
DEEP extended persistence context inheritance or SHALLOW.
The AS/docs/schema/jboss-jpa_1_0.xsd describes the jboss-jpa deployment descriptor that may be
included in the jboss-all.xml. Below is an example of using SHALLOW extended persistence context
inheritance:
<jboss>
<jboss-jpa xmlns="http://www.jboss.com/xml/ns/javaee">
<extended-persistence inheritance="SHALLOW"/>
</jboss-jpa>
</jboss>
Below is an example of using DEEP extended persistence inheritance:
<jboss>
<jboss-jpa xmlns="http://www.jboss.com/xml/ns/javaee">
<extended-persistence inheritance="DEEP"/>
</jboss-jpa>
</jboss>
The AS console/cli can change the default extended persistence context setting (DEEP or SHALLOW). The
following cli commands will read the current JPA settings and enable SHALLOW extended persistence
context inheritance for applications that do not include the jboss-jpa deployment descriptor:
WildFly 9
./jboss-cli.sh
cd subsystem=jpa
:read-resource
:write-attribute(name=default-extended-persistence-inheritance,value="SHALLOW")
6.9.9 Entities
JPA 2.0 makes it easy to use your (pojo) plain old Java class to represent a database table row.
WildFly 9
6.9.10 Deployment
The persistence.xml contains the persistence unit configuration (e.g. datasource name) and as described in
the JPA 2.0 spec (section 8.2), the jar file or directory whose META-INF directory contains the
persistence.xml file is termed the root of the persistence unit. In Java EE environments, the root of a
persistence unit must be one of the following (quoted directly from the JPA 2.0 specification):
"
an EJB-JAR file
the WEB-INF/classes directory of a WAR file
a jar file in the WEB-INF/lib directory of a WAR file
a jar file in the EAR library directory
an application client jar file
The persistence.xml can specify either a JTA datasource or a non-JTA datasource. The JTA datasource is
expected to be used within the EE environment (even when reading data without an active transaction). If a
datasource is not specified, the default-datasource will instead be used (must be configured).
NOTE: Java Persistence 1.0 supported use of a jar file in the root of the EAR as the root of a persistence
unit. This use is no longer supported. Portable applications should use the EAR library directory for this case
instead.
"
Question: Can you have a EAR/META-INF/persistence.xml?
Answer: No, the above may deploy but it could include other archives also in the EAR, so you may have
deployment issues for other reasons. Better to put the persistence.xml in an EAR/lib/somePuJar.jar.
6.9.11 Troubleshooting
The org.jboss.as.jpa logging can be enabled to get the following information:
INFO - when persistence.xml has been parsed, starting of persistence unit service (per deployed
persistence.xml), stopping of persistence unit service
DEBUG - informs about entity managers being injected, creating/reusing transaction scoped entity
manager for active transaction
TRACE - shows how long each entity manager operation took in milliseconds, application searches
for a persistence unit, parsing of persistence.xml
To enable TRACE, open the as/standalone/configuration/standalone.xml (or
as/domain/configuration/domain.xml) file. Search for <subsystem
xmlns="urn:jboss:domain:logging:1.0"> and add the org.jboss.as.jpa category. You need to change
the console-handler level from INFO to TRACE.
WildFly 9
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE">
<level name="TRACE" />
...
</console-handler>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN" />
</logger>
<logger category="org.jboss.as.jpa">
<level name="TRACE" />
</logger>
<logger category="org.apache.tomcat.util.modeler">
<level name="WARN" />
</logger>
...
To see what is going on at the JDBC level, enable jboss.jdbc.spy TRACE and add spy="true" to the
datasource.
To troubleshoot issues with the Hibernate second level cache, try enabling trace for org.hibernate.SQL +
org.hibernate.cache.infinispan + org.infinispan:
WildFly 9
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE">
<level name="TRACE" />
...
</console-handler>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN" />
</logger>
<logger category="org.hibernate.SQL">
<level name="TRACE" />
</logger>
<logger category="org.hibernate">
<level name="TRACE" />
</logger>
<logger category="org.infinispan">
<level name="TRACE" />
</logger>
<logger category="org.apache.tomcat.util.modeler">
<level name="WARN" />
</logger>
...
WildFly 9
Artifact ID
Version
8.1.0.Final
8.1.0.Final
org.jipijapa jipijapa-hibernate3
1.1.0.Final
EclipseLink
8.1.0.Final
org.jipijapa jipijapa-eclipselink
1.1.0.Final
OpenJPA
8.1.0.Final
org.jipijapa jipijapa-openjpa
1.1.0.Final
WildFly 9
Here is an example of enabling the second level cache for a Hibernate native API hibernate.cfg.xml file:
<property name="hibernate.cache.region.factory_class"
value="org.jboss.as.jpa.hibernate4.infinispan.InfinispanRegionFactory"/>
<property name="hibernate.cache.infinispan.cachemanager"
value="java:jboss/infinispan/container/hibernate"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
Dependencies: org.infinispan,org.hibernate
Infinispan Hibernate/JPA second level cache provider documentation contains advanced configuration
information but you should bear in mind that when Hibernate runs within WildFly 8, some of those
configuration options, such as region factory, are not needed. Moreover, the application server providers you
with option of selecting a different cache container for Infinispan via hibernate.cache.infinispan.container
persistence property. To reiterate, this property is not mandatory and a default container is already deployed
for by the application server to host the second level cache.
WildFly 9
WildFly 9
The WildFly testsuite contains a test that packages jars from the Hibernate 3.6.5.Final jars in the ear lib.
WildFly 9
1. In a command shell, go to the AS installation and change into the modules/org folder.
cd WF\modules\modules\system\layers\base\org\hibernate\3
2. Copy the Hibernate3 jars into this folder
(hibernate3-core.jar, hibernate3-commons-annotations.jar, hibernate3-entitymanager.jar needed for
Hibernate 3.x).
3. Update the module.xml file to name each jar you copied in as a "resource-root":
-->
<dependencies>
<module name="asm.asm"/>
<module name="javax.api"/>
<module name="javax.annotation.api"/>
<module name="javax.enterprise.api"/>
<module name="javax.persistence.api"/>
<module name="javax.transaction.api"/>
<module name="javax.validation.api"/>
<module name="javax.xml.bind.api"/>
<module name="org.antlr"/>
<module name="org.apache.commons.collections"/>
<module name="org.dom4j"/>
<module name="org.javassist"/>
<module name="org.jboss.as.jpa.spi"/>
<module name="org.jboss.jandex"/>
<module name="org.jboss.logging"/>
<module name="org.slf4j"/>
<module name="org.jboss.vfs"/>
</dependencies>
</module>
1.
In your persistence.xml, you will refer to the Hibernate 3 persistence provider as follows:
WildFly 9
WildFly 9
jboss-cli.sh --connect
'/system-property=eclipselink.archive.factory:add(value=org.jipijapa.eclipselink.JBossArchiveFactoryImpl)'
. The following shows what the standalone.xml (or your WildFly configuration you are using) file might look
like after updating the system properties:
WildFly 9
<system-properties>
...
<property name="eclipselink.archive.factory"
value="org.jipijapa.eclipselink.JBossArchiveFactoryImpl"/>
</system-properties>
You should then be able to deploy applications with persistence.xml that include;
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
Also refer to page how to use EclipseLink with WildFly guide here.
WildFly 9
The AS7/modules/org/hibernate/ogm folder should contain the OGM jars and the following module.xml:
WildFly 9
Manifest-Version: 1.0
...
Dependencies: org.hibernate
If you use the Hibernate native api in your application and also use the JPA api to access the same entities
(from the same Hibernate session/EntityManager), you could get surprising results (e.g.
HibernateSession.saveOrUpdate(entity) is different than EntityManager.merge(entity). Each entity should be
managed by either Hibernate native API or JPA code.
import org.hibernate.Session;
import org.hibernate.SessionFactory;
@Stateful public class MyStatefulBean ... {
@PersistenceContext(unitName="crm") Session session1;
@PersistenceContext(unitName="crm2", type=EXTENDED) Session extendedpc;
@PersistenceUnit(unitName="crm") SessionFactory factory;
}
WildFly 9
Property
Purpose
hibernate.id.new_generator_mappings =true
hibernate.transaction.jta.platform= instance
of
org.hibernate.ejb.packaging.Scanner interface
hibernate.session_factory_name_is_jndi =
false
hibernate.session_factory_name.
hibernate.ejb.entitymanager_factory_name
WildFly 9
Purpose
jboss.as.jpa.providerModule
jboss.as.jpa.adapterModule
name of the integration classes that help WildFly to work with the
persistence provider. Current valid values are
org.jboss.as.jpa.hibernate:4 (Hibernate 4 integration classes) and
org.jboss.as.jpa.hibernate:3 (Hibernate 3 integration classes). Other
integration adapter modules are expected to be added.
jboss.as.jpa.adapterClass
jboss.as.jpa.managed
jboss.as.jpa.classtransformer
set to false to disable class transformers for the persistence unit. The
default is true, which allows class enhancing/rewriting. Hibernate also
needs persistence unit property hibernate.ejb.use_class_enhancer
to be true, for class enhancing to be enabled.
wildfly.jpa.default-unit
wildfly.jpa.twophasebootstrap
WildFly 9
wildfly.jpa.allowdefaultdatasourceuse set to false to prevent persistence unit from using the default data
source. Defaults to true. This is only important for persistence units
that do not specify a datasource.
jboss.as.jpa.deferdetach
Module name
blank
org.hibernate
org.hibernate.ejb.HibernatePersistence
org.hibernate
org.hibernate.ogm.jpa.HibernateOgmPersistence
org.hibernate:ogm
oracle.toplink.essentials.PersistenceProvider
oracle.toplink
oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
oracle.toplink
org.eclipse.persistence.jpa.PersistenceProvider
org.eclipse.persistence
org.datanucleus.api.jpa.PersistenceProviderImpl
org.datanucleus
org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider org.datanucleus:appengine
org.apache.openjpa.persistence.PersistenceProviderImpl
org.apache.openjpa
WildFly 9
As a reminder, a
@Stateful
public class ExampleSFSB {
public void createSomeEntityWithTransactionScopedEM(String name) {
Context context = new InitialContext();
javax.persistence.EntityManager entityManager = (javax.persistence.EntityManager)
context.lookup("java:/myEntityManager");
SomeEntity someEntity = new SomeEntity();
someEntity.setName(name);
entityManager.persist(name);
}
}
WildFly 9
6.9.30 Community
Many thanks to the community, for reporting issues, solutions and code changes. A number of people have
been answering Wildfly forum questions related to JPA usage. I would like to thank them for this, as well as
those reporting issues. For those of you that haven't downloaded the AS source code and started hacking
patches together. I would like to encourage you to start by reading Hacking on WildFly. You will find that it
easy very easy to find your way around the WildFly/JPA/* source tree and make changes. Also, new for
WildFly, is the JipiJapa project that contains additional integration code that makes EE JPA application
deployments work better. The following list of contributors should grow over time, I hope to see more of you
listed here.
WildFly 9
WildFly 9
java:jboss
java:/
Only entries within the java:jboss/exported context are accessible over remote JNDI.
For web deployments java:comp is aliased to java:module, so EJB's deployed in a war do not
have their own comp namespace.
<web-app 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-app_3_1.xsd"
version="3.1">
<env-entry>
<env-entry-name>java:global/mystring</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello World</env-entry-value>
</env-entry>
<env-entry>
<env-entry-name>hello</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello Module</env-entry-value>
</env-entry>
</web-app>
WildFly 9
Programatically
Java EE Applications
Standard Java EE applications may use the standard JNDI API, included with Java SE, to bind entries in the
global namespaces (the standard java:comp, java:module and java:app namespaces are read-only,
as mandated by the Java EE Platform Specification).
There is no need to unbind entries created programatically, since WildFly tracks which bindings
belong to a deployment, and the bindings are automatically removed when the deployment is
undeployed.
The ServiceTarget removes the bind when uninstalled, thus using one out of the module/extension
domain usage should be avoided, unless entries are removed using unbind().
WildFly 9
/subsystem=naming/binding=java\:global\/mybinding:add(binding-type=simple, type=long,
value=1000)
WildFly's Administrator Guide includes a section describing in detail the Naming subsystem
configuration.
WildFly 9
@Resource(lookup = "java:global/mystring")
private String myString;
@Resource(name = "hello")
private String hello;
@Resource
ManagedExecutorService executor;
Note that @Resource is more than a JNDI lookup, it also binds an entry in the component's JNDI
environment. The new bind JNDI name is defined by @Resource's name attribute, which value, if
unspecified, is the Java type concatenated with / and the field's name, for instance
java.lang.String/myString. More, similar to when using deployment descriptors to bind JNDI entries.
unless the name is an absolute JNDI name, it is considered relative to java:comp/env. For instance, with
respect to the field named myString above, the @Resource's lookup attribute instructs WildFly to lookup
the value in java:global/mystring, bind it in java:comp/env/java.lang.String/myString, and
then inject such value into the field.
With respect to the field named hello, there is no lookup attribute value defined, so the responsibility to
provide the entry's value is delegated to the deployment descriptor. Considering that the deployment
descriptor was the web.xml previously shown, which defines an environment entry with same hello name,
then WildFly inject the valued defined in the deployment descriptor into the field.
The executor field has no attributes specified, so the bind's name would default to
java:comp/env/javax.enterprise.concurrent.ManagedExecutorService/executor, but
there is no such entry in the deployment descriptor, and when that happens it's up to WildFly to provide a
default value or null, depending on the field's Java type. In this particular case WildFly would inject the
default instance of a managed executor service, the value in
java:comp/DefaultManagedExecutorService, as mandated by the EE Concurrency Utilities 1.0
Specification (JSR 236).
WildFly 9
or simply
remote:
The remote: protocol uses the WildFly remoting protocol to lookup items from the servers local JNDI. To
use it, you must have the appropriate jars on the class path, if you are maven user can be done simply by
adding the following to your pom.xml:
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>8.0.0.Final</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
If you are not using maven a shaded jar that contains all required classes
can be found in the bin/client directory of WildFly's distribution.
WildFly 9
ejb:
The ejb: namespace is provided by the jboss-ejb-client library. This protocol allows you to look up EJB's,
using their application name, module name, ejb name and interface type.
This is a client side JNDI implementation. Instead of looking up an EJB on the server the lookup name
contains enough information for the client side library to generate a proxy with the EJB information. When
you invoke a method on this proxy it will use the current EJB client context to perform the invocation. If the
current context does not have a connection to a server with the specified EJB deployed then an error will
occur. Using this protocol it is possible to look up EJB's that do not actually exist, and no error will be thrown
until the proxy is actually used. The exception to this is stateful session beans, which need to connect to a
server when they are created in order to create the session bean instance on the server.
Some examples are:
ejb:myapp/myejbjar/MyEjbName!com.test.MyRemoteInterface
ejb:myapp/myejbjar/MyStatefulName!comp.test.MyStatefulRemoteInterface?stateful
The first example is a lookup of a singleton, stateless or EJB 2.x home interface. This lookup will not hit the
server, instead a proxy will be generated for the remote interface specified in the name. The second
example is for a stateful session bean, in this case the JNDI lookup will hit the server, in order to tell the
server to create the SFSB session.
For more details on how the server connections are configured, please see EJB invocations from a remote
client using JNDI.
WildFly 9
WildFly 9
<persistence-context-ref>
<persistence-context-ref-name>persistence/petclinic-em</persistence-unit-ref-name>
<persistence-unit-name>petclinic</persistence-unit-name>
</persistence-context-ref>
or, respectively:
<persistence-unit-ref>
<persistence-unit-ref-name>persistence/petclinic-emf</persistence-unit-ref-name>
<persistence-unit-name>petclinic</persistence-unit-name>
</persistence-unit-ref>
When doing so, the persistence context or persistence unit are available to be looked up in JNDI, as follows:
or
JNDI binding
JNDI binding via persistence.xml properties is not supported in WildFly 8.
WildFly 9
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation"
value="classpath*:META-INF/jpa-persistence.xml"/>
<!-- other definitions -->
</bean>
Managing dependencies
Since the LocalContainerEntityManagerFactoryBean and the corresponding HibernateJpaVendorAdapter
are based on Hibernate 3, it is required to use that version with the application. Therefore, the Hibernate 3
jars must be included in the deployment. At the same time, due the presence of @PersistenceUnit or
@PersistenceContext annotations on the application classes, the application server will automatically add
the 'org.hibernate' module as a dependency.
This can be avoided by instructing the server to exclude the module from the deployment's list of
dependencies. In order to do so, include a META-INF/jboss-deployment-structure.xml or, for web
applications, WEB-INF/jboss-deployment-structure.xml with the following content:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="org.hibernate"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
WildFly 9
This article is not a tutorial on application client development, rather it covers the specifics of the
WildFly application client. There are tutorials available elsewhere that cover application client
basics, such as this one.
Note that the application client is different to the EJB client libraries, it is perfectly possible to write
client application that do not use the application client, but instead use the jboss-ejb-client library
directly.
The --host argument tells the appclient the server to connect to. The next argument is the application
client deployment to use, application clients can only run a single deployment, and this deployment must
also be deployed on the full server instance that the client is connecting too.
Any arguments after the deployment to use are passed directly through to the application clients main
function.
WildFly 9
6.14.3 Example
A simple example how to package an application client and use it with WildFly can be within the quickstart
appclient which is located on Github .
WildFly 9
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<dependencies>
<module name="deployment.d1.jar" meta-inf="import"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
Note that this can be used to create beans from both modules in the modules directory, and from other
deployments.
For more information on class loading and adding dependencies to your deployment please see the Class
Loading Guide
WildFly 9
deployment configuration
You can either set this up for your deployment only by adding the following content to the
META-INF/jboss-all.xml file of your application:
<jboss xmlns="urn:jboss:1.0">
<weld xmlns="urn:jboss:weld:1.0" require-bean-descriptor="true"/>
</jboss>
Global configuration
Alternatively, you may configure this for all deployments in your WildFly instance by executing the following
command:
/subsystem=weld:write-attribute(name=require-bean-descriptor,value=true)
WildFly 9
Fortunatelly, there is a non-portable mode available in WildFly which skips some of the API usage checks
and therefore allows the legacy extensions to work as before.
Again, there are two ways to enable the non-portable mode:
deployment configuration
You can either set this up for your deployment only by adding the following content to the
META-INF/jboss-all.xml file of your application:
<jboss xmlns="urn:jboss:1.0">
<weld xmlns="urn:jboss:weld:1.0" non-portable-mode="true" />
</jboss>
Global configuration
Alternatively, you may configure this for all deployments in your WildFly instance by executing the following
command:
/subsystem=weld:write-attribute(name=non-portable-mode,value=true)
Note that new portable extensions should always use the BeanManager API properly and thus never
required the non-portable mode. The non-portable mode only exists to preserve compatibility with
legacy extensions!
WildFly 9
WildFly 9
By default this is set to false, which allows the sub-deployments to see classes belonging to other
sub-deployments within the .ear.
For example, consider the following .ear deployment:
myapp.ear
|
|--- web.war
|
|--- ejb1.jar
|
|--- ejb2.jar
If the ear-subdeployments-isolated is set to false, then the classes in web.war can access classes belonging
to ejb1.jar and ejb2.jar. Similarly, classes from ejb1.jar can access classes from ejb2.jar (and vice-versa).
The ear-subdeployments-isolated element value has no effect on the isolated classloader of the
.war file(s). i.e. irrespective of whether this flag is set to true or false, the .war within a .ear will have
a isolated classloader and other sub-deployments within that .ear will not be able to access classes
from that .war. This is as per spec.
If the ear-subdeployments-isolated is set to true then no automatic module dependencies between the
sub-deployments are set up. User must manually setup the dependency with Class-Path entries, or by
setting up explicit module dependencies.
WildFly 9
Portability
The Java EE specification says that portable applications should not rely on sub deployments
having access to other sub deployments unless an explicit Class-Path entry is set in the
MANIFEST.MF. So portable applications should always use Class-Path entry to explicitly state their
dependencies.
WildFly 9
To generate a MANIFEST.MF entry when using maven put the following in your pom.xml:
pom.xml
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Dependencies>org.slf4j</Dependencies>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
If your deployment is a jar you must use the maven-jar-plugin rather than the
maven-war-plugin.
WildFly 9
WildFly 9
</exclude-subsystems>
<!-- Exclusions allow you to prevent the server from automatically adding some dependencies
-->
<exclusions>
<module name="org.javassist" />
</exclusions>
<!-- This allows you to define additional dependencies, it is the same as using the
Dependencies: manifest attribute -->
<dependencies>
<module name="deployment.javassist.proxy" />
<module name="deployment.myjavassist" />
<!-- Import META-INF/services for ServiceLoader impls as well -->
<module name="myservicemodule" services="import"/>
</dependencies>
<!-- These add additional classes to the module. In this case it is the same as including
the jar in the EAR's lib directory -->
<resources>
<resource-root path="my-library.jar" />
</resources>
</deployment>
<sub-deployment name="myapp.war">
<!-- This corresponds to the module for a web deployment -->
<!-- it can use all the same tags as the <deployment> entry above -->
<dependencies>
<!-- Adds a dependency on a ejb jar. This could also be done with a Class-Path entry -->
<module name="deployment.myear.ear.myejbjar.jar" />
</dependencies>
<!-- Set's local resources to have the lowest priority -->
<!-- If the same class is both in the sub deployment and in another sub deployment that -->
<!-- is visible to the war, then the Class from the other deployment will be loaded, -->
<!-- rather than the class actually packaged in the war. -->
<!-- This can be used to resolve ClassCastExceptions if the same class is in multiple sub
deployments-->
<local-last value="true" />
</sub-deployment>
<!-- Now we are going to define two additional modules -->
<!-- This one is a different version of javassist that we have packaged -->
<module name="deployment.myjavassist" >
<resources>
<resource-root path="javassist.jar" >
<!-- We want to use the servers version of javassist.util.proxy.* so we filter it out-->
<filter>
<exclude path="javassist/util/proxy" />
</filter>
</resource-root>
</resources>
</module>
<!-- This is a module that re-exports the containers version of javassist.util.proxy -->
<!-- This means that there is only one version of the Proxy classes defined
-->
<module name="deployment.javassist.proxy" >
<dependencies>
<module name="org.javassist" >
<imports>
<include path="javassist/util/proxy" />
<exclude path="/**" />
</imports>
</module>
</dependencies>
WildFly 9
</module>
</jboss-deployment-structure>
https://github.com/wildfly/wildfly/blob/master/build/src/main/resources/docs/schema/jboss-deployment-structure-1_2
Location
Specification Description
jboss-deployment-structure.xml META-INF or
Info
WEB-INF of the
used to control
top level
class loading
deployment
for the
WildFly
deployment
beans.xml
WEB-INF or
META-INF
CDI
The presence
Weld Reference
of this
Guide
descriptor
(even if empty)
activates CDI
WildFly 9
web.xml
WEB-INF
Servlet
Web
deployment
descriptor
jboss-web.xml
JBoss Web
WEB-INF
deployment
descriptor. This
can be use to
override
settings from
web.xml, and
to set
WildFly specific
options
ejb-jar.xml
WEB-INF of a
EJB
war, or
deployment
META-INF of an
descriptor
ejb-jar.xml schema
EJB jar
jboss-ejb3.xml
WEB-INF of a
war, or
deployment
META-INF of an
descriptor, this
EJB jar
can be used to
override
settings from
ejb-jar.xml,
and to set
WildFly specific
settings
application.xml
META-INF of an
Java EE
application.xml
EAR
Platform
schema
Specification
jboss-app.xml
META-INF of an
JBoss
EAR
application
deployment
descriptor, can
be used to
override
settings
application.xml,
and to set
WildFly specific
settings
WildFly 9
persistence.xml
META-INF
JPA
JPA descriptor
Hibernate Reference
used for
Guide
defining
persistence
units
jboss-ejb-client.xml
WEB-INF of a
Remote EJB
EJB invocations
war, or
settings. This
from a remote
META-INF of an
file is used to
server instance
EJB jar
jbosscmp-jdbc.xml
META-INF of an
CMP
EJB jar
deployment
descriptor.
Used to map
CMP entity
beans to a
database. The
format is
largely
unchanged
from previous
versions.
ra.xml
META-INF of a
Spec
IronJacamar
rar archive
deployment
Reference Guide
descriptor for
Schema
resource
adaptor
deployments
ironjacamar.xml
META-INF of a
JBoss
IronJacamar
rar archive
deployment
Reference Guide
descriptor for
resource
adaptor
deployments
WildFly 9
*-jms.xml
META-INF or
JMS message
WEB-INF
destination
deployment
descriptor,
used to deploy
message
destinations
with a
deployment
*-ds.xml
META-INF or
Datasource
DataSource
WEB-INF
deployment
Configuration
descriptor, use
to bundle
datasources
with a
deployment
application-client.xml
META-INF of an
Java EE6
The spec
application-client.xml
application client
Platform
deployment
schema
jar
Specification
descriptor for
application
client
deployments
jboss-client.xml
META-INF of an
The
application client
WildFly specific
jar
deployment
descriptor for
application
client
deployments
jboss-webservices.xml
META-INF for
The JBossWS
EJB webservice
4.0.x specific
deployments or
deployment
WEB-INF for
descriptor for
POJO
webservice
webservice
endpoints
deployments/EJB
webservice
endpoints
bundled in .war
WildFly 9
WildFly 9
WildFly default configurations creates a single default instance of a Context Service, which may be retrieved
through @Resource injection:
@Resource
private ContextService contextService;
To retrieve instead a non default Context Service instance, @Resource's lookup attribute needs
to specify the JNDI name used in the wanted instance configuration. WildFly will always inject the
default instance, no matter what's the name attribute value, if the lookup attribute is not defined.
As mandated by the Java EE specification, the default Context Service instance's JNDI name is
java:comp/DefaultContextService.
WildFly 9
Managed Thread Factory instances are managed by the application server, thus Java EE applications are
forbidden to invoke any lifecycle related method.
In case the Managed Thread Factory is configured to use a Context Service, the application's thread context
is captured when a thread creation is requested, and such context is propagated to the thread's Runnable
execution.
Managed Thread Factory threads implement javax.enterprise.concurrent.ManageableThread,
which allows an application to learn about termination status.
Usage example:
WildFly default configurations creates a single default instance of a Managed Thread Factory, which may be
retrieved through @Resource injection:
@Resource
private ManagedThreadFactory managedThreadFactory;
To retrieve instead a non default Managed Thread Factory instance, @Resource's lookup
attribute needs to specify the JNDI name used in the wanted instance configuration. WildFly will
always inject the default instance, no matter what's the name attribute value, in case the lookup
attribute is not defined.
ManagedThreadFactory managedThreadFactory =
InitialContext.doLookup("java:comp/DefaultManagedThreadFactory");
As mandated by the Java EE specification, the default Managed Thread Factory instance's JNDI
name is java:comp/DefaultManagedThreadFactory.
WildFly 9
WildFly default configurations creates a single default instance of a Managed Executor Service, which may
be retrieved through @Resource injection:
@Resource
private ManagedExecutorService managedExecutorService;
To retrieve instead a non default Managed Executor Service instance, @Resource's lookup
attribute needs to specify the JNDI name used in the wanted instance configuration. WildFly will
always inject the default instance, no matter what's the name attribute value, in case the lookup
attribute is not defined.
ManagedExecutorService managedExecutorService =
InitialContext.doLookup("java:comp/DefaultManagedExecutorService");
As mandated by the Java EE specification, the default Managed Executor Service instance's JNDI
name is java:comp/DefaultManagedExecutorService.
WildFly 9
WildFly default configurations creates a single default instance of a Managed Scheduled Executor Service,
which may be retrieved through @Resource injection:
@Resource
private ManagedScheduledExecutorService managedScheduledExecutorService;
To retrieve instead a non default Managed Scheduled Executor Service instance, @Resource's
lookup attribute needs to specify the JNDI name used in the wanted instance configuration.
WildFly will always inject the default instance, no matter what's the name attribute value, in case
the lookup attribute is not defined.
ManagedScheduledExecutorService managedScheduledExecutorService =
InitialContext.doLookup("java:comp/DefaultManagedScheduledExecutorService");
WildFly 9
As mandated by the Java EE specification, the default Managed Scheduled Executor Service
instance's JNDI name is java:comp/DefaultManagedScheduledExecutorService.
@MessageDriven(messageListenerInterface = PostmanPat.class)
@ResourceAdapter("ejb3-rar.rar")
WildFly 9
6.20.2 as Principal
Whenever a run-as role is specified for a given method invocation the default anonymous principal is used
as the caller principal. This principal can be overridden by specifying a run-as principal.
@RunAs("admin")
@RunAsPrincipal("MyBean")
@SecurityDomain("other")
WildFly 9
Although this is only applicable when using transaction attribute REQUIRED or REQUIRES_NEW the
application server will not detect invalid setups.
New Transactions
Take care that even when transaction attribute REQUIRED is specified, the timeout will only be
applicable if a new transaction is started.
WildFly 9
Example of trans-timeout
jboss-ejb3.xml
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:tx="urn:trans-timeout"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd
urn:trans-timeout http://www.jboss.org/j2ee/schema/trans-timeout-1_0.xsd"
version="3.1"
impl-version="2.0">
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>BeanWithTimeoutValue</ejb-name>
<method-name>*</method-name>
<method-intf>Local</method-intf>
</method>
<tx:trans-timeout>
<tx:timeout>10</tx:timeout>
<tx:unit>Seconds</tx:unit>
</tx:trans-timeout>
</container-transaction>
</assembly-descriptor>
</jboss:ejb-jar>
WildFly 9
A persistent timer will be identified by the name of the EAR, the name of the sub-deployment JAR
and the Bean's name.
If one of those names are changed (e.g. EAR name contain a version) the timer entry became
orphaned and the timer event will not longer be fired.
Recurring timer
The timer will be started at the specified first occurrence and after that point at each time if the interval is
elapsed.
If the timer will be started during the last execution is not finished the execution will be suppressed with a
warning to avoid concurrent execution.
In case of server downtime for a persistent timer, the timeout method will be called only once if one, or more
than one, interval is elapsed.
If the timer is not persistent (since EJB3.1 see 18.2.3) it will not longer be active after the server is restarted
or the application is redeployed.
WildFly 9
Calendar timer
The timer will be started if the schedule expression match. It will be automatically deactivated and removed if
there will be no next expiration possible, i.e. If you set a specific year.
For example:
@Schedule( ... dayOfMonth="1", month="1", year="2012")
// start once at 01-01-2012 00:00:00
WildFly 9
The invocation on the bean.doSomething() triggers the following (only relevant portion of the flow shown
below):
1. WildFly specific interceptor (a.k.a container interceptor) 1
2. WildFly specific interceptor (a.k.a container interceptor) 2
3. ....
4. WildFly specific interceptor (a.k.a container interceptor) N
5. User application specific Java EE interceptor(s) (if any)
6. Invocation on the EJB instance's method
The WildFly specific interceptors include the security context propagation, transaction management and
other container provided services. In some cases, the "container interceptors" (let's call them that)
might even decide break the invocation flow and not let the invocation proceed (for example: due to the
invoking caller not being among the allowed user roles who can invoke the method on the bean).
Previous versions of JBoss AS allowed a way to plug-in the user application specific interceptors (which
relied on JBoss AS specific libraries) into this invocation flow so that they do run some application specific
logic before the control reaches step#5 above. For example, AS5 allowed the use of JBoss AOP interceptors
to do this.
WildFly 8 doesn't have such a feature.
WildFly 9
Furthermore, configuring these container interceptors is similar to configuring the Java EE interceptors for
EJBs. In fact, it uses the same xsd elements that are allowed in ejb-jar.xml for 3.1 version of ejb-jar
deployment descriptor.
Container interceptors can only be configured via deployment descriptors. There's no annotation
based way to configure container interceptors. This was an intentional decision, taken to avoid
introducing any WildFly specific library dependency for the annotation.
Configuring the container interceptors can be done in jboss-ejb3.xml file, which then gets placed under the
META-INF folder of the EJB deployment, just like the ejb-jar.xml. Here's an example of how the container
interceptor(s) can be configured in jboss-ejb3.xml:
WildFly 9
jboss-ejb3.xml
<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns:ci ="urn:container-interceptors:1.0">
<jee:assembly-descriptor>
<ci:container-interceptors>
<!-- Default interceptor -->
<jee:interceptor-binding>
<ejb-name>*</ejb-name>
<interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ContainerInterceptorOne</intercepto
</jee:interceptor-binding>
<!-- Class level container-interceptor -->
<jee:interceptor-binding>
<ejb-name>AnotherFlowTrackingBean</ejb-name>
<interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ClassLevelContainerInterceptor</int
</jee:interceptor-binding>
<!-- Method specific container-interceptor -->
<jee:interceptor-binding>
<ejb-name>AnotherFlowTrackingBean</ejb-name>
<interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.MethodSpecificContainerInterceptor<
<method>
<method-name>echoWithMethodSpecificContainerInterceptor</method-name>
</method>
</jee:interceptor-binding>
<!-- container interceptors in a specific order -->
<jee:interceptor-binding>
<ejb-name>AnotherFlowTrackingBean</ejb-name>
<interceptor-order>
<interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ClassLevelContainerInterceptor</int
<interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.MethodSpecificContainerInterceptor<
<interceptor-class>org.jboss.as.test.integration.ejb.container.interceptor.ContainerInterceptorOne</intercepto
</interceptor-order>
<method>
<method-name>echoInSpecificOrderOfContainerInterceptors</method-name>
</method>
</jee:interceptor-binding>
</ci:container-interceptors>
</jee:assembly-descriptor>
</jboss>
WildFly 9
The interceptor classes themselves are simple POJOs and use the @javax.annotation.AroundInvoke
to mark the around invoke method which will get invoked during the invocation on the bean. Here's an
example of the interceptor:
Example of container interceptor
public class ClassLevelContainerInterceptor {
@AroundInvoke
private Object iAmAround(final InvocationContext invocationContext) throws Exception {
return this.getClass().getName() + " " + invocationContext.proceed();
}
}
Testcase
This testcase in the WildFly codebase can be used for reference for implementing container interceptors in
user applications
https://github.com/jbossas/jboss-as/blob/master/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/ejb/con
WildFly 9
Note that for this to work correctly the underlying database must support the READ_COMMITTED
or SERIALIZABLE isolation mode and the datasource must be configured accordingly
WildFly 9
Setup
In order to use clustered timers it is necessary to add a database backed timer store. This can be done from
the CLI with the following command:
/subsystem=ejb3/service=timer-service/database-data-store=my-clustered-store:add(allow-execution=true,
datasource-jndi-name='java:/MyDatasource', refresh-interval=60000, database='postgresql',
partition='mypartition')
WildFly 9
Another option is to use a separate data store for specific applications, all that is required is to set the timer
data store name in jboss-ejb3.xml:
Technical details
Internally every node that is allowed to execute timers schedules a timeout for every timer is knows about.
When this timeout expires then this node attempts to 'lock' the timer, by updating its state to running. The
query this executes looks like:
UPDATE JBOSS_EJB_TIMER SET TIMER_STATE=? WHERE ID=? AND TIMER_STATE<>? AND NEXT_DATE=?;
Due to the use of a transaction and READ_COMMITTED or SERIALIZABLE isolation mode only one node
will succeed in updating the row, and this is the node that the timer will run on.
WildFly 9
WildFly 9
<subsystem xmlns="urn:jboss:domain:ejb3:1.2">
<session-bean>
<stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless>
<stateful default-access-timeout="5000" cache-ref="simple" clustered-cache-ref="clustered"/>
<singleton default-access-timeout="5000"/>
</session-bean>
<mdb>
<resource-adapter-ref resource-adapter-name="hornetq-ra"/>
<bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>
</mdb>
<entity-bean>
<bean-instance-pool-ref pool-name="entity-strict-max-pool"/>
</entity-bean>
<pools>
<bean-instance-pools>
<strict-max-pool name="slsb-strict-max-pool" max-pool-size="20"
instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
<strict-max-pool name="mdb-strict-max-pool" max-pool-size="20"
instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
<strict-max-pool name="entity-strict-max-pool" max-pool-size="100"
instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
</bean-instance-pools>
</pools>
<caches>
<cache name="simple" aliases="NoPassivationCache"/>
<cache name="passivating" passivation-store-ref="file" aliases="SimpleStatefulCache"/>
<cache name="clustered" passivation-store-ref="infinispan" aliases="StatefulTreeCache"/>
</caches>
<passivation-stores>
<file-passivation-store name="file"/>
<cluster-passivation-store name="infinispan" cache-container="ejb"/>
</passivation-stores>
<async thread-pool-name="default"/>
<timer-service thread-pool-name="default">
<data-store path="timer-service-data" relative-to="jboss.server.data.dir"/>
</timer-service>
<remote connector-ref="remoting-connector" thread-pool-name="default"/>
<thread-pools>
<thread-pool name="default">
<max-threads count="10"/>
<keepalive-time time="100" unit="milliseconds"/>
</thread-pool>
</thread-pools>
<iiop enable-by-default="false" use-qualified-name="false"/>
<in-vm-remote-interface-invocation pass-by-value="false"/> <!-- Warning see notes below about
possible issues -->
</subsystem>
WildFly 9
<session-bean>
<stateless>
This element is used to configure the instance pool that is used by default for stateless session beans. If it is
not present stateless session beans are not pooled, but are instead created on demand for every invocation.
The instance pool can be overridden on a per deployment or per bean level using jboss-ejb3.xml or the
org.jboss.ejb3.annotation.Pool annotation. The instance pools themselves are configured in the
<pools> element.
<stateful>
This element is used to configure Stateful Session Beans.
default-access-timeout This attribute specifies the default time concurrent invocations on the
same bean instance will wait to acquire the instance lock. It can be overridden via the deployment
descriptor or via the javax.ejb.AccessTimeout annotation.
cache-ref This attribute is used to set the default cache for non-clustered beans. It can be
overridden by jboss-ejb3.xml, or via the org.jboss.ejb3.annotation.Cache annotation.
clustered-cache-ref This attribute is used to set the default cache for clustered beans.
<singleton>
This element is used to configure Singleton Session Beans.
default-access-timeout This attribute specifies the default time concurrent invocations will wait
to acquire the instance lock. It can be overridden via the deployment descriptor or via the
javax.ejb.AccessTimeout annotation.
<mdb>
<resource-adaptor-ref>
This element sets the default resource adaptor for Message Driven Beans.
<bean-instance-pool-ref>
This element is used to configure the instance pool that is used by default for Message Driven Beans. If it is
not present they are not pooled, but are instead created on demand for every invocation. The instance pool
can be overridden on a per deployment or per bean level using jboss-ejb3.xml or the
org.jboss.ejb3.annotation.Pool annotation. The instance pools themselves are configured in the
<pools> element.
WildFly 9
<entity-bean>
This element is used to configure the behavior for EJB2 EntityBeans.
<bean-instance-pool-ref>
This element is used to configure the instance pool that is used by default for Entity Beans. If it is not present
they are not pooled, but are instead created on demand for every invocation. The instance pool can be
overridden on a per deployment or per bean level using jboss-ejb3.xml or the
org.jboss.ejb3.annotation.Pool annotation. The instance pools themselves are configured in the
<pools> element.
<pools>
<caches>
<passivation-stores>
<async>
This element enables async EJB invocations. It is also used to specify the thread pool that these invocations
will use.
<timer-service>
This element enables the EJB timer service. It is also used to specify the thread pool that these invocations
will use.
<data-store>
This is used to configure the directory that persistent timer information is saved to.
<remote>
This is used to enable remote EJB invocations. It specifies the remoting connector to use (as defined in the
remoting subsystem configuration), and the thread pool to use for remote invocations.
<thread-pools>
This is used to configure the thread pools used by async, timer and remote invocations.
WildFly 9
<iiop>
This is used to enable IIOP (i.e. CORBA) invocation of EJB's. If this element is present then the JacORB
subsystem must also be installed. It supports the following two attributes:
enable-by-default If this is true then all EJB's with EJB2.x home interfaces are exposed via IIOP,
otherwise they must be explicitly enabled via jboss-ejb3.xml.
use-qualified-name If this is true then EJB's are bound to the corba naming context with a
binding name that contains the application and modules name of the deployment (e.g.
myear/myejbjar/MyBean), if this is false the default binding name is simply the bean name.
<in-vm-remote-interface-invocation>
By default remote interface invocations use pass by value, as required by the EJB spec. This element can
use used to enable pass by reference, which can give you a performance boost. Note WildFly will do a
shallow check to see if the caller and the EJB have access to the same class definitions, which means if you
are passing something such as a List<MyObject>, WildFly only checks the List to see if it is the same class
definition on the call & EJB side. If the top level class definition is the same, JBoss will make the call using
pass by reference, which means that if MyObject or any objects beneath it are loaded from different
classloaders, you would get a ClassCastException. If the top level class definitions are loaded from different
classloaders, JBoss will use pass by value. JBoss cannot do a deep check of all of the classes to ensure no
ClassCastExceptions will occur because doing a deep check would eliminate any performance boost you
would have received by using call by reference. It is recommended that you configure pass by reference
only on callers that you are sure will use the same class definitions and not globally. This can be done via a
configuration in the jboss-ejb-client.xml as shown below.
To configure a caller/client use pass by reference, you configure your top level deployment with a
META-INF/jboss-ejb-client.xml containing:
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0">
<client-context>
<ejb-receivers local-receiver-pass-by-value="false"/>
</client-context>
</jboss-ejb-client>
WildFly 9
Enabling JTS
To enable JTS simply add a <jts/> element to the transactions subsystem configuration.
It is also necessary to enable the JacORB transactions interceptor as shown below.
<subsystem xmlns="urn:jboss:domain:jacorb:1.1">
<orb>
<initializers transactions="on"/>
</orb>
</subsystem>
Dynamic Stub's
Downloading stubs directly from the server is no longer supported. If you do not wish to pre-generate your
stub classes JDK Dynamic stubs can be used instead. The enable JDK dynamic stubs simply set the
com.sun.CORBA.ORBUseDynamicStub system property to true.
Example File
A simple example is shown below:
WildFly 9
As you can see the format is largely similar to ejb-jar.xml, in fact they even use the same namespaces,
however jboss-ejb3.xml adds some additional namespaces of its own to allow for configuring non-spec
info. The format of the standard http://java.sun.com/xml/ns/javaee is well documented elsewhere,
this document will cover the non-standard namespaces.
WildFly 9
<s:security>
<ejb-name>*</ejb-name>
<s:security-domain>myDomain</s:security-domain>
<s:run-as-principal>myPrincipal</s:run-as-principal>
</s:security>
<r:resource-adapter-binding>
<ejb-name>*</ejb-name>
<r:resource-adapter-name>myResourceAdaptor</r:resource-adapter-name>
</r:resource-adapter-binding>
<p:pool>
<ejb-name>*</ejb-name>
<p:bean-instance-pool-ref>my-pool</p:bean-instance-pool-ref>
</p:pool>
<c:cache>
<ejb-name>*</ejb-name>
<c:cache-ref>my-cache</c:cache-ref>
</c:cache>
WildFly 9
Security Domain
The Java EE spec doesn't mandate a specific way to configure security domain for a bean. It leaves it to the
vendor implementations to allow such configurations, the way they wish. In WildFly 8, the use of
@org.jboss.ejb3.annotation.SecurityDomain annotation allows the developer to configure the
security domain for a bean. Here's an example:
import org.jboss.ejb3.annotation.SecurityDomain;
import javax.ejb.Stateless;
@Stateless
@SecurityDomain("other")
public class MyBean ...
{
....
The use of @SecurityDomain annotation lets the developer to point the container to the name of the security
domain which is configured in the EJB3 subsystem in the standalone/domain configuration. The
configuration of the security domain in the EJB3 subsystem is out of the scope of this chapter.
An alternate way of configuring a security domain, instead of using annotation, is to use jboss-ejb3.xml
deployment descriptor. Here's an example of how the configuration will look like:
WildFly 9
As you can see we use the security-domain element to configure the security domain.
WildFly 9
@Stateless
public class FooBean {
@RolesAllowed("bar")
public void doSomething() {
..
}
...
}
As you can see the doSomething method is configured to be accessible for users with role "bar". However,
the bean isn't configured for any specific security domain. Prior to WildFly 8, the absence of an explicitly
configured security domain on the bean would leave the bean unsecured, which meant that even if the
doSomething method was configured with @RolesAllowed("bar") anyone even without the "bar" role
could invoke on the bean.
In WildFly 8, the presence of any security metadata (like @RolesAllowed, @PermitAll, @DenyAll, @RunAs,
@RunAsPrincipal) on the bean or any business method of the bean, makes the bean secure, even in the
absence of an explicitly configured security domain. In such cases, the security domain name is default to
"other". Users can explicitly configure an security domain for the bean if they want to using either the
annotation or deployment descriptor approach explained earlier.
@Stateless
public class FooBean {
@RolesAllowed("bar")
public void doSomething() {
..
}
WildFly 9
As you can see the doSomething method is marked for access for only users with role "bar". That enables
security on the bean (with security domain defaulted to "other"). However, notice that the method
helloWorld doesn't have any specific security configurations.
In WildFly 8, such methods which have no explicit security configurations, in a secured bean, will be treated
similar to a method with @DenyAll configuration. What that means is, no one is allowed access to the
helloWorld method. This behaviour can be controlled via the jboss-ejb3.xml deployment descriptor at a
per bean level or a per deployment level as follows:
Notice the use of <missing-method-permissions-deny-access> element. The value for this element
can either be true or false. If this element isn't configured then it is equivalent to a value of true i.e. no one is
allowed access to methods, which have no explicit security configurations, on secured beans. Setting this to
false allows access to such methods for all users i.e. the behaviour will be switched to be similar to
@PermitAll.
This behaviour can also be configured at the EJB3 subsystem level so that it applies to all EJB3
deployments on the server, as follows:
<subsystem xmlns="urn:jboss:domain:ejb3:1.4">
...
<default-missing-method-permissions-deny-access value="true"/>
...
</subsystem>
WildFly 9
After you have read this article, do remember to take a look at Remote EJB invocations via JNDI EJB client API or remote-naming project
Before getting into the details, we would like the users to know that we have introduced a new EJB client
API, which is a WildFly-specific API and allows invocation on remote EJBs. This client API isn't based on
JNDI. So remote clients need not rely on JNDI API to invoke on EJBs. A separate document covering the
EJB remote client API will be made available. For now, you can refer to the javadocs of the EJB client
project at http://docs.jboss.org/ejbclient/. In this document, we'll just concentrate on the traditional JNDI
based invocation on EJBs. So let's get started:
As a first step, you'll have to deploy your application containing the EJBs on the AS7 server. If you want
those EJBs to be remotely invocable, then you'll have to expose atleast one remote view for that bean. In
this example, let's consider a simple Calculator stateless bean which exposes a RemoteCalculator remote
business interface. We'll also have a simple stateful CounterBean which exposes a RemoteCounter remote
business interface. Here's the code:
package org.jboss.as.quickstarts.ejb.remote.stateless;
/**
* @author Jaikiran Pai
*/
public interface RemoteCalculator {
int add(int a, int b);
int subtract(int a, int b);
}
WildFly 9
package org.jboss.as.quickstarts.ejb.remote.stateless;
import javax.ejb.Remote;
import javax.ejb.Stateless;
/**
* @author Jaikiran Pai
*/
@Stateless
@Remote(RemoteCalculator.class)
public class CalculatorBean implements RemoteCalculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int subtract(int a, int b) {
return a - b;
}
}
package org.jboss.as.quickstarts.ejb.remote.stateful;
/**
* @author Jaikiran Pai
*/
public interface RemoteCounter {
void increment();
void decrement();
int getCount();
}
WildFly 9
package org.jboss.as.quickstarts.ejb.remote.stateful;
import javax.ejb.Remote;
import javax.ejb.Stateful;
/**
* @author Jaikiran Pai
*/
@Stateful
@Remote(RemoteCounter.class)
public class CounterBean implements RemoteCounter {
private int count = 0;
@Override
public void increment() {
this.count++;
}
@Override
public void decrement() {
this.count--;
}
@Override
public int getCount() {
return this.count;
}
}
Let's package this in a jar (how you package it in a jar is out of scope of this chapter) named
"jboss-as-ejb-remote-app.jar" and deploy it to the server. Make sure that your deployment has been
processed successfully and there aren't any errors.
package org.jboss.as.quickstarts.ejb.remote.client;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
WildFly 9
import java.security.Security;
import java.util.Hashtable;
import org.jboss.as.quickstarts.ejb.remote.stateful.CounterBean;
import org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter;
import org.jboss.as.quickstarts.ejb.remote.stateless.CalculatorBean;
import org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator;
import org.jboss.sasl.JBossSaslProvider;
/**
* A sample program which acts a remote client for a EJB deployed on AS7 server.
* This program shows how to lookup stateful and stateless beans via JNDI and then invoke on
them
*
* @author Jaikiran Pai
*/
public class RemoteEJBClient {
public static void main(String[] args) throws Exception {
// Invoke a stateless bean
invokeStatelessBean();
// Invoke a stateful bean
invokeStatefulBean();
}
/**
* Looks up a stateless bean and invokes on it
*
* @throws NamingException
*/
private static void invokeStatelessBean() throws NamingException {
// Let's lookup the remote stateless calculator
final RemoteCalculator statelessRemoteCalculator = lookupRemoteStatelessCalculator();
System.out.println("Obtained a remote stateless calculator for invocation");
// invoke on the remote calculator
int a = 204;
int b = 340;
System.out.println("Adding " + a + " and " + b + " via the remote stateless calculator
deployed on the server");
int sum = statelessRemoteCalculator.add(a, b);
System.out.println("Remote calculator returned sum = " + sum);
if (sum != a + b) {
throw new RuntimeException("Remote stateless calculator returned an incorrect sum "
+ sum + " ,expected sum was " + (a + b));
}
// try one more invocation, this time for subtraction
int num1 = 3434;
int num2 = 2332;
System.out.println("Subtracting " + num2 + " from " + num1 + " via the remote stateless
calculator deployed on the server");
int difference = statelessRemoteCalculator.subtract(num1, num2);
System.out.println("Remote calculator returned difference = " + difference);
if (difference != num1 - num2) {
throw new RuntimeException("Remote stateless calculator returned an incorrect
difference " + difference + " ,expected difference was " + (num1 - num2));
}
}
WildFly 9
/**
* Looks up a stateful bean and invokes on it
*
* @throws NamingException
*/
private static void invokeStatefulBean() throws NamingException {
// Let's lookup the remote stateful counter
final RemoteCounter statefulRemoteCounter = lookupRemoteStatefulCounter();
System.out.println("Obtained a remote stateful counter for invocation");
// invoke on the remote counter bean
final int NUM_TIMES = 20;
System.out.println("Counter will now be incremented " + NUM_TIMES + " times");
for (int i = 0; i < NUM_TIMES; i++) {
System.out.println("Incrementing counter");
statefulRemoteCounter.increment();
System.out.println("Count after increment is " + statefulRemoteCounter.getCount());
}
// now decrementing
System.out.println("Counter will now be decremented " + NUM_TIMES + " times");
for (int i = NUM_TIMES; i > 0; i--) {
System.out.println("Decrementing counter");
statefulRemoteCounter.decrement();
System.out.println("Count after decrement is " + statefulRemoteCounter.getCount());
}
}
/**
* Looks up and returns the proxy to remote stateless calculator bean
*
* @return
* @throws NamingException
*/
private static RemoteCalculator lookupRemoteStatelessCalculator() throws NamingException {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
// The app name is the application name of the deployed EJBs. This is typically the ear
name
// without the .ear suffix. However, the application name could be overridden in the
application.xml of the
// EJB deployment on the server.
// Since we haven't deployed the application as a .ear, the app name for us will be an
empty string
final String appName = "";
// This is the module name of the deployed EJBs on the server. This is typically the jar
name of the
// EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
// In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the
module name is
// jboss-as-ejb-remote-app
final String moduleName = "jboss-as-ejb-remote-app";
// AS7 allows each deployment to have an (optional) distinct name. We haven't specified
a distinct name for
// our EJB deployment, so this is an empty string
final String distinctName = "";
// The EJB name which by default is the simple class name of the bean implementation
class
WildFly 9
final String beanName = CalculatorBean.class.getSimpleName();
// the remote view fully qualified class name
final String viewClassName = RemoteCalculator.class.getName();
// let's do the lookup
return (RemoteCalculator) context.lookup("ejb:" + appName + "/" + moduleName + "/" +
distinctName + "/" + beanName + "!" + viewClassName);
}
/**
* Looks up and returns the proxy to remote stateful counter bean
*
* @return
* @throws NamingException
*/
private static RemoteCounter lookupRemoteStatefulCounter() throws NamingException {
final Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
// The app name is the application name of the deployed EJBs. This is typically the ear
name
// without the .ear suffix. However, the application name could be overridden in the
application.xml of the
// EJB deployment on the server.
// Since we haven't deployed the application as a .ear, the app name for us will be an
empty string
final String appName = "";
// This is the module name of the deployed EJBs on the server. This is typically the jar
name of the
// EJB deployment, without the .jar suffix, but can be overridden via the ejb-jar.xml
// In this example, we have deployed the EJBs in a jboss-as-ejb-remote-app.jar, so the
module name is
// jboss-as-ejb-remote-app
final String moduleName = "jboss-as-ejb-remote-app";
// AS7 allows each deployment to have an (optional) distinct name. We haven't specified
a distinct name for
// our EJB deployment, so this is an empty string
final String distinctName = "";
// The EJB name which by default is the simple class name of the bean implementation
class
final String beanName = CounterBean.class.getSimpleName();
// the remote view fully qualified class name
final String viewClassName = RemoteCounter.class.getName();
// let's do the lookup (notice the ?stateful string as the last part of the jndi name
for stateful bean lookup)
return (RemoteCounter) context.lookup("ejb:" + appName + "/" + moduleName + "/" +
distinctName + "/" + beanName + "!" + viewClassName + "?stateful");
}
}
The entire server side and client side code is hosted at the github repo here ejb-remote
The code has some comments which will help you understand each of those lines. But we'll explain here in
more detail what the code does. As a first step in the client code, we'll do a lookup of the EJB using a JNDI
name. In AS7, for remote access to EJBs, you use the ejb: namespace with the following syntax:
WildFly 9
For stateless beans:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>?s
The ejb: namespace identifies it as a EJB lookup and is a constant (i.e. doesn't change) for doing EJB
lookups. The rest of the parts in the jndi name are as follows:
app-name : This is the name of the .ear (without the .ear suffix) that you have deployed on the server and
contains your EJBs.
Java EE 6 allows you to override the application name, to a name of your choice by setting it in the
application.xml. If the deployment uses uses such an override then the app-name used in the JNDI
name should match that name.
EJBs can also be deployed in a .war or a plain .jar (like we did in step 1). In such cases where the
deployment isn't an .ear file, then the app-name must be an empty string, while doing the lookup.
module-name : This is the name of the .jar (without the .jar suffix) that you have deployed on the server and
the contains your EJBs. If the EJBs are deployed in a .war then the module name is the .war name (without
the .war suffix).
Java EE 6 allows you to override the module name, by setting it in the ejb-jar.xml/web.xml of your
deployment. If the deployment uses such an override then the module-name used in the JNDI name
should match that name.
Module name part cannot be an empty string in the JNDI name
distinct-name : This is a WildFly-specific name which can be optionally assigned to the deployments that
are deployed on the server. More about the purpose and usage of this will be explained in a separate
chapter. If a deployment doesn't use distinct-name then, use an empty string in the JNDI name, for
distinct-name
bean-name : This is the name of the bean for which you are doing the lookup. The bean name is typically
the unqualified classname of the bean implementation class, but can be overriden through either ejb-jar.xml
or via annotations. The bean name part cannot be an empty string in the JNDI name.
fully-qualified-classname-of-the-remote-interface : This is the fully qualified class name of the interface
for which you are doing the lookup. The interface should be one of the remote interfaces exposed by the
bean on the server. The fully qualified class name part cannot be an empty string in the JNDI name.
For stateful beans, the JNDI name expects an additional "?stateful" to be appended after the fully qualified
interface name part. This is because for stateful beans, a new session gets created on JNDI lookup and the
EJB client API implementation doesn't contact the server during the JNDI lookup to know what kind of a
bean the JNDI name represents (we'll come to this in a while). So the JNDI name itself is expected to
indicate that the client is looking up a stateful bean, so that an appropriate session can be created.
WildFly 9
Now that we know the syntax, let's see our code and check what JNDI name it uses. Since our stateless
EJB named CalculatorBean is deployed in a jboss-as-ejb-remote-app.jar (without any ear) and since we are
looking up the org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator remote interface, our JNDI
name will be:
ejb:/jboss-as-ejb-remote-app//CalculatorBean!org.jboss.as.quickstarts.ejb.remote.stateless.RemoteCalculator
That's what the lookupRemoteStatelessCalculator() method in the above client code uses.
For the stateful EJB named CounterBean which is deployed in hte same jboss-as-ejb-remote-app.jar and
which exposes the org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter, the JNDI name will be:
ejb:/jboss-as-ejb-remote-app//CounterBean!org.jboss.as.quickstarts.ejb.remote.stateful.RemoteCounter?stateful
That's what the lookupRemoteStatefulCounter() method in the above client code uses.
Now that we know of the JNDI name, let's take a look at the following piece of code in the
lookupRemoteStatelessCalculator():
Here we are creating a JNDI InitialContext object by passing it some JNDI properties. The
Context.URL_PKG_PREFIXES is set to org.jboss.ejb.client.naming. This is necessary because we should
let the JNDI API know what handles the ejb: namespace that we use in our JNDI names for lookup. The
"org.jboss.ejb.client.naming" has a URLContextFactory implementation which will be used by the JNDI APIs
to parse and return an object for ejb: namespace lookups. You can either pass these properties to the
constructor of the InitialContext class or have a jndi.properites file in the classpath of the client application,
which (atleast) contains the following property:
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
So at this point, we have setup the InitialContext and also have the JNDI name ready to do the lookup. You
can now do the lookup and the appropriate proxy which will be castable to the remote interface that you
used as the fully qualified class name in the JNDI name, will be returned. Some of you might be wondering,
how the JNDI implementation knew which server address to look, for your deployed EJBs. The answer is in
AS7, the proxies returned via JNDI name lookup for ejb: namespace do not connect to the server unless an
invocation on those proxies is done.
Now let's get to the point where we invoke on this returned proxy:
WildFly 9
We can see here that the proxy returned after the lookup is used to invoke the add(...) method of the bean.
It's at this point that the JNDI implementation (which is backed by the EJB client API) needs to know the
server details. So let's now get to the important part of setting up the EJB client context properties.
endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=10.20.30.40
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.default.username=appuser
remote.connection.default.password=apppassword
WildFly 9
This file includes a reference to a default password. Be sure to change this as soon as possible.
The above properties file is just an example. The actual file that was used for this sample program is
available here for reference jboss-ejb-client.properties
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
This is where you define the connections that you want to setup for communication with the remote
server. The "remote.connections" property uses a comma separated value of connection "names".
The connection names are just logical and are used grouping together the connection configuration
properties later on in the properties file. The example above sets up a single remote connection
named "default". There can be more than one connections that are configured. For example:
remote.connections=one, two
Here we are listing 2 connections named "one" and "two". Ultimately, each of the connections will
map to a EJB receiver. So if you have 2 connections, that will setup 2 EJB receivers that will be
added to the EJB client context. Each of these connections will be configured with the connection
specific properties as follows:
WildFly 9
remote.connection.default.host=10.20.30.40
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
As you can see we are using the "remote.connection.<connection-name>." prefix for specifying the
connection specific property. The connection name here is "default" and we are setting the "host"
property of that connection to point to 10.20.30.40. Similarly we set the "port" for that connection to
4447.
By default WildFly uses 8080 as the remoting port. The EJB client API uses the http port, with the
http-upgrade functionality, for communicating with the server for remote invocations, so that's the port we
use in our client programs (unless the server is configured for some other http port)
remote.connection.default.username=appuser
remote.connection.default.password=apppassword
The given user/password must be set by using the command bin/add-user.sh (or.bat).
The user and password must be set because the security-realm is enabled for the subsystem
remoting (see standalone*.xml or domain.xml) by default.
If you do not need the security for remoting you might remove the attribute security-realm in the
configuration.
WildFly 9
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=one, two
remote.connection.one.host=localhost
remote.connection.one.port=6999
remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.two.host=localhost
remote.connection.two.port=7999
remote.connection.two.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
As you can see we setup 2 connections "one" and "two" which both point to "localhost" as the
"host" but different ports. Each of these connections will internally be used to create the EJB
receivers in the EJB client context.
So that's how the jboss-ejb-client.properties file can be setup and placed in the classpath.
Setting up the client classpath with the jars that are required to
run the client application
A jboss-client jar is shipped in the distribution. It's available at
WILDFLY_HOME/bin/client/jboss-client.jar. Place this jar in the classpath of your client application.
If you are using Maven to build the client application, then please follow the instructions in the
WILDFLY_HOME/bin/client/README.txt to add this jar as a Maven dependency.
WildFly 9
6.21.4 Summary
In the above examples, we saw what it takes to invoke a EJB from a remote client. To summarize:
On the server side you need to deploy EJBs which expose the remote views.
On the client side you need a client program which:
Has a jboss-ejb-client.properties in its classpath to setup the server connection information
Either has a jndi.properties to specify the java.naming.factory.url.pkgs property or passes that
as a property to the InitialContext constructor
Setup the client classpath to include the jboss-client jar that's required for remote invocation of
the EJBs. The location of the jar is mentioned above. You'll also need to have your
application's bean interface jars and other jars that are required by your application, in the
client classpath
Note that this chapter deals with the case where the bean is deployed on the "Destination Server"
but not on the "Client Server".
myapp.ear
|
|---- myejb.jar
|
|
|
Note that packaging itself isn't really important in the context of this article. You can deploy the
EJBs in any standard way (.ear, .war or .jar).
WildFly 9
6.22.2 Beans
In our example, we'll consider a simple stateless session bean which is as follows:
package org.myapp.ejb;
public interface Greeter {
String greet(String user);
}
package org.myapp.ejb;
import javax.ejb.Remote;
import javax.ejb.Stateless;
@Stateless
@Remote (Greeter.class)
public class GreeterBean implements Greeter {
@Override
public String greet(String user) {
return "Hello " + user + ", have a pleasant day!";
}
}
6.22.3 Security
WildFly 8 is secure by default. What this means is that no communication can happen with an
WildFly instance from a remote client (irrespective of whether it is a standalone client or another server
instance) without passing the appropriate credentials. Remember that in this example, our "client server" will
be communicating with the "destination server". So in order to allow this communication to happen
successfully, we'll have to configure user credentials which we will be using during this communication. So
let's start with the necessary configurations for this.
WildFly 9
As you can see in the output above we have now configured a user on the destination server who'll be
allowed to access this server. We'll use this user credentials later on in the client server for communicating
with this server. The important bits to remember are the user we have created in this example is ejb and the
password is test.
Note that you can use any username and password combination you want to.
You do not require the server to be started to add a user using the add-user script.
WildFly 9
./standalone.sh -server-config=standalone-full.xml
It's very important to note that if you are starting both the server instances on the same machine,
then each of those server instances must have a unique jboss.node.name system property.
You can do that by passing an appropriate value for -Djboss.node.name system property to the
startup script:
WildFly 9
While generating the base64 encoded string make sure that you don't have any trailing or leading
spaces for the original password. That can lead to incorrect encoded versions being generated.
With new versions the add-user script will show the base64 password if you type 'y' if you've been
ask
Is this new user going to be used for one AS process to connect to another AS process
e.g. slave domain controller?
Now that we have generated that base64 encoded password, let's use in the in the security realm that we
are going to configure on the "client server". I'll first shutdown the client server and edit the
standlaone-full.xml file to add the following in the <management> section
Now let's create a "security-realm" for the base64 encoded password.
/core-service=management/security-realm=ejb-security-realm:add()
/core-service=management/security-realm=ejb-security-realm/server-identity=secret:add(value=dGVzdA==)
WildFly 9
Notice that the CLI show the message "process-state" => "reload-required", so you have to restart
the server before you can use this change.
upon successful invocation of this command, the following configuration will be created in the management
section:
standalone-full.xml
<management>
<security-realms>
...
<security-realm name="ejb-security-realm">
<server-identities>
<secret value="dGVzdA=="/>
</server-identities>
</security-realm>
</security-realms>
...
As you can see I have created a security realm named "ejb-security-realm" (you can name it anything) with
the base64 encoded password. So that completes the security realm configuration for the client server. Now
let's move on to the next step.
WildFly 9
/socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-ejb:add(host=localhos
port=8080)
The above command will create a outbound-socket-binding named "remote-ejb" (we can name it anything)
which points to "localhost" as the host and port 8080 as the destination port. Note that the host information
should match the host/IP of the "Destination Server" (in this example we are running on the same machine
so we use "localhost") and the port information should match the http-remoting connector port used by the
EJB subsystem (by default it's 8080). When this command is run successfully, we'll see that the
standalone-full.xml (the file which we used to start the server) was updated with the following
outbound-socket-binding in the socket-binding-group:
/subsystem=remoting/remote-outbound-connection=remote-ejb-connection:add(outbound-socket-binding-ref=remote-ej
protocol=http-remoting, security-realm=ejb-security-realm, username=ejb)
The above command creates a remote-outbound-connection, named "remote-ejb-connection" (we can name
it anything), in the remoting subsystem and uses the previously created "remote-ejb"
outbound-socket-binding (notice the outbound-socket-binding-ref in that command) with the http-remoting
protocol. Furthermore, we also set the security-realm attribute to point to the security-realm that we created
in the previous step. Also notice that we have set the username attribute to use the user name who is
allowed to communicate with the destination server.
WildFly 9
What this step does is, it creates a outbound connection, on the client server, to the remote destination
server and sets up the username to the user who allowed to communicate with that destination server and
also sets up the security-realm to a pre-configured security-realm capable of passing along the user
credentials (in this case the password). This way when a connection has to be established from the client
server to the destination server, the connection creation logic will have the necessary security credentials to
pass along and setup a successful secured connection.
Now let's run the following two operations to set some default connection creation options for the outbound
connection:
/subsystem=remoting/remote-outbound-connection=remote-ejb-connection/property=SASL_POLICY_NOANONYMOUS:add(valu
/subsystem=remoting/remote-outbound-connection=remote-ejb-connection/property=SSL_ENABLED:add(value=false)
Ultimately, upon successful invocation of this command, the following configuration will be created in the
remoting subsystem:
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
....
<outbound-connections>
<remote-outbound-connection name="remote-ejb-connection"
outbound-socket-binding-ref="remote-ejb" protocol="http-remoting"
security-realm="ejb-security-realm" username="ejb">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
</outbound-connections>
</subsystem>
From a server configuration point of view, that's all we need on the "Client Server". Our next step is to deploy
an application on the "Client Server" which will invoke on the bean deployed on the "Destination Server".
WildFly 9
client-app.ear
|
|--- META-INF
|
|
|
|
|--- jboss-ejb-client.xml
|--- web.war
|
|
|
|
|--- WEB-INF/classes
|
|
In the client application we'll use a servlet which invokes on the bean deployed on the "Destination Server".
We can even invoke the bean on the "Destination Server" from a EJB on the "Client Server". The code
remains the same (JNDI lookup, followed by invocation on the proxy). The important part to notice in this
client application is the file jboss-ejb-client.xml which is packaged in the META-INF folder of a top level
deployment (in this case our client-app.ear). This jboss-ejb-client.xml contains the EJB client configurations
which will be used during the EJB invocations for finding the appropriate destinations (also known as, EJB
receivers). The contents of the jboss-ejb-client.xml are explained next.
If your application is deployed as a top level .war deployment, then the jboss-ejb-client.xml is
expected to be placed in .war/WEB-INF/ folder (i.e. the same location where you place any
web.xml file).
WildFly 9
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0">
<client-context>
<ejb-receivers>
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection"/>
</ejb-receivers>
</client-context>
</jboss-ejb-client>
You'll notice that we have configured the EJB client context (for this application) to use a
remoting-ejb-receiver which points to our earlier created "remote-outbound-connection" named "
remote-ejb-connection". This links the EJB client context to use the "remote-ejb-connection" which ultimately
points to the EJB remoting connector on the "Destination Server".
WildFly 9
import javax.naming.Context;
import java.util.Hashtable;
import javax.naming.InitialContext;
...
public void invokeOnBean() {
try {
final Hashtable props = new Hashtable();
// setup the ejb: namespace URL factory
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
// create the InitialContext
final Context context = new javax.naming.InitialContext(props);
// Lookup the Greeter bean using the ejb: namespace syntax which is explained here
https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI
final Greeter bean = (Greeter) context.lookup("ejb:" + "myapp" + "/" + "myejb" + "/"
+ "" + "/" + "GreeterBean" + "!" + org.myapp.ejb.Greeter.class.getName());
// invoke on the bean
final String greeting = bean.greet("Tom");
System.out.println("Received greeting: " + greeting);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
That's it! The above code will invoke on the bean deployed on the "Destination Server" and return the result.
WildFly 9
jBPM-Console application
Kris Verlaenen migrated this application from AS 5 to WildFly 8. For details about this migration, see jBPM5
on WildFly on his Kris's Blog.
WildFly 9
Summary of changes
Code Changes
Modify JNDI lookup code
Since this application was first written for EAP 4.2/4.3, which did not support EJB reference injection, the
servlets were using pre-EE 5 methods for looking up stateless and stateful session bean interfaces. While
migrating to WildFly, it seemed a good time to change the code to use the @EJB annotation, although this
was not a required change.
The real difference is in the lookup name. WildFly only supports the new EE 6 portable JNDI names rather
than the old EAR structure based names. The JNDI lookup code changed as follows:
Example of code in the EAP 5.1 version:
WildFly 9
try {
context = new InitialContext();
distributionCenterManager = (DistributionCenterManager)
context.lookup("OrderManagerApp/DistributionCenterManagerBean/local");
} catch(Exception lookupError) {
throw new ServletException("Couldn't find DistributionCenterManager bean", lookupError);
}
try {
customerManager = (CustomerManager)
context.lookup("OrderManagerApp/CustomerManagerBean/local");
} catch(Exception lookupError) {
throw new ServletException("Couldn't find CustomerManager bean", lookupError);
}
try {
productManager = (ProductManager)
context.lookup("OrderManagerApp/ProductManagerBean/local");
} catch(Exception lookupError) {
throw new ServletException("Couldn't find the ProductManager bean", lookupError);
}
@EJB(lookup="java:app/OrderManagerEJB/DistributionCenterManagerBean!services.ejb.DistributionCenterManager")pr
DistributionCenterManager distributionCenterManager;
@EJB(lookup="java:app/OrderManagerEJB/CustomerManagerBean!services.ejb.CustomerManager")
private CustomerManager customerManager;
@EJB(lookup="java:app/OrderManagerEJB/ProductManagerBean!services.ejb.ProductManager")
private ProductManager productManager;
In addition to the change to injection, which was supported in EAP 5.1.0, the lookup name changed from:
OrderManagerApp/DistributionCenterManagerBean/local
to:
java:app/OrderManagerEJB/DistributionCenterManagerBean!services.ejb.DistributionCenterManager
All the other beans were changed in a similar manner. They are now based on the portable JNDI names
described in EE 6.
WildFly 9
if(log.isTraceEnabled()) {
log.trace("Just flushed " + batchSize + " rows to the database.");
log.trace("Total rows flushed is " + (i+1));
}
if(logger.isLoggable(Level.TRACE)) {
logger.log(Level.TRACE, "Just flushed " + batchSize + " rows to the database.");
logger.log(Level.TRACE, "Total rows flushed is " + (i+1));
}
In addition to the code changes made to use the new AS7 JBoss log manager module, you must add this
dependency to the MANIFEST.MF file as follows:
Manifest-Version: 1.0
Dependencies: org.jboss.logmanager
WildFly 9
<properties>
<property name="hibernate.cache.region.factory_class"
value="org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory"/>
<property name="hibernate.cache.region.jbc2.cachefactory" value="java:CacheManager"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
<property name="hibernate.cache.use_minimal_puts" value="true"/>
<property name="hibernate.cache.region.jbc2.cfg.entity" value="mvcc-entity"/>
<property name="hibernate.cache.region_prefix" value="services"/>
</properties>
This is how it was modified to use Infinispan for the same configuration:
<properties>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_minimal_puts" value="true"/>
</properties>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
Most of the properties are removed since they will default to the correct values for the second level cache.
See "Using the Infinispan second level cache" for more details.
That was the extent of the code changes required to migrate the application to AS7.
WildFly 9
$ jar tf OrderManagerApp.ear
META-INF/MANIFEST.MF
META-INF/application.xml
OrderManagerWeb.war
OrderManagerEntities.jar
OrderManagerEJB.jar
META-INF/
In this structure, the entities and the persistence.xml were in one jar file,
OrderManagerEntities.jar, and the stateless and stateful session beans were in another jar file,
OrderManagerEJB.jar. This did not work due to modular class loading changes in WildFly. There are a
couple of ways to resolve this issue:
1. Modify the class path in the MANIFEST.MF
2. Flatten the code and put all the beans in one JAR file.
The second approach was selected because it simplified the EAR structure:
$ jar tf OrderManagerApp.ear
META-INF/application.xml
OrderManagerWeb.war
OrderManagerEJB.jar
META-INF/
Since there is no longer an OrderManagerEntities.jar file, the applcation.xml file was modified to
remove the entry.
An entry was added to the MANIFEST.MF file in the OrderManagerWeb.war to resolve another class
loading issue resulting from the modification to use EJB reference injection in the servlets.
Manifest-Version: 1.0
Dependencies: org.jboss.logmanager
Class-Path: OrderManagerEJB.jar
The Class-Path entry tells the application to look in the OrderManagerEJB.jar file for the injected
beans.
WildFly 9
Summary
Although the existing EAR structure could have worked with additional modifications to the MANIFEST.MF
file, this approach seemed more appealing because it simplified the structure while maintaining the web tier
in its own WAR.
The source files for both versions is attached so you can view the changes that were made to the
application.
WildFly 9
Step 1: Build and deploy the EAP5.1 version of the Seam Booking
application
1. Build the EAR
cd /EAP5_HOME/jboss-eap5.1/seam/examples/booking
~/tools/apache-ant-1.8.2/bin/ant explode
cp -r
EAP5_HOME/jboss-eap-5.1/seam/examples/booking/exploded-archives/jboss-seam-booking.ear
AS7_HOME/standalone/deployments/
cp -r
EAP5_HOME/jboss-eap-5.1/seam/examples/booking/exploded-archives/jboss-seam-booking.war
AS7_HOME/standalone/deployments/jboss-seam.ear
cp -r
EAP5_HOME/jboss-eap-5.1/seam/examples/booking/exploded-archives/jboss-seam-booking.jar
AS7_HOME/standalone/deployments/jboss-seam.ear
3. Start the WildFly server and check the log. You will see:
4. Create an empty file with the name jboss-seam-booking.ear.dodeploy and copy it into the
deployments directory. In the log, you will now see the following, indicating that it is deploying:
At this point, you will first encounter your first deployment error. In the next section, we will step through each
issue and how to debug and resolve it.
WildFly 9
ERROR \[org.jboss.msc.service.fail\] (MSC service thread 1-1) MSC00001: Failed to start service
jboss.deployment.subunit."jboss-seam-booking.ear"."jboss-seam-booking.war".POST_MODULE:
org.jboss.msc.service.StartException in service
jboss.deployment.subunit."jboss-seam-booking.ear"."jboss-seam-booking.war".POST_MODULE:
Failed to process phase POST_MODULE of subdeployment "jboss-seam-booking.war" of deployment
"jboss-seam-booking.ear"
(.. additional logs removed ...)
Caused by: java.lang.ClassNotFoundException: javax.faces.FacesException from \[Module
"deployment.jboss-seam-booking.ear:main" from Service Module Loader\]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:191)
What it means:
The ClassNotFoundException indicates a missing dependency. In this case, it can not find the class
javax.faces.FacesException and you need to explicitly add the dependency.
WildFly 9
javax/faces/api/main
javax/faces/api/1.2
Both modules have the same module name: javax.faces.api but one in the main directory is for JSF 2.0
and the one located in the 1.2 directory is for JSF 1.2. If there was only one module available, we could
simply create a MANIFEST.MF file and added the module dependency. But in this case, we want to use the
JSF 1.2 version and not the 2.0 version in main, so we need to be able to specify one and exclude the other.
To do this, we create a jboss-deployment-structure.xml file in the EAR META-INF/ directory that
contains the following data:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
</dependencies>
</deployment>
<sub-deployment name="jboss-seam-booking.war">
<exclusions>
<module name="javax.faces.api" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2"/>
</dependencies>
</sub-deployment>
</jboss-deployment-structure>
In the "deployment" section, we add the dependency for the javax.faces.api for the JSF 1.2 module.
We also add the dependency for the JSF 1.2 module in the sub-deployment section for the WAR and
exclude the module for JSF 2.0.
Redeploy the application by deleting the
standalone/deployments/jboss-seam-booking.ear.failed file and creating a blank
jboss-seam-booking.ear.dodeploy file in the same directory.
WildFly 9
ERROR [org.jboss.msc.service.fail] (MSC service thread 1-8) MSC00001: Failed to start service
jboss.deployment.unit."jboss-seam-booking.ear".INSTALL:
org.jboss.msc.service.StartException in service
jboss.deployment.unit."jboss-seam-booking.ear".INSTALL:
Failed to process phase INSTALL of deployment "jboss-seam-booking.ear"
(.. additional logs removed ...)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.Log from [Module
"deployment.jboss-seam-booking.ear.jboss-seam-booking.war:main" from Service Module Loader]
What it means:
The ClassNotFoundException indicates a missing dependency. In this case, it can not find the class
org.apache.commons.logging.Log and you need to explicitly add the dependency.
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
<module name="org.apache.commons.logging" export="true"/>
</dependencies>
</deployment>
<sub-deployment name="jboss-seam-booking.war">
<exclusions>
<module name="javax.faces.api" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2"/>
</dependencies>
</sub-deployment>
</jboss-deployment-structure>
WildFly 9
What it means:
Again, the ClassNotFoundException indicates a missing dependency. In this case, it can not find the class
org.dom4j.DocumentException.
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
<module name="org.apache.commons.logging" export="true"/>
<module name="org.dom4j" export="true"/>
</dependencies>
</deployment>
<sub-deployment name="jboss-seam-booking.war">
<exclusions>
<module name="javax.faces.api" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2"/>
</dependencies>
</sub-deployment>
</jboss-deployment-structure>
WildFly 9
What it means:
Again, the ClassNotFoundException indicates a missing dependency. In this case, it can not find the class
org.hibernate.validator.InvalidValue.
cd EAP5_HOME/jboss-eap-5.1/seam/lib
grep 'org.hibernate.validator.InvalidValue' `find . -name '*.jar'`
cp EAP5_HOME/jboss-eap-5.1/seam/lib/hibernate-validator.jar jboss-seam-booking.ear/lib
WildFly 9
INFO
What it means:
The com.sun.faces.config.ConfigurationException and java.lang.InstantiationException indicate a
dependency issue. In this case, it is not as obvious.
WildFly 9
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
<module name="com.sun.jsf-impl" slot="1.2" export="true"/>
<module name="org.apache.commons.logging" export="true"/>
<module name="org.dom4j" export="true"/>
</dependencies>
</deployment>
<sub-deployment name="jboss-seam-booking.war">
<exclusions>
<module name="javax.faces.api" slot="main"/>
<module name="com.sun.jsf-impl" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2"/>
<module name="com.sun.jsf-impl" slot="1.2"/>
</dependencies>
</sub-deployment>
</jboss-deployment-structure>
WildFly 9
What it means:
Again, the ClassNotFoundException indicates a missing dependency. In this case, it can not find the class
org.apache.commons.collections.ArrayStack.
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
<module name="com.sun.jsf-impl" slot="1.2" export="true"/>
<module name="org.apache.commons.logging" export="true"/>
<module name="org.dom4j" export="true"/>
<module name="org.apache.commons.collections" export="true"/>
</dependencies>
</deployment>
<sub-deployment name="jboss-seam-booking.war">
<exclusions>
<module name="javax.faces.api" slot="main"/>
<module name="com.sun.jsf-impl" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2"/>
<module name="com.sun.jsf-impl" slot="1.2"/>
</dependencies>
</sub-deployment>
</jboss-deployment-structure>
WildFly 9
["jboss.deployment.subunit.\"jboss-seam-booking.ear\".\"jboss-seam-booking.jar\".component.AuthenticatorAction
missing [
jboss.naming.context.java.comp.jboss-seam-booking.\"jboss-seam-booking.jar\".AuthenticatorAction.\"env/org.jbo
]","jboss.deployment.subunit.\"jboss-seam-booking.ear\".\"jboss-seam-booking.jar\".component.HotelSearchingAct
missing [
jboss.naming.context.java.comp.jboss-seam-booking.\"jboss-seam-booking.jar\".HotelSearchingAction.\"env/org.jb
]","
<... additional logs removed ...>
"jboss.deployment.subunit.\"jboss-seam-booking.ear\".\"jboss-seam-booking.jar\".component.BookingListAction.ST
missing [
jboss.naming.context.java.comp.jboss-seam-booking.\"jboss-seam-booking.jar\".BookingListAction.\"env/org.jboss
]","jboss.persistenceunit.\"jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase\"
missing [ jboss.naming.context.java.bookingDatasource ]"]}}}
What it means:
When you get a Services with missing/unavailable dependencies error, look that the text within the
brackets after missing.
In this case you see:
missing [
jboss.naming.context.java.comp.jboss-seam-booking.\"jboss-seam-booking.jar\".AuthenticatorAction.\"env/org.jbo
]
WildFly 9
ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC00001: Failed to start service
jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase":
org.jboss.msc.service.StartException in service
jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase": Failed to
start service
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1786)
(... log messages removed ...)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: bookingDatabase] Unable to
build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:903)
{... log messages removed ...)
Caused by: org.hibernate.HibernateException: could not instantiate RegionFactory
[org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge]
at org.hibernate.cfg.SettingsFactory.createRegionFactory(SettingsFactory.java:355)
(... log messages removed ...)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [:1.6.0_25]
(... log messages removed ...)
Caused by: org.hibernate.cache.CacheException: could not instantiate CacheProvider
[org.hibernate.cache.HashtableCacheProvider]
at
org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge.<init>(RegionFactoryCacheProviderBridge.j
... 20 more
Caused by: java.lang.ClassNotFoundException: org.hibernate.cache.HashtableCacheProvider from
[Module "org.hibernate:main" from local module loader @12a3793 (roots:
/home/sgilda/tools/jboss7/modules)]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:191)
(... log messages removed ...)
What it means:
The ClassNotFoundException indicates a missing dependency. In this case, it can not find the class
org.hibernate.cache.HashtableCacheProvider.
WildFly 9
cd EAP5_HOME/jboss-eap-5.1/seam/lib
grep 'org.hibernate.validator.InvalidValue' `find . -name '*.jar'`
cp EAP5_HOME/jboss-eap-5.1/seam/lib/hibernate-core.jar jboss-seam-booking.ear/lib
WildFly 9
ERROR [org.jboss.msc.service.fail] (MSC service thread 1-2) MSC00001: Failed to start service
jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase":
org.jboss.msc.service.StartException in service
jboss.persistenceunit."jboss-seam-booking.ear/jboss-seam-booking.jar#bookingDatabase": Failed to
start service
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1786)
(... log messages removed ...)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: bookingDatabase] Unable to
build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:903)
(... log messages removed ...)
Caused by: org.hibernate.HibernateException: could not instantiate RegionFactory
[org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge]
at org.hibernate.cfg.SettingsFactory.createRegionFactory(SettingsFactory.java:355)
(... log messages removed ...)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [:1.6.0_25]
(... log messages removed ...)
Caused by: org.hibernate.cache.CacheException: could not instantiate CacheProvider
[org.hibernate.cache.HashtableCacheProvider]
at
org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge.<init>(RegionFactoryCacheProviderBridge.j
... 20 more
Caused by: java.lang.ClassCastException: org.hibernate.cache.HashtableCacheProvider cannot be
cast to org.hibernate.cache.spi.CacheProvider
at
org.hibernate.cache.internal.bridge.RegionFactoryCacheProviderBridge.<init>(RegionFactoryCacheProviderBridge.j
... 20 more
What it means:
A ClassCastException can be a result of many problems. If you look at this exception in the log, it appears
the class org.hibernate.cache.HashtableCacheProvider extends org.hibernate.cache.spi.CacheProvider and
is being loaded by a different class loader than the class it extends. The
org.hibernate.cache.HashtableCacheProvider class is in in the hibernate-core.jar and is being loaded by the
application class loader. The class it extends, org.hibernate.cache.spi.CacheProvider, is in the
org/hibernate/main/hibernate-core-4.0.0.Beta1.jar and is implicitly loaded by that module.
This is not obvious, but due to changes in Hibernate 4, this problem is caused by a backward compatibility
issue due moving the HashtableCacheProvider class into another package. This class was moved from the
org.hibernate.cache package to the org.hibernate.cache.internal package. If you don't remove the
hibernate.cache.provider_class property from the persistence.xml file, it will force the Seam application to
bundle the old Hibernate libraries, resulting in ClassCastExceptions, In WildFly, you should move away from
using HashtableCacheProvider and use Infinispan instead.
WildFly 9
What it means:
A NameNotFoundException indications a JNDI naming issue. JNDI naming rules have changed in
WildFly and we need to modify the lookup names to follow the new rules.
15:01:16,138 INFO
WildFly 9
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-1) JNDI bindings for session bean named RegisterAction in deployment unit subdeployment
"jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam-booking.jar/RegisterAction!org.jboss.seam.example.booking.Register
java:app/jboss-seam-booking.jar/RegisterAction!org.jboss.seam.example.booking.Register
java:module/RegisterAction!org.jboss.seam.example.booking.Register
java:global/jboss-seam-booking/jboss-seam-booking.jar/RegisterAction
java:app/jboss-seam-booking.jar/RegisterAction
java:module/RegisterAction
15:01:16,138 INFO
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-1) JNDI bindings for session bean named BookingListAction in deployment unit
subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam-booking.jar/BookingListAction!org.jboss.seam.example.booking.Bookin
java:app/jboss-seam-booking.jar/BookingListAction!org.jboss.seam.example.booking.BookingList
java:module/BookingListAction!org.jboss.seam.example.booking.BookingList
java:global/jboss-seam-booking/jboss-seam-booking.jar/BookingListAction
java:app/jboss-seam-booking.jar/BookingListAction
java:module/BookingListAction
15:01:16,138 INFO
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-1) JNDI bindings for session bean named HotelBookingAction in deployment unit
subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelBookingAction!org.jboss.seam.example.booking.Hotel
java:app/jboss-seam-booking.jar/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking
java:module/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking
java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelBookingAction
java:app/jboss-seam-booking.jar/HotelBookingAction
java:module/HotelBookingAction
15:01:16,138 INFO
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-1) JNDI bindings for session bean named AuthenticatorAction in deployment unit
subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam-booking.jar/AuthenticatorAction!org.jboss.seam.example.booking.Auth
java:app/jboss-seam-booking.jar/AuthenticatorAction!org.jboss.seam.example.booking.Authenticator
java:module/AuthenticatorAction!org.jboss.seam.example.booking.Authenticator
java:global/jboss-seam-booking/jboss-seam-booking.jar/AuthenticatorAction
java:app/jboss-seam-booking.jar/AuthenticatorAction
java:module/AuthenticatorAction
15:01:16,139 INFO
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-1) JNDI bindings for session bean named ChangePasswordAction in deployment unit
subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam-booking.jar/ChangePasswordAction!org.jboss.seam.example.booking.Cha
java:app/jboss-seam-booking.jar/ChangePasswordAction!org.jboss.seam.example.booking.ChangePassword
java:module/ChangePasswordAction!org.jboss.seam.example.booking.ChangePassword
java:global/jboss-seam-booking/jboss-seam-booking.jar/ChangePasswordAction
java:app/jboss-seam-booking.jar/ChangePasswordAction
java:module/ChangePasswordAction
WildFly 9
15:01:16,139 INFO
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-1) JNDI bindings for session bean named HotelSearchingAction in deployment unit
subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelSearchingAction!org.jboss.seam.example.booking.Hot
java:app/jboss-seam-booking.jar/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching
java:module/HotelSearchingAction!org.jboss.seam.example.booking.HotelSearching
java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelSearchingAction
java:app/jboss-seam-booking.jar/HotelSearchingAction
java:module/HotelSearchingAction
15:01:16,140 INFO
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-6) JNDI bindings for session bean named EjbSynchronizations in deployment unit
subdeployment "jboss-seam.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizat
java:app/jboss-seam/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations
java:module/EjbSynchronizations!org.jboss.seam.transaction.LocalEjbSynchronizations
java:global/jboss-seam-booking/jboss-seam/EjbSynchronizations
java:app/jboss-seam/EjbSynchronizations
java:module/EjbSynchronizations
15:01:16,140 INFO
[org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service
thread 1-6) JNDI bindings for session bean named TimerServiceDispatcher in deployment unit
subdeployment "jboss-seam.jar" of deployment "jboss-seam-booking.ear" are as follows:
java:global/jboss-seam-booking/jboss-seam/TimerServiceDispatcher!org.jboss.seam.async.LocalTimerServiceDispat
java:app/jboss-seam/TimerServiceDispatcher!org.jboss.seam.async.LocalTimerServiceDispatcher
java:module/TimerServiceDispatcher!org.jboss.seam.async.LocalTimerServiceDispatcher
java:global/jboss-seam-booking/jboss-seam/TimerServiceDispatcher
java:app/jboss-seam/TimerServiceDispatcher
java:module/TimerServiceDispatcher
We need to modify the WAR's lib/components.xml file to use the new JNDI bindings. In the log, note the EJB
JNDI bindings all start with "java:app/jboss-seam-booking.jar"
Replace the <core:init> element as follows:
Next, we need to add the EjbSynchronizations and TimerServiceDispatcher JNDI bindings. Add the following
component elements to the file:
WildFly 9
<component class="org.jboss.seam.transaction.EjbSynchronizations"
jndi-name="java:app/jboss-seam/EjbSynchronizations"/>
<component class="org.jboss.seam.async.TimerServiceDispatcher"
jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
WildFly 9
Summary of Changes
Although it would be much more efficient to determine dependencies in advance and add the implicit
dependencies in one step, this exercise shows how problems appear in the log and provides some
information on how to debug and resolve them.
The following is a summary of changes made to the application when migrating it to WildFly:
1. We created a jboss-deployment-structure.xml file in the EAR's META-INF/ directory. We
added "dependencies" and "exclusions" to resolve ClassNotFoundExceptions. This file contains the
following data:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
<module name="com.sun.jsf-impl" slot="1.2" export="true"/>
<module name="org.apache.commons.logging" export="true"/>
<module name="org.dom4j" export="true"/>
<module name="org.apache.commons.collections" export="true"/>
</dependencies>
</deployment>
<sub-deployment name="jboss-seam-booking.war">
<exclusions>
<module name="javax.faces.api" slot="main"/>
<module name="com.sun.jsf-impl" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2"/>
<module name="com.sun.jsf-impl" slot="1.2"/>
</dependencies>
</sub-deployment>
</jboss-deployment-structure>
hibernate-core.jar
hibernate-validator.jar
WildFly 9
3. We modified the {{jboss-seam-booking.jar/META-INF/persistence.xml} file as follows.
1. First, we changed the jta-data-source element to use the Example database that ships with
AS7:
4. We modified the WAR's lib/components.xml file to use the new JNDI bindings
1. We replaced the <core:init> existing element as follows:
<component class="org.jboss.seam.transaction.EjbSynchronizations"
jndi-name="java:app/jboss-seam/EjbSynchronizations"/>
<component class="org.jboss.seam.async.TimerServiceDispatcher"
jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
The unmodified EAR from EAP 5.1 (jboss-seam-booking-eap51.ear.tar.gz) and the EAR as modified to run
on AS7 (jboss-seam-booking-as7.ear.tar.gz) are attached to this document.
WildFly 9
WildFly 9
Feel free to add content in any way you prefer. You do not need to follow the template below. This
is a work in progress.
Introduction
About this Guide
Introduction to the JBoss AS 7 Server
Java Enterprise Edition 6 Overview
Overview of Java EE 6 Profiles
Java Enterprise Edition 6 Web Profile
Java Enterprise Edition 6 Full Profile
JBoss AS 7 Architectural Overview
Review What's New and Different in JBoss AS 7
Modules and Modular Class Loading
Directory Structure of JBoss AS 7
Deployment
Administration Tools
Prepare for Migration
Become Familiar with Java EE 6
Become Familiar with JBoss AS 7
Identify the current hardware and operating systems
Examine the existing WebLogic application server and platform
Examine and understand the existing WebLogic application
Review monitoring and administration procedures and tools
Review resources available for the migration process
Prepare a migration plan
Execute the plan
Server Configuration and Deployment Descriptor Files
WebLogic and JBoss Server Configuration File
WebLogic Server Configuration and Deployment Descriptor Files
JBoss AS 7 Configuration File
Migrate the Server Configuration
Map Configuration Files and Descriptors to the JBoss Equivalent
Replace the weblogic-ejb-jar.xml Deployment Descriptor
Map weblogic-ejb-jar.xml Elements to the jboss-ejb3.xml Descriptor
Map Additional weblogic-ejb-jar.xml Elements to the JBoss Enterprise Application
Platform Equivalent
Migrate weblogic.xml Descriptor File Configurations
Migrate weblogic-application.xml Descriptor File Configurations
Replace the WebLogic plan.xml Deployment Descriptor Configuration
Use Property Substitution to Specify the Target Deployment Environment
WebService.xml
*-jms.xml
weblogic-ejb-jar.xml
WildFly 9
Security
Replace WebLogic Oracle Wallets
WebLogic Certicom-based SSL Implementation
WebLogic Security versus JBoss JAAS Security APIs
Understand Differences Between WebLogic and JBoss Implementations
Overview of JNDI Differences
Migrate WebLogic JNDI Lookups to Use Portable JNDI Syntax
Replace WebLogic JNDI Lookup Code
Portable JNDI Naming Syntax
Portable JNDI Naming Syntax Rules
Programmatic Login
WebLogic Transaction Manager JEE Transaction Manager
WebLogic JMX Lookups versus JBoss JMX Lookups
Class Loading and Application Packaging
Archive Packaging and Assembly Rules
Debug and Resolve ClassCastExceptions and ClassNotFoundExceptions
Hibernate and JPA
Migrate Your Application From Hibernate 3 to Hibernate 4
Configure Your Application to Use the Hibernate 3 Libraries
Replace WebLogic Proprietary Features
WebLogic CommonJ Framework or WebLogic Work Manager API
Replace WebLogic Virtual Directories
Split Directories
Replace WebLogic ApplicationLifecycleListener Code
Replace Application Start and Stop Events
WebLogic Proprietary Annotations
Replace the Proprietary WebLogic @WLServlet Annotation
Replace the Proprietary WebLogic @WLFilter Annotation
Replace the Proprietary WebLogic @WLInitParam Annotation
WebLogic Specific Oracle Datasources
WildFly 9
Evaluate the WebLogic Application
Examine the High-level Architecture of the Application
JVM Version
Frameworks
IDE (Eclipse Plugins)
Database
LDAP
Requirements for High-Availablity, Clusting, Failover, Caching
Third-party Libraries
External Systems
WebLogic Proprietary Libraries and APIs
Examine the Current Build Process
Analyze and Understand the Application Code
Services and Components
Proprietary WebLogic Features or Libraries
Packaging and Deployment
Deployment Descriptors and Plans
Evaluate the WebLogic Development Tools
Eclipse and Plugins
NetBeans
ADF
Data Migration
Determine Need for JBoss Modules
Configure the Environment for the Migrated Applications
Install JBoss
Verify the Installation Using the Helloworld Quickstart
Migrate the Application
Execute the Migration Plan
Test
Move to Production
Tools and Tips
Debugging
Automated Tools
FAQs
Consulting Service
Introduction
About this Guide
The purpose of this document is to guide you through the planning process and migration of fairly simple and
standard Oracle WebLogic applications to JBoss AS 7. Oracle WebLogic applications that adhere to the
Java EE 6 specification should require minimal changes to run on JBoss AS 7.
This document will not cover migration of advanced features such as portal, rules engines, workflow
systems, or ESB frameworks. Red Hat Consulting and Red Hat partners offer a wide variety of workshops,
training, and service offerings designed to help customers migrate more complex applications.
WildFly 9
WildFly 9
WildFly 9
Domain Management
In JBoss AS 7, the server can be run as a standalone server or in a managed domain. In a managed
domain, you can configure entire groups of servers at once, keeping configurations synchronized across
your entire network of servers. While this should not impact applications built for previous releases, this can
simplify management of deployments to multiple servers. For more information, refer to About Managed
Domains in the Administration and Configuration Guide for JBoss Enterprise Application Platform 6 on the
Customer Portal .
Deployment Configuration
Standalone Servers and Managed Domains
JBoss AS 7 used profile based deployment configuration. These profiles were located in the
JBOSS_HOME/server/ directory. Applications often contained multiple configuration files for security,
database, resource adapter, and other configurations. In JBoss Enterprise Application Platform 6,
deployment configuration is done using one file. This file is used to configure all the services and
subsystems used for the deployment. A standalone server is configured using the
JBOSS_HOME/standalone/configuration/standalone.xml file. For servers running in a managed domain, the
server is configured using the JBOSS_HOME/domain/configuration/domain.xml file. The information
contained in the multiple JBoss Enterprise Application Platform 5 configuration files must be migrated to the
new single configuration file.
Ordering of deployments
JBoss AS 7 uses fast, concurrent initialization for deployment resulting in improved performance and
efficiency. In most cases, the application server is able to automatically determine dependencies in advance
and choose the most efficient deployment strategy. However, JBoss Enterprise Application Platform 5
applications that consist of multiple modules deployed as EARs and use legacy JNDI lookups instead of CDI
injection or resource-ref entries may require configuration changes.
Directory Structure and Scripts
As previously mentioned, JBoss AS 7 no longer uses profile based deployment configuration, so there is no
JBOSS_HOME/server/ directory. Configuration files for standalone servers are now located in the
JBOSS_HOME/standalone/configuration/ directory and deployments are located in the
JBOSS_HOME/standalone/deployments/ directory. For servers running in a managed domain, configuration
files can be found in the JBOSS_HOME/domain/configuration/ directory and deployments can be found in
the JBOSS_HOME/domain/deployments/ directory.
In JBoss Enterprise Application Platform 5, the Linux script JBOSS_HOME/bin/run.sh or Windows script
JBOSS_HOME/bin/run.bat was used to start the server. In JBoss Enterprise Application Platform 6, the
server start script is dependent on how you run your server. The Linux script
JBOSS_HOME/bin/standalone.sh or Windows script JBOSS_HOME/bin/standalone.bat is used to start a
standalone server. The Linux script JBOSS_HOME/bin/domain.sh or Windows script
JBOSS_HOME/bin/domain.bat is used to start a managed domain.
WildFly 9
JNDI Lookups
JBoss AS 7 now uses standardized portable JNDI namespaces. Applications that use other types of JNDI
lookups must be changed to follow the new standardized JNDI namespace convention. For more information
about JNDI naming syntax, see the section below on Portable JNDI Naming Syntax.
The module name, com.mysql, should match the directory structure for the module.
Creating custom static modules can be useful if many applications are deployed on the same server that use
the same third party libraries. Instead of bundling those libraries with each application, a module containing
these libraries can be created and installed by the JBoss administrator. The applications can then declare an
explicit dependency on the custom static modules.
h6, Dynamic Modules
Dynamic Modules are created and loaded by the application server for each JAR or WAR deployment, or
subdeployment in an EAR. The name of a dynamic module is derived from the name of the deployed
archive. Because deployments are loaded as modules, they can configure dependencies and be used as
dependencies by other deployments.
Modules are only loaded when required. This usually only occurs when an application is deployed that has
explicit or implicit dependencies.
For more information on modular class loading, see Class Loading in AS7 .
WildFly 9
Modules and Class Loading in Enterprise Archives
Enterprise Archives (EAR) are not loaded as a single module like JAR or WAR deployments. They are
loaded as multiple unique modules.
The following rules determine what modules exist in an EAR.
Each WAR and EJB JAR subdeployment is a module.
The contents of the lib/ directory in the root of the EAR archive is a module. This is called the
parent module.
These modules have the same behavior as any other module with the following additional implicit
dependencies:
WAR subdeployments have implicit dependencies on the parent module and any EJB JAR
subdeployments.
EJB JAR subdeployments have implicit dependencies on the parent module and any other EJB JAR
subdeployments.
The implicit dependencies described above occur because JBoss AS 7 has subdeployment class loader
isolation disabled by default.
Subdeployment class loader isolation can be enabled if strict compatibility is required. This can be enabled
for a single EAR deployment or for all EAR deployments. The Java EE 6 specification recommends that
portable applications should not rely on subdeployments being able to access each other unless
dependencies are explicitly declared as Class-Path entries in the MANIFEST.MF file of each subdeployment.
WildFly 9
level Directories
Name
Purpose
appclient/
bin/
Contains start-up scripts for JBoss EAP 6 on Red Hat Enterprise Linux and Microsoft
Windows.
bundles/
docs/
domain/
Configuration files, deployment content, and writable areas used when JBoss EAP 6
runs as a managed domain.
modules/
Modules which are dynamically loaded by JBoss EAP 6 when services request them.
standalone/
Configuration files, deployment content, and writable areas used when JBoss EAP 6
runs as a standalone server.
welcome-content/ Contains content used by the Welcome web application which is available on port 8080
of a default installation.
jboss-modules.jar The bootstrapping mechanism which loads modules.
Directories within the domain/ directory
Name
Purpose
configuration/ Configuration files for the managed domain. These files are modified by the Management
Console and Management CLI, and are not meant to be edited directly.
data/
Information about deployed services. Services are deployed using the Management
Console and Management CLI, rather than by a deployment scanner. Therefore, do not
place files in this directory manually.
log/
Contains the run-time log files for the host and process controllers which run on the local
instance.
servers/ Contains the equivalent data/, log/, and tmp/ directories for each server instance in a domain, which
contain similar data to the same directories within the top-level domain/ directory. |
tmp/ Contains temporary data such as files pertaining to the shared-key mechanism used by the
Management CLI to authenticate local users to the managed domain.
WildFly 9
Directories within the standalone/ directory
Name
Purpose
configuration/ Configuration files for the standalone server. These files are modified by the Management
Console and Management CLI, and are not meant to be edited directly.
deployments/ Information about deployed services. The standalone server does include a deployment
scanner, so you can place archives in this directory to be deployed. However, the
recommended approach is to manage deployments using the Management Console or
Management CLI.
lib/
tmp/
Contains temporary data such as files pertaining to the shared-key mechanism used by the
Management CLI to authenticate local users to the server.
Deployment
TODO: section is not complete.
Administration Tools
Management Console
The Management Console is a web-based administration tool used to to start and stop servers, deploy and
undeploy applications, tune system settings, and make persistent modifications to the server configuration.
The Management Console also has the ability to perform administrative tasks, with live notifications when
any changes require the server instance to be restarted or reloaded. In a Managed Domain, server instances
and server groups in the same domain can be centrally managed from the Management Console of the
domain controller.
JBoss CLI
The Management Command Line Interface (CLI) is a command line administration tool that can perform
operations in batch modes, allowing multiple tasks to be run as a group.
JON
TODO: section is not complete.
WildFly 9
WildFly 9
AS 7 Equivalent
ejb-jar.xml,
weblogic-ejb-jar.xml, or
weblogic-cmp-rdbms-jar.xml or domain.xml
weblogic.xml
standalone.xml
or domain.xml
*-jdbc.xml
standalone.xml
or domain.xml
WildFly 9
WEBLOGIC_PREFIX/ejb-name
JBOSS_PREFIX/ejb-name
WEBLOGIC_PREFIX/resource-description/res-ref-name
JBOSS_PREFIX/resource-ref/res-ref-name
WEBLOGIC_PREFIX/resource-env-description/res-env-ref-name
JBOSS_PREFIX/resource-env-ref/resource-env-re
WEBLOGIC_PREFIX/ejb-reference-description/ejb-ref-name
JBOSS_PREFIX/ejb-ref/ejb-ref-name
WEBLOGIC_PREFIX/service-reference-description/service-ref-name JBOSS_PREFIX/service-ref/service-ref-name
WEBLOGIC_PREFIX/service-reference-description/wsdl-file
JBOSS_PREFIX/service-ref/wsdl-file
For readability, the variables WEBLOGIC_PREFIX and JBOSS_PREFIX were used in place of
paths in the table.
For WebLogic descriptor elements, replace the variable WEBLOGIC_PREFIX with the
following path prefix: /weblogic-ejb-jar/weblogic-enterprise-bean for all bean types.
For JBoss descriptor elements, replace the variable JBOSS_PREFIX with the following file
path prefix depending on the bean type:
Entity Bean: /ejb-jar/enterprise-beans/entity
Session Bean: /ejb-jar/enterprise-beans/session
Message-Driven Bean: /ejb-jar/enterprise-beans/message-driven
WildFly 9
<jbosscmp-jdbc>
...
<entity>
<ejb-name>Student</ejb-name>
<create-table>true</create-table>
<remove-table>true</remove-table>
<table-name>STUDENT</table-name>
...
<sync-on-commit-only>true</sync-on-commit-only>
<insert-after-ejb-post-create>true</insert-after-ejb-post-create>
<call-ejb-store-on-clean>true</call-ejb-store-on-clean>
</entity>
</jbosscmp-jdbc>
This feature is available in JBoss Enterprise Application Platform 6.1. For JBoss Enterprise
Application Platform 6.0.x, it is available as a patch.
WildFly 9
The following table maps the some common weblogic.xml configurations to JBoss
weblogic.xml
JBoss Equivalent
<context-root>MyAppContextRoot</context-root>
<jboss-web>
<context-root>MyAppContextRoot</context-roo
</jboss-web>
WildFly 9
Map roles:
<security-role-assignment>
<role-name>TestRole1</role-name>
<principal-name>TestRole1</principal-name>
</security-role-assignment>
<security-domain name="FormBasedAuthWebAppPolic
<authentication> \\
<login-module code="org.jboss.security.
flag="required">
<module-option name="dsJndiName" va
<module-option name="principalsQuer
PRINCIPLES where principal_id=?"/>
<module-option name="rolesQuery" va
ROLES where principal_id=?"/>
</login-module>
<module-option name="rolesPropertie
value="/home/userone/jboss-eap-6.0-GA/standalon
<module-option name="replaceRole" v
</login-module>
</authentication>
</security-domain>
<jboss-web>
<security-domain>java:/jaas/FormBasedAuthWe
</jboss-web>
<session-descriptor>
<session-param>
<param-name>TimeoutSecs</param-name>
<param-value>3650</param-value>
</session-param>
<session-config>
<session-timeout>3650</session-timeout>\
</session-config>
</session-descriptor>
Since the WAR has its own scoped class loader, the
<save-sessions-enabled>true</save-sessions-enabled>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
WildFly 9
Configure JSPs:
<jsp-descriptor>
<jsp-param>
<param-name>keepgenerated</param-name>
<param-value>true</param-value>
native="false">
<configuration>
<jsp-configuration development="true" j
</jsp-param>
keep-generated="true"/>
<jsp-param>
<param-name>encoding</param-name>
<param-value>ISO8859_1</param-value>
</configuration>
<connector name="http" protocol="HTTP/1.1"
<virtual-server name="default-host" enable-
</jsp-param>
<alias name="localhost"/>
</jsp-descriptor>
<alias name="example.com"/>
</virtual-server>
</subsystem>
<application-param>
<description>
Web application default encoding
<context-param>
<description>
Web application default encoding
</description>
<param-name>
webapp.encoding.default
</description>
<param-name>
webapp.encoding.default
</param-name>
</param-name>
<param-value>
UTF8
</param-value>
<param-value>
UTF8
</param-value>
</application-param>
</context-param>
WildFly 9
<subsystem xmlns="urn:jboss:domain:ee:1.1">
<spec-descriptor-property-replacement>true</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
</subsystem>
For more information about property substitution, refer to the Administration and Configuration Guide for
JBoss Enterprise Application Platform 6 located on the Customer Portal at
https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/.
2. Bind Strings for JNDI Runtime Mapping
For values outside deployment descriptors that change depending on the target environment, you can bind
string values into JNDI and them map them into the application.
Assume the application's web.xml file contains the following resource reference:
<resource-env-ref>
<description>IP address of the destination</description>
<resource-env-ref-name>destination/ip-address</resource-env-ref-name>
<resource-env-ref-type>java.lang.String</resource-env-ref-type>
</resource-env-ref>
To bind simple strings into JNDI, create a <simple> element in the naming subsystem of the server
configuration file. The following is an example of the naming subsystem element configured for JNDI
substitution.
WildFly 9
<subsystem xmlns="urn:jboss:domain:naming:1.1">
<bindings>
<simple name="java:/my/jndi/key" value="MyJndiValue"/>
</bindings>
</subsystem>
Add an entry to the application's jboss-web.xml to map the global JNDI entry to the application's
java:comp/env/ Environment Naming Context (ENC). The <resource-env-ref-name> element value must
match the value specified in the web.xml and the <jndi-name> element must match the <simple> element
name in the server configuration file.
<jboss-web>
<resource-env-ref>
<resource-env-ref-name>destination/ip-address</resource-env-ref-name>
<jndi-name>java:/my/jndi/key</jndi-name>
</resource-env-ref>
</jboss-web>
Follow the same procedure to implement property substitution for other descriptor files.
For more information about how to manage the server configuration files, refer to the Administration and
Configuration Guide for JBoss Enterprise Application Platform 6 located on the Customer Portal at
https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/.
WebService.xml
WebLogic Webservice descriptor files
TODO: This section is not complete
*-jms.xml
WebLogic JMS descriptor file
TODO: This section is not complete
weblogic-ejb-jar.xml
WebLogic EJB descriptor
WildFly 9
Security
Replace WebLogic Oracle Wallets
Weblogic administrators use wallets created by Oracle Wallet Manager to manage public key security
credentials on application clients and servers. These wallets must first be converted to standard Java
KeyStore (JKS) entries that can then be used to configure the credentials in JBoss Enterprise Application
Platform 6.
1. Convert Oracle Wallet to JKS
Use the Oracle orapki command-line tool to convert the wallet to standard JKS keystore. Refer to the Oracle
Wallet Manager documentation for details:
http://docs.oracle.com/cd/E16340_01/core.1111/e10105/walletmgr.htm#ASADM10989.
2. Configure JBoss Enterprise Application Platform 6 to Use the Java KeyStore
Java KeyStores are configured in the security subsystem of the server configuration file. The schema is
defined in the file:///JBOSS_INSTALL_DIRECTORY/docs/schema/jboss-as-config_1_4.xsd file. Be sure to
replace JBOSS_INSTALL_DIRECTORY in the previous link with the actual path for your install. For details
on how to configure the server to use keystores, refer to the chapter entitled Securing JBoss Enterprise
Application Platform in the Administration and Configuration Guide for JBoss Enterprise Application Platform
6 located on the Customer Portal at
https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/.
WildFly 9
In JBoss, you instantiate the InitialContext with no argument and then look up the service using the portable
JNDI lookup rules: java:global, java:app, java:module.
This is an example of what the code would look like in JBoss:
WildFly 9
Description
Namespace
java:global
Names in this namespace are shared by all applications deployed in an application server
instance. Use names in this namespace to find remote EJBs. The following is an example of
a java:global namespace:
java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelBookingAction
java:module Names in this namespace are shared by all components in a module, for example, all
enterprise beans in a single EJB module or all components in a web module. The following
is an example of a java:module namespace:
java:module/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking
java:app
Names in this namespace are shared by all components in all modules in a single
application. For example, a WAR and an EJB jar file in the same EAR file would have
access to resources in the java:app namespace.
The following is an example of a java:app namespace:
java:app/jboss-seam-booking.jar/HotelBookingAction
You can find more information about JNDI naming contexts in section EE.5.2.2, "Application Component
Environment Namespaces" in the "JSR 316: JavaTM Platform, Enterprise Edition (Java EE) Specification,
v6". You can download the specification from here: http://jcp.org/en/jsr/detail?id=316
WildFly 9
Programmatic Login
WebLogic provides a proprietary ServletAuthentication class to perform programmatic login. In JBoss
AS 7, you can use the standard Java EE6 Servlet 3.0 HttpServletRequest.login() method to perform
programmatic login or you can define a <security-constraint> element in the web.xml file.
To enable programmatic login, you must replace the WebLogic proprietary code with one of the following:
You can add the following annotations to the Servlet class that performs the authentication.
If you prefer not to use the standard servlet, you can instead add a <security-constraint>
element containing a dummy URL pattern to the web.xml file. This notifies JBoss to create a default
Authenticator. Failure to create a <security-constraint> element in the web.xml file may result
in the error message "No authenticator available for programmatic login".
The following is an example of a web.xml file with a <security-constraint> element:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>ApplicationRealm</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/loginError.jsp</form-error-page>
</form-login-config>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources</web-resource-name>
<description>Protects all resources</description>
<url-pattern>/dummy/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>myRole</role-name>
</auth-constraint>
</security-constraint>
WildFly 9
If the application uses the WebLogic proprietary ServletAuthentication class for programmatic login,
you must replace it with the standard HttpServletRequest login as follows:
WildFly 9
WildFly 9
Resolve ClassCastExceptions Caused by Duplicate JARs
Because JBoss AS 7 ships with a number of classes, or modules, that are commonly used by applications,
packaging these common JARs with your application can result in a ClassCastException. For example, if
you bundle the jstl.jar and standard.jar with the application archive, you may see a ClassCastException
similar to the following:
08:38:01,867 ERROR
[org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/].[MVCUserInterface]]
(http-localhost/127.0.0.1:8080-2)
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<dependencies>
<module name="javax.servlet.jstl.api" slot="main" />
</dependencies>
</deployment>
</jboss-deployment-structure>
3. Search the application archive to find all JAR(s) that are packaged with the application that contain
the class named by the ClassCastException. In this case, the jstl.jar and standard.jar JARs were
packaged in the lib/ folder of the application archive. Remove the duplicate JAR(s) from the
application's packaged WAR or EAR file.
WildFly 9
Resolve ClassCastExceptions and ClassNotFoundExceptions Caused by API Version Differences
If your application uses a version of an API other than the default API included in the main/ module of the
modules/system/layers/base/ directory, you may see a ClassCastException or a ClassNotFoundException
when you run the application.
For example, if your application uses JSF 1.2 instead of the default JSF 2.0, you may see you may see a
ClassCastException or ClassNotFoundException like the following:
In this case, it cannot find the class javax.faces.FacesException due to a mismatch in API versions. The
default JSF module for JBoss AS 7 is version JSF 2.0 and the application is using JSF 1.2. To resolve the
mismatch, you must explicitly include the JSF 1.2 dependency and exclude the JSF 2.0 dependency.
To resolve this issue:
1. Find the JBoss module that contains the class named by the ClassNotFoundException. In this case,
there are 2 modules for the javax.faces.api classes. The default module for JSF 2.0 is located in the
EAP_HOME/modules/system/layers/base/javax/faces/api/main directory and a module for JSF 1.2 is
located in the EAP_HOME/modules/system/layers/base/javax/faces/api/1.2 directory.
2. Explicitly define the dependency on the older JSF 1.2 version in the jboss-deployment-structure.xml
file and exclude the default JSF 2.0 module as follows:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="javax.faces.api" slot="main"/>
<module name="com.sun.jsf-impl" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
<module name="com.sun.jsf-impl" slot="1.2" export="true"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
3. Search the application archives and remove any jsf-api JARs from the packaged application.
WildFly 9
You have 2 choices:
1. You can migrate your Hibernate 3.x application to use Hibernate 4. This is the recommended
approach.
2. If you do not want to update your application to use Hibernate 4, you can configure your application to
use Hibernate 3.x in one of the following ways:
1. You can package the Hibernate 3 libraries with your application.
2. You can create a custom Hibernate 3 module.
The following sections describe how to do this.
WildFly 9
Migrate Your Hibernate 3.5.x Application to Hibernate 4.x
1. Merge the AnnotationConfiguration into the Configuration
Although AnnotationConfiguration is now deprecated, it should not affect your migration. If you are still
using an hbm.xml file, you should be aware that JBoss AS 7 now uses the
"org.hibernate.cfg.EJB3NamingStrategy" in AnnotationConfiguration instead of the
"org.hibernate.cfg.DefaultNamingStrategy" that was used in previous releases. This can result in
naming mismatches. If you rely on the naming strategy to default the name of an association
(many-to-many and collections of elements) table, you may see this issue. To resolve it, you can tell
Hibernate to use the legacy org.hibernate.cfg.DefaultNamingStrategy by calling
Configuration#setNamingStrategy and passing it
org.hibernate.cfg.DefaultNamingStrategy#INSTANCE.
2. Modify the namespaces to conform to the new Hibernate DTD file names.
Previous DTD Namespace
http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd http://www.hibernate.org/dtd/hibernate-configurati
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd
http://www.hibernate.org/dtd/hibernate-mapping-3
WildFly 9
Package the Hibernate 3.x JARs with the Application
1. Copy the specific Hibernate 3.x JARs into the application's lib/ directory.
2. Create a jboss-deployment-structure.xml file with the following content to tell the server to
exclude the Hibernate 4 classes:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="org.hibernate"/>
</exclusions>
<deployment>
</jboss-deployment-structure>
In some cases this may result in ClassCastExceptions or other class loading issues due to the
mixed use of the Hibernate versions. If that happens, you need to instruct the server to use only the
Hibernate 3 libraries using the following procedure.
WildFly 9
1. Create a custom module for the Hibernate 3 libraries.
1. Create a directory structure under the JBOSS_HOME/module directory to contain the Hibernate
3 files and JARs. For example:
$ cd JBOSS_HOME/modules/
$ mkdir -p org/hibernate/3
WildFly 9
2. Modify the persistence.xml to use the custom Hibernate module. Set the
"jboss.as.jpa.providerModule" to "org.hibernate:3" as follows:
The Java Persistence API (JPA) deployer will detect the presence of a persistence provider in the
application and use the Hibernate 3 libraries.
3. Create a jboss-deployment-structure.xml file with the following content to tell the server to
use the Hibernate 3 module and exclude the Hibernate 4 libraries:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="org.hibernate" slot="3"/>
</dependencies>
<exclusions>
<module name="org.hibernate" slot="main"/>
</exclusions>
<deployment>
</jboss-deployment-structure>
WildFly 9
Split Directories
WebLogic supports a split development directory environment. This directory layout contains both source
and build directories. WebLogic uses both directories during deployment to find or generate artifacts. This
model is meant for development purposes only. It is not recommended for production, so it should not impact
your migration.
WildFly 9
WebLogic Method
Description
void
preStart(ApplicationLifecycleEvent
evt)
void
postStart(ApplicationLifecycleEvent
evt)
void
preStop(ApplicationLifecycleEvent
evt)
shutdown process.
void
postStop(ApplicationLifecycleEvent
shutdown process.
evt)
WildFly 9
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent evt)
WildFly 9
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
@Startup
@Singleton
public class StartupBean
{
@PostConstruct
void startup() {
System.out.println("startup()", "@PostContruct called");
}
@PreDestroy
void shutdown() {
System.out.println("shutdown()", "@PreDestroy called");
}
}
@WLServlet
@WebServlet
javax.servlet.annotation.WebServlet
@WLFilter
@WebFilter
javax.servlet.annotation.WebFilter
@WLInitParam @WebInitParam
javax.servlet.annotation.WebParam
Be sure to modify the attributes for the annotations to conform to the standard attribute names. Details about
the attributes are listed below. For more information on the Java EE 6 servlet annotations, see the
javax.servlet.annotation javadoc .
You must also remove the WebLogic imports and JAR.
WildFly 9
WebLogic
Attribute Name
Java EE 6 Equivalent
Description / Comments
String
displayName
String displayName
String description
String description
Servlet description
String icon
String smallicon
-or-String largeicon
String name
String name
WLInitParam[]
WebInitParam[]
initParams
initParams
int loadOnStartup
int loadOnStartup
String runAs
No equivalent attribute
The run-as User for the Servlet. There are 3 options for
replacement detailed below.
String[] mapping
String[] urlPatterns or
String[] value
The following is a list of options for replacement of the runAs attribute:
1. Use the javax.annotation.security.RunAs annotation in the class file.
2. Define the run-as element for the Servlet in the application's web.xml file.
3. Define the run-as element in a application's {{web-fragments.xml} file. See sections 8.2.1 through
8.2.3 of the Servlet 3.0 specification for further information about web-fragments.
Here is an example of WebLogic code that uses the @WLServlet annotation:
import weblogic.servlet.annotation.WLServlet;
@WLServlet (
name = "catalog",
runAs = "SuperEditor"
initParams = {
@WLInitParam (name="catalog", value="spring"),
@WLInitParam (name="language", value="English")
},
mapping = {"/catalog/*"}
)
public class MyCatalogServlet extends HttpServlet { . . . }
Here is the equivalent code that uses the standard @WebServlet annotation:
WildFly 9
import javax.annotation.security.RunAs;
import javax.servlet.annotation.WebServlet;
@WebServlet (
name = "catalog",
initParams = {
@WebInitParam (name="catalog", value="spring"),
@WLInitParam (name="language", value="English")
},
urlPatterns = "/catalog/*"
)
@RunAs("SuperEditor")
public class MyCatalogServlet extends HttpServlet { . . . }
Java EE 6 Equivalent
Description / Comments
String displayName
String displayName
String description
String description
Servlet description
String icon
Name
largeicon
String name
String name
WLInitParam[]
WebInitParam[] initParams
String[] mapping
No equivalent attribute
DispatcherTypes[]
dispatcherTypes
applies
String[] servletNames
initParams
No equivalent attribute
WildFly 9
import weblogic.servlet.annotation.WLFilter;
import weblogic.servlet.annotation.WLInitParam;
@WLFilter (
name = "catalogFilter",
initParams = { @WLInitParam(name="catalog", value="winter") }
mapping = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
Here is the equivalent code that uses the standard @WebFilter annotation:
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
@WebFilter (
filterName = "catalogFilter",
initParams = { @WebInitParam(name="catalog", value="winter") }
urlPatterns = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
WildFly 9
String name
String value
String value
No equivalent attribute
String description
import weblogic.servlet.annotation.WLFilter;
import weblogic.servlet.annotation.WLInitParam;
@WLFilter (
name = "catalogFilter",
initParams = { @WLInitParam(name="catalog", value="winter") }
mapping = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
Here is the equivalent code that uses the standard @WebInitParam annotation:
import javax.servlet.annotation.WebFilter;
import avax.servlet.annotation.WebInitParam;
@WebFilter (
filterName = "catalogFilter",
initParams = { @WebInitParam(name="catalog", value="winter", description="winter catalog") }
urlPatterns = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
WildFly 9
Frameworks
Portal
Rules Engine
Workflow
ESB
LDAP
Requirements for High-Availablity, Clusting, Failover, Caching
Third-party Libraries
External Systems
WebLogic Proprietary Libraries and APIs
Examine the Current Build Process
Consider conversion to Maven
WildFly 9
Data Migration
Database
LDAP
JMS
WildFly 9
Feel free to add content in any way you prefer. You do not need to follow the template below. This
is a work in progress.
Introduction
About this Guide
Introduction to the JBoss AS 7 Server
Java Enterprise Edition 6 Overview
Overview of Java EE 6 Profiles
Java Enterprise Edition 6 Web Profile
Java Enterprise Edition 6 Full Profile
JBoss AS 7 Architectural Overview
Review What's New and Different in JBoss AS 7
Modules and Modular Class Loading
Directory Structure of JBoss AS 7
Deployment
Administration Tools
Prepare for Migration
Become Familiar with Java EE 6
Become Familiar with JBoss AS 7
Identify the current hardware and operating systems
Examine the existing WebLogic application server and platform
Examine and understand the existing WebLogic application
Review monitoring and administration procedures and tools
Review resources available for the migration process
Prepare a migration plan
Execute the plan
WildFly 9
Server Configuration and Deployment Descriptor Files
WebLogic and JBoss Server Configuration File
WebLogic Server Configuration and Deployment Descriptor Files
JBoss AS 7 Configuration File
Migrate the Server Configuration
Map Configuration Files and Descriptors to the JBoss Equivalent
Replace the weblogic-ejb-jar.xml Deployment Descriptor
Map weblogic-ejb-jar.xml Elements to the jboss-ejb3.xml Descriptor
Map Additional weblogic-ejb-jar.xml Elements to the JBoss Enterprise Application
Platform Equivalent
Migrate weblogic.xml Descriptor File Configurations
Migrate weblogic-application.xml Descriptor File Configurations
Replace the WebLogic plan.xml Deployment Descriptor Configuration
Use Property Substitution to Specify the Target Deployment Environment
WebService.xml
*-jms.xml
weblogic-ejb-jar.xml
Security
Replace WebLogic Oracle Wallets
WebLogic Certicom-based SSL Implementation
WebLogic Security versus JBoss JAAS Security APIs
Understand Differences Between WebLogic and JBoss Implementations
Overview of JNDI Differences
Migrate WebLogic JNDI Lookups to Use Portable JNDI Syntax
Replace WebLogic JNDI Lookup Code
Portable JNDI Naming Syntax
Portable JNDI Naming Syntax Rules
Programmatic Login
WebLogic Transaction Manager JEE Transaction Manager
WebLogic JMX Lookups versus JBoss JMX Lookups
Class Loading and Application Packaging
Archive Packaging and Assembly Rules
Debug and Resolve ClassCastExceptions and ClassNotFoundExceptions
Hibernate and JPA
Migrate Your Application From Hibernate 3 to Hibernate 4
Configure Your Application to Use the Hibernate 3 Libraries
WildFly 9
Replace WebLogic Proprietary Features
WebLogic CommonJ Framework or WebLogic Work Manager API
Replace WebLogic Virtual Directories
Split Directories
Replace WebLogic ApplicationLifecycleListener Code
Replace Application Start and Stop Events
WebLogic Proprietary Annotations
Replace the Proprietary WebLogic @WLServlet Annotation
Replace the Proprietary WebLogic @WLFilter Annotation
Replace the Proprietary WebLogic @WLInitParam Annotation
WebLogic Specific Oracle Datasources
Evaluate the WebLogic Application
Examine the High-level Architecture of the Application
JVM Version
Frameworks
IDE (Eclipse Plugins)
Database
LDAP
Requirements for High-Availablity, Clusting, Failover, Caching
Third-party Libraries
External Systems
WebLogic Proprietary Libraries and APIs
Examine the Current Build Process
Analyze and Understand the Application Code
Services and Components
Proprietary WebLogic Features or Libraries
Packaging and Deployment
Deployment Descriptors and Plans
Evaluate the WebLogic Development Tools
Eclipse and Plugins
NetBeans
ADF
Data Migration
Determine Need for JBoss Modules
Configure the Environment for the Migrated Applications
Install JBoss
Verify the Installation Using the Helloworld Quickstart
Migrate the Application
Execute the Migration Plan
Test
Move to Production
Tools and Tips
Debugging
Automated Tools
FAQs
Consulting Service
WildFly 9
Introduction
About this Guide
The purpose of this document is to guide you through the planning process and migration of fairly simple and
standard Oracle WebLogic applications to JBoss AS 7. Oracle WebLogic applications that adhere to the
Java EE 6 specification should require minimal changes to run on JBoss AS 7.
This document will not cover migration of advanced features such as portal, rules engines, workflow
systems, or ESB frameworks. Red Hat Consulting and Red Hat partners offer a wide variety of workshops,
training, and service offerings designed to help customers migrate more complex applications.
WildFly 9
WildFly 9
WildFly 9
Domain Management
In JBoss AS 7, the server can be run as a standalone server or in a managed domain. In a managed
domain, you can configure entire groups of servers at once, keeping configurations synchronized across
your entire network of servers. While this should not impact applications built for previous releases, this can
simplify management of deployments to multiple servers. For more information, refer to About Managed
Domains in the Administration and Configuration Guide for JBoss Enterprise Application Platform 6 on the
Customer Portal .
Deployment Configuration
Standalone Servers and Managed Domains
JBoss AS 7 used profile based deployment configuration. These profiles were located in the
JBOSS_HOME/server/ directory. Applications often contained multiple configuration files for security,
database, resource adapter, and other configurations. In JBoss Enterprise Application Platform 6,
deployment configuration is done using one file. This file is used to configure all the services and
subsystems used for the deployment. A standalone server is configured using the
JBOSS_HOME/standalone/configuration/standalone.xml file. For servers running in a managed domain, the
server is configured using the JBOSS_HOME/domain/configuration/domain.xml file. The information
contained in the multiple JBoss Enterprise Application Platform 5 configuration files must be migrated to the
new single configuration file.
Ordering of deployments
JBoss AS 7 uses fast, concurrent initialization for deployment resulting in improved performance and
efficiency. In most cases, the application server is able to automatically determine dependencies in advance
and choose the most efficient deployment strategy. However, JBoss Enterprise Application Platform 5
applications that consist of multiple modules deployed as EARs and use legacy JNDI lookups instead of CDI
injection or resource-ref entries may require configuration changes.
Directory Structure and Scripts
As previously mentioned, JBoss AS 7 no longer uses profile based deployment configuration, so there is no
JBOSS_HOME/server/ directory. Configuration files for standalone servers are now located in the
JBOSS_HOME/standalone/configuration/ directory and deployments are located in the
JBOSS_HOME/standalone/deployments/ directory. For servers running in a managed domain, configuration
files can be found in the JBOSS_HOME/domain/configuration/ directory and deployments can be found in
the JBOSS_HOME/domain/deployments/ directory.
In JBoss Enterprise Application Platform 5, the Linux script JBOSS_HOME/bin/run.sh or Windows script
JBOSS_HOME/bin/run.bat was used to start the server. In JBoss Enterprise Application Platform 6, the
server start script is dependent on how you run your server. The Linux script
JBOSS_HOME/bin/standalone.sh or Windows script JBOSS_HOME/bin/standalone.bat is used to start a
standalone server. The Linux script JBOSS_HOME/bin/domain.sh or Windows script
JBOSS_HOME/bin/domain.bat is used to start a managed domain.
WildFly 9
JNDI Lookups
JBoss AS 7 now uses standardized portable JNDI namespaces. Applications that use other types of JNDI
lookups must be changed to follow the new standardized JNDI namespace convention. For more information
about JNDI naming syntax, see the section below on Portable JNDI Naming Syntax.
The module name, com.mysql, should match the directory structure for the module.
Creating custom static modules can be useful if many applications are deployed on the same server that use
the same third party libraries. Instead of bundling those libraries with each application, a module containing
these libraries can be created and installed by the JBoss administrator. The applications can then declare an
explicit dependency on the custom static modules.
h6, Dynamic Modules
Dynamic Modules are created and loaded by the application server for each JAR or WAR deployment, or
subdeployment in an EAR. The name of a dynamic module is derived from the name of the deployed
archive. Because deployments are loaded as modules, they can configure dependencies and be used as
dependencies by other deployments.
Modules are only loaded when required. This usually only occurs when an application is deployed that has
explicit or implicit dependencies.
For more information on modular class loading, see Class Loading in AS7 .
WildFly 9
Modules and Class Loading in Enterprise Archives
Enterprise Archives (EAR) are not loaded as a single module like JAR or WAR deployments. They are
loaded as multiple unique modules.
The following rules determine what modules exist in an EAR.
Each WAR and EJB JAR subdeployment is a module.
The contents of the lib/ directory in the root of the EAR archive is a module. This is called the
parent module.
These modules have the same behavior as any other module with the following additional implicit
dependencies:
WAR subdeployments have implicit dependencies on the parent module and any EJB JAR
subdeployments.
EJB JAR subdeployments have implicit dependencies on the parent module and any other EJB JAR
subdeployments.
The implicit dependencies described above occur because JBoss AS 7 has subdeployment class loader
isolation disabled by default.
Subdeployment class loader isolation can be enabled if strict compatibility is required. This can be enabled
for a single EAR deployment or for all EAR deployments. The Java EE 6 specification recommends that
portable applications should not rely on subdeployments being able to access each other unless
dependencies are explicitly declared as Class-Path entries in the MANIFEST.MF file of each subdeployment.
WildFly 9
level Directories
Name
Purpose
appclient/
bin/
Contains start-up scripts for JBoss EAP 6 on Red Hat Enterprise Linux and Microsoft
Windows.
bundles/
docs/
domain/
Configuration files, deployment content, and writable areas used when JBoss EAP 6
runs as a managed domain.
modules/
Modules which are dynamically loaded by JBoss EAP 6 when services request them.
standalone/
Configuration files, deployment content, and writable areas used when JBoss EAP 6
runs as a standalone server.
welcome-content/ Contains content used by the Welcome web application which is available on port 8080
of a default installation.
jboss-modules.jar The bootstrapping mechanism which loads modules.
Directories within the domain/ directory
Name
Purpose
configuration/ Configuration files for the managed domain. These files are modified by the Management
Console and Management CLI, and are not meant to be edited directly.
data/
Information about deployed services. Services are deployed using the Management
Console and Management CLI, rather than by a deployment scanner. Therefore, do not
place files in this directory manually.
log/
Contains the run-time log files for the host and process controllers which run on the local
instance.
servers/ Contains the equivalent data/, log/, and tmp/ directories for each server instance in a domain, which
contain similar data to the same directories within the top-level domain/ directory. |
tmp/ Contains temporary data such as files pertaining to the shared-key mechanism used by the
Management CLI to authenticate local users to the managed domain.
WildFly 9
Directories within the standalone/ directory
Name
Purpose
configuration/ Configuration files for the standalone server. These files are modified by the Management
Console and Management CLI, and are not meant to be edited directly.
deployments/ Information about deployed services. The standalone server does include a deployment
scanner, so you can place archives in this directory to be deployed. However, the
recommended approach is to manage deployments using the Management Console or
Management CLI.
lib/
tmp/
Contains temporary data such as files pertaining to the shared-key mechanism used by the
Management CLI to authenticate local users to the server.
Deployment
TODO: section is not complete.
Administration Tools
Management Console
The Management Console is a web-based administration tool used to to start and stop servers, deploy and
undeploy applications, tune system settings, and make persistent modifications to the server configuration.
The Management Console also has the ability to perform administrative tasks, with live notifications when
any changes require the server instance to be restarted or reloaded. In a Managed Domain, server instances
and server groups in the same domain can be centrally managed from the Management Console of the
domain controller.
JBoss CLI
The Management Command Line Interface (CLI) is a command line administration tool that can perform
operations in batch modes, allowing multiple tasks to be run as a group.
JON
TODO: section is not complete.
WildFly 9
WildFly 9
AS 7 Equivalent
ejb-jar.xml,
weblogic-ejb-jar.xml, or
weblogic-cmp-rdbms-jar.xml or domain.xml
weblogic.xml
*-jdbc.xml
standalone.xml
or domain.xml
standalone.xml
or domain.xml
WildFly 9
WEBLOGIC_PREFIX/ejb-name
JBOSS_PREFIX/ejb-name
WEBLOGIC_PREFIX/resource-description/res-ref-name
JBOSS_PREFIX/resource-ref/res-ref-name
WEBLOGIC_PREFIX/resource-env-description/res-env-ref-name
JBOSS_PREFIX/resource-env-ref/resource-env-re
WEBLOGIC_PREFIX/ejb-reference-description/ejb-ref-name
JBOSS_PREFIX/ejb-ref/ejb-ref-name
WEBLOGIC_PREFIX/service-reference-description/service-ref-name JBOSS_PREFIX/service-ref/service-ref-name
WEBLOGIC_PREFIX/service-reference-description/wsdl-file
JBOSS_PREFIX/service-ref/wsdl-file
For readability, the variables WEBLOGIC_PREFIX and JBOSS_PREFIX were used in place of
paths in the table.
For WebLogic descriptor elements, replace the variable WEBLOGIC_PREFIX with the
following path prefix: /weblogic-ejb-jar/weblogic-enterprise-bean for all bean types.
For JBoss descriptor elements, replace the variable JBOSS_PREFIX with the following file
path prefix depending on the bean type:
Entity Bean: /ejb-jar/enterprise-beans/entity
Session Bean: /ejb-jar/enterprise-beans/session
Message-Driven Bean: /ejb-jar/enterprise-beans/message-driven
WildFly 9
<jbosscmp-jdbc>
...
<entity>
<ejb-name>Student</ejb-name>
<create-table>true</create-table>
<remove-table>true</remove-table>
<table-name>STUDENT</table-name>
...
<sync-on-commit-only>true</sync-on-commit-only>
<insert-after-ejb-post-create>true</insert-after-ejb-post-create>
<call-ejb-store-on-clean>true</call-ejb-store-on-clean>
</entity>
</jbosscmp-jdbc>
This feature is available in JBoss Enterprise Application Platform 6.1. For JBoss Enterprise
Application Platform 6.0.x, it is available as a patch.
WildFly 9
The following table maps the some common weblogic.xml configurations to JBoss
weblogic.xml
JBoss Equivalent
<context-root>MyAppContextRoot</context-root>
<jboss-web>
<context-root>MyAppContextRoot</context-roo
</jboss-web>
WildFly 9
Map roles:
<security-role-assignment>
<security-domain name="FormBasedAuthWebAppPolic
<role-name>TestRole1</role-name>
<principal-name>TestRole1</principal-name>
</security-role-assignment>
<authentication> \\
<login-module code="org.jboss.security.
flag="required">
<module-option name="dsJndiName" va
<module-option name="principalsQuer
PRINCIPLES where principal_id=?"/>
<module-option name="rolesQuery" va
ROLES where
principal_id=?"/>
</login-module>
<login-module code="org.jboss.security.
flag="optional">
<module-option name="rolesPropertie
value="/home/userone/jboss-eap-6.0-GA/standalon
<module-option name="replaceRole" v
</login-module>
</authentication>
</security-domain>
<jboss-web>
<security-domain>java:/jaas/FormBasedAuthWe
</jboss-web>
<session-descriptor>
<session-param>
<param-name>TimeoutSecs</param-name>
<session-config>
<session-timeout>3650</session-timeout>\
</session-config>
<param-value>3650</param-value>
</session-param>
</session-descriptor>
Since the WAR has its own scoped class loader, the
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
WildFly 9
Configure JSPs:
<jsp-descriptor>
<jsp-param>
<param-name>keepgenerated</param-name>
<configuration>
<param-value>true</param-value>
</jsp-param>
<jsp-param>
<jsp-configuration development="true" j
keep-generated="true"/>
</configuration>
<param-name>encoding</param-name>
<param-value>ISO8859_1</param-value>
</jsp-param>
</jsp-descriptor>
<application-param>
<context-param>
<description>
Web application default encoding
</description>
<description>
Web application default encoding
</description>
<param-name>
<param-name>
webapp.encoding.default
</param-name>
<param-value>
webapp.encoding.default
</param-name>
<param-value>
UTF8
</param-value>
</application-param>
UTF8
</param-value>
</context-param>
WildFly 9
<subsystem xmlns="urn:jboss:domain:ee:1.1">
<spec-descriptor-property-replacement>true</spec-descriptor-property-replacement>
<jboss-descriptor-property-replacement>true</jboss-descriptor-property-replacement>
</subsystem>
For more information about property substitution, refer to the Administration and Configuration Guide for
JBoss Enterprise Application Platform 6 located on the Customer Portal at
https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/.
2. Bind Strings for JNDI Runtime Mapping
For values outside deployment descriptors that change depending on the target environment, you can bind
string values into JNDI and them map them into the application.
Assume the application's web.xml file contains the following resource reference:
<resource-env-ref>
<description>IP address of the destination</description>
<resource-env-ref-name>destination/ip-address</resource-env-ref-name>
<resource-env-ref-type>java.lang.String</resource-env-ref-type>
</resource-env-ref>
To bind simple strings into JNDI, create a <simple> element in the naming subsystem of the server
configuration file. The following is an example of the naming subsystem element configured for JNDI
substitution.
WildFly 9
<subsystem xmlns="urn:jboss:domain:naming:1.1">
<bindings>
<simple name="java:/my/jndi/key" value="MyJndiValue"/>
</bindings>
</subsystem>
Add an entry to the application's jboss-web.xml to map the global JNDI entry to the application's
java:comp/env/ Environment Naming Context (ENC). The <resource-env-ref-name> element value must
match the value specified in the web.xml and the <jndi-name> element must match the <simple> element
name in the server configuration file.
<jboss-web>
<resource-env-ref>
<resource-env-ref-name>destination/ip-address</resource-env-ref-name>
<jndi-name>java:/my/jndi/key</jndi-name>
</resource-env-ref>
</jboss-web>
Follow the same procedure to implement property substitution for other descriptor files.
For more information about how to manage the server configuration files, refer to the Administration and
Configuration Guide for JBoss Enterprise Application Platform 6 located on the Customer Portal at
https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/.
WebService.xml
WebLogic Webservice descriptor files
TODO: This section is not complete
*-jms.xml
WebLogic JMS descriptor file
TODO: This section is not complete
weblogic-ejb-jar.xml
WebLogic EJB descriptor
WildFly 9
Security
Replace WebLogic Oracle Wallets
Weblogic administrators use wallets created by Oracle Wallet Manager to manage public key security
credentials on application clients and servers. These wallets must first be converted to standard Java
KeyStore (JKS) entries that can then be used to configure the credentials in JBoss Enterprise Application
Platform 6.
1. Convert Oracle Wallet to JKS
Use the Oracle orapki command-line tool to convert the wallet to standard JKS keystore. Refer to the Oracle
Wallet Manager documentation for details:
http://docs.oracle.com/cd/E16340_01/core.1111/e10105/walletmgr.htm#ASADM10989.
2. Configure JBoss Enterprise Application Platform 6 to Use the Java KeyStore
Java KeyStores are configured in the security subsystem of the server configuration file. The schema is
defined in the file:///JBOSS_INSTALL_DIRECTORY/docs/schema/jboss-as-config_1_4.xsd file. Be sure to
replace JBOSS_INSTALL_DIRECTORY in the previous link with the actual path for your install. For details
on how to configure the server to use keystores, refer to the chapter entitled Securing JBoss Enterprise
Application Platform in the Administration and Configuration Guide for JBoss Enterprise Application Platform
6 located on the Customer Portal at
https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/.
WildFly 9
In JBoss, you instantiate the InitialContext with no argument and then look up the service using the portable
JNDI lookup rules: java:global, java:app, java:module.
This is an example of what the code would look like in JBoss:
WildFly 9
Names in this namespace are shared by all applications deployed in an application server
instance. Use names in this namespace to find remote EJBs. The following is an example of
a java:global namespace:
java:global/jboss-seam-booking/jboss-seam-booking.jar/HotelBookingAction
java:module Names in this namespace are shared by all components in a module, for example, all
enterprise beans in a single EJB module or all components in a web module. The following
is an example of a java:module namespace:
java:module/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking
java:app
Names in this namespace are shared by all components in all modules in a single
application. For example, a WAR and an EJB jar file in the same EAR file would have
access to resources in the java:app namespace.
The following is an example of a java:app namespace:
java:app/jboss-seam-booking.jar/HotelBookingAction
You can find more information about JNDI naming contexts in section EE.5.2.2, "Application Component
Environment Namespaces" in the "JSR 316: JavaTM Platform, Enterprise Edition (Java EE) Specification,
v6". You can download the specification from here: http://jcp.org/en/jsr/detail?id=316
WildFly 9
Programmatic Login
WebLogic provides a proprietary ServletAuthentication class to perform programmatic login. In JBoss
AS 7, you can use the standard Java EE6 Servlet 3.0 HttpServletRequest.login() method to perform
programmatic login or you can define a <security-constraint> element in the web.xml file.
To enable programmatic login, you must replace the WebLogic proprietary code with one of the following:
You can add the following annotations to the Servlet class that performs the authentication.
If you prefer not to use the standard servlet, you can instead add a <security-constraint>
element containing a dummy URL pattern to the web.xml file. This notifies JBoss to create a default
Authenticator. Failure to create a <security-constraint> element in the web.xml file may result
in the error message "No authenticator available for programmatic login".
The following is an example of a web.xml file with a <security-constraint> element:
<login-config>
<auth-method>FORM</auth-method>
<realm-name>ApplicationRealm</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/loginError.jsp</form-error-page>
</form-login-config>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources</web-resource-name>
<description>Protects all resources</description>
<url-pattern>/dummy/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>myRole</role-name>
</auth-constraint>
</security-constraint>
WildFly 9
If the application uses the WebLogic proprietary ServletAuthentication class for programmatic login,
you must replace it with the standard HttpServletRequest login as follows:
WildFly 9
WildFly 9
Resolve ClassCastExceptions Caused by Duplicate JARs
Because JBoss AS 7 ships with a number of classes, or modules, that are commonly used by applications,
packaging these common JARs with your application can result in a ClassCastException. For example, if
you bundle the jstl.jar and standard.jar with the application archive, you may see a ClassCastException
similar to the following:
08:38:01,867 ERROR
[org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/].[MVCUserInterface]]
(http-localhost/127.0.0.1:8080-2)
Servlet.service() for servlet MVCUserInterface threw exception: java.lang.ClassCastException:
javax.servlet.jsp.jstl.fmt.LocalizationContext cannot be cast to java.lang.String at
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<dependencies>
<module name="javax.servlet.jstl.api" slot="main" />
</dependencies>
</deployment>
</jboss-deployment-structure>
3. Search the application archive to find all JAR(s) that are packaged with the application that contain
the class named by the ClassCastException. In this case, the jstl.jar and standard.jar JARs were
packaged in the lib/ folder of the application archive. Remove the duplicate JAR(s) from the
application's packaged WAR or EAR file.
WildFly 9
Resolve ClassCastExceptions and ClassNotFoundExceptions Caused by API Version Differences
If your application uses a version of an API other than the default API included in the main/ module of the
modules/system/layers/base/ directory, you may see a ClassCastException or a ClassNotFoundException
when you run the application.
For example, if your application uses JSF 1.2 instead of the default JSF 2.0, you may see you may see a
ClassCastException or ClassNotFoundException like the following:
In this case, it cannot find the class javax.faces.FacesException due to a mismatch in API versions. The
default JSF module for JBoss AS 7 is version JSF 2.0 and the application is using JSF 1.2. To resolve the
mismatch, you must explicitly include the JSF 1.2 dependency and exclude the JSF 2.0 dependency.
To resolve this issue:
1. Find the JBoss module that contains the class named by the ClassNotFoundException. In this case,
there are 2 modules for the javax.faces.api classes. The default module for JSF 2.0 is located in the
EAP_HOME/modules/system/layers/base/javax/faces/api/main directory and a module for JSF 1.2 is
located in the EAP_HOME/modules/system/layers/base/javax/faces/api/1.2 directory.
2. Explicitly define the dependency on the older JSF 1.2 version in the jboss-deployment-structure.xml
file and exclude the default JSF 2.0 module as follows:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="javax.faces.api" slot="main"/>
<module name="com.sun.jsf-impl" slot="main"/>
</exclusions>
<dependencies>
<module name="javax.faces.api" slot="1.2" export="true"/>
<module name="com.sun.jsf-impl" slot="1.2" export="true"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
3. Search the application archives and remove any jsf-api JARs from the packaged application.
WildFly 9
You have 2 choices:
1. You can migrate your Hibernate 3.x application to use Hibernate 4. This is the recommended
approach.
2. If you do not want to update your application to use Hibernate 4, you can configure your application to
use Hibernate 3.x in one of the following ways:
1. You can package the Hibernate 3 libraries with your application.
2. You can create a custom Hibernate 3 module.
The following sections describe how to do this.
WildFly 9
Migrate Your Hibernate 3.5.x Application to Hibernate 4.x
1. Merge the AnnotationConfiguration into the Configuration
Although AnnotationConfiguration is now deprecated, it should not affect your migration. If you are still
using an hbm.xml file, you should be aware that JBoss AS 7 now uses the
"org.hibernate.cfg.EJB3NamingStrategy" in AnnotationConfiguration instead of the
"org.hibernate.cfg.DefaultNamingStrategy" that was used in previous releases. This can result in
naming mismatches. If you rely on the naming strategy to default the name of an association
(many-to-many and collections of elements) table, you may see this issue. To resolve it, you can tell
Hibernate to use the legacy org.hibernate.cfg.DefaultNamingStrategy by calling
Configuration#setNamingStrategy and passing it
org.hibernate.cfg.DefaultNamingStrategy#INSTANCE.
2. Modify the namespaces to conform to the new Hibernate DTD file names.
Previous DTD Namespace
http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd http://www.hibernate.org/dtd/hibernate-configurati
http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd
http://www.hibernate.org/dtd/hibernate-mapping-3
WildFly 9
Package the Hibernate 3.x JARs with the Application
1. Copy the specific Hibernate 3.x JARs into the application's lib/ directory.
2. Create a jboss-deployment-structure.xml file with the following content to tell the server to
exclude the Hibernate 4 classes:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="org.hibernate"/>
</exclusions>
<deployment>
</jboss-deployment-structure>
In some cases this may result in ClassCastExceptions or other class loading issues due to the
mixed use of the Hibernate versions. If that happens, you need to instruct the server to use only the
Hibernate 3 libraries using the following procedure.
WildFly 9
1. Create a custom module for the Hibernate 3 libraries.
1. Create a directory structure under the JBOSS_HOME/module directory to contain the Hibernate
3 files and JARs. For example:
$ cd JBOSS_HOME/modules/
$ mkdir -p org/hibernate/3
WildFly 9
2. Modify the persistence.xml to use the custom Hibernate module. Set the
"jboss.as.jpa.providerModule" to "org.hibernate:3" as follows:
The Java Persistence API (JPA) deployer will detect the presence of a persistence provider in the
application and use the Hibernate 3 libraries.
3. Create a jboss-deployment-structure.xml file with the following content to tell the server to
use the Hibernate 3 module and exclude the Hibernate 4 libraries:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<dependencies>
<module name="org.hibernate" slot="3"/>
</dependencies>
<exclusions>
<module name="org.hibernate" slot="main"/>
</exclusions>
<deployment>
</jboss-deployment-structure>
WildFly 9
Split Directories
WebLogic supports a split development directory environment. This directory layout contains both source
and build directories. WebLogic uses both directories during deployment to find or generate artifacts. This
model is meant for development purposes only. It is not recommended for production, so it should not impact
your migration.
WildFly 9
WebLogic Method
Description
void
preStart(ApplicationLifecycleEvent
evt)
initialization.
void
postStart(ApplicationLifecycleEvent
initialization.
evt)
void
preStop(ApplicationLifecycleEvent
evt)
void
postStop(ApplicationLifecycleEvent
evt)
WildFly 9
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent evt)
ServletContext ctx = evt.getServletContext();
WildFly 9
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
@Startup
@Singleton
public class StartupBean
{
@PostConstruct
void startup() {
System.out.println("startup()", "@PostContruct called");
}
@PreDestroy
void shutdown() {
System.out.println("shutdown()", "@PreDestroy called");
}
}
@WLServlet
@WebServlet
javax.servlet.annotation.WebServlet
@WLFilter
@WebFilter
javax.servlet.annotation.WebFilter
@WLInitParam @WebInitParam
javax.servlet.annotation.WebParam
Be sure to modify the attributes for the annotations to conform to the standard attribute names. Details about
the attributes are listed below. For more information on the Java EE 6 servlet annotations, see the
javax.servlet.annotation javadoc .
You must also remove the WebLogic imports and JAR.
WildFly 9
WebLogic
Java EE 6 Equivalent
Description / Comments
String displayName
String description
String description
Servlet description
String icon
String smallicon
-or-String largeicon
String name
String name
WLInitParam[]
initParams
WebInitParam[]
initParams
int loadOnStartup
int loadOnStartup
String runAs
No equivalent attribute
The run-as User for the Servlet. There are 3 options for
Attribute Name
String
displayName
String[] urlPatterns or
String[] value
import weblogic.servlet.annotation.WLServlet;
@WLServlet (
name = "catalog",
runAs = "SuperEditor"
initParams = {
@WLInitParam (name="catalog", value="spring"),
@WLInitParam (name="language", value="English")
},
mapping = {"/catalog/*"}
)
public class MyCatalogServlet extends HttpServlet { . . . }
Here is the equivalent code that uses the standard @WebServlet annotation:
WildFly 9
import javax.annotation.security.RunAs;
import javax.servlet.annotation.WebServlet;
@WebServlet (
name = "catalog",
initParams = {
@WebInitParam (name="catalog", value="spring"),
@WLInitParam (name="language", value="English")
},
urlPatterns = "/catalog/*"
)
@RunAs("SuperEditor")
public class MyCatalogServlet extends HttpServlet { . . . }
Java EE 6 Equivalent
Description / Comments
String displayName
String displayName
String description
String description
Servlet description
String icon
String name
String name
WLInitParam[]
initParams
WebInitParam[] initParams
String[] mapping
value
No equivalent attribute
DispatcherTypes[]
dispatcherTypes
No equivalent attribute
String[] servletNames
WildFly 9
import weblogic.servlet.annotation.WLFilter;
import weblogic.servlet.annotation.WLInitParam;
@WLFilter (
name = "catalogFilter",
initParams = { @WLInitParam(name="catalog", value="winter") }
mapping = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
Here is the equivalent code that uses the standard @WebFilter annotation:
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
@WebFilter (
filterName = "catalogFilter",
initParams = { @WebInitParam(name="catalog", value="winter") }
urlPatterns = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
WildFly 9
String name
String value
String value
No equivalent attribute
String description
import weblogic.servlet.annotation.WLFilter;
import weblogic.servlet.annotation.WLInitParam;
@WLFilter (
name = "catalogFilter",
initParams = { @WLInitParam(name="catalog", value="winter") }
mapping = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
Here is the equivalent code that uses the standard @WebInitParam annotation:
import javax.servlet.annotation.WebFilter;
import avax.servlet.annotation.WebInitParam;
@WebFilter (
filterName = "catalogFilter",
initParams = { @WebInitParam(name="catalog", value="winter", description="winter catalog") }
urlPatterns = {"/catalog/*"}
)
public class MyFilter implements Filter { . . . }
WildFly 9
Frameworks
Portal
Rules Engine
Workflow
ESB
LDAP
Requirements for High-Availablity, Clusting, Failover, Caching
Third-party Libraries
External Systems
WebLogic Proprietary Libraries and APIs
Examine the Current Build Process
Consider conversion to Maven
WildFly 9
Data Migration
Database
LDAP
JMS
WildFly 9
WildFly 9
As can be seen, we have a simple @Stateless EJB. When the deployment containing this class is being
processed, the EJB deployment processor will see that the deployment contains a class with the @Stateless
annotation and thus identifies this as a EJB deployment. This is just one of the several ways, various
deployment processors can identify a deployment of some specific type. The EJB deployment
processor will then add an implicit dependency on the Java EE API module, so that all the Java EE API
classes are visible to the deployment.
Some subsystems will always add a API classes, even if the trigger condition is not met. These are
listed separately below.
In the next section, we'll list down the implicit module dependencies that are added to a deployment, by
various deployers within WildFly.
for adding
the implicit
dependency
Core Server
javax.api
sun.jdk
org.jboss.vfs
WildFly 9
EE
Subsystem
javaee.api
EJB3
javaee.api
subsystem
JAX-RS
(Resteasy)
subsystem
javax.xml.bind.api
org.jboss.resteasy.resteasy-atom-provider
org.jboss.resteasy.resteasy-cdi
org.jboss.resteasy.resteasy-jaxrs
org.jboss.resteasy.resteasy-jaxb-provider
org.jboss.resteasy.resteasy-jackson-provider
org.jboss.resteasy.resteasy-jsapi
org.jboss.resteasy.resteasy-multipart-provider
org.jboss.resteasy.async-http-servlet-30
JCA
sub-system
javax.resource.api
javax.jms.api
javax.validation.api
org.jboss.logging
org.jboss.ironjacamar.api
org.jboss.ironjacamar.impl
org.hibernate.validator
JPA
(Hibernate)
javax.persistence.api
subsystem
javaee.api
org.jboss.as.jpa
org.hibernate
WildFly 9
Logging
Subsystem
org.jboss.logging
org.apache.commons.logging
org.apache.log4j
org.slf4j
org.jboss.logging.jul-to-slf4j-stub
SAR
Subsystem
Security
Subsystem
org.jboss.logging
org.jboss.modules
org.picketbox
Web
Subsystem
javaee.api
com.sun.jsf-impl
org.hibernate.validator
org.jboss.as.web
org.jboss.logging
Web
Services
Subsystem
org.jboss.ws.api
org.jboss.ws.spi
Weld (CDI)
Subsystem
javax.persistence.api
javaee.api
org.javassist
org.jboss.interceptor
org.jboss.as.weld
org.jboss.logging
org.jboss.weld.core
org.jboss.weld.api
org.jboss.weld.spi
WildFly 9
@ApplicationPath("/mypath")
public class MyApplication extends Application {
}
<servlet-mapping>
<servlet-name>com.acme.MyApplication</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
You can also use this approach to override an application path set with the @ApplicationPath
annotation.
WildFly 9
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/hello/*</url-pattern>
</servlet-mapping>
Note that you only have to add the mapping, not the corresponding servlet. The server is
responsible for adding the corresponding servlet automatically.
WildFly 9
WildFly 9
java:jboss
java:/
Only entries within the java:jboss/exported context are accessible over remote JNDI.
For web deployments java:comp is aliased to java:module, so EJB's deployed in a war do not
have their own comp namespace.
<web-app 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-app_3_1.xsd"
version="3.1">
<env-entry>
<env-entry-name>java:global/mystring</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello World</env-entry-value>
</env-entry>
<env-entry>
<env-entry-name>hello</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello Module</env-entry-value>
</env-entry>
</web-app>
WildFly 9
Programatically
Java EE Applications
Standard Java EE applications may use the standard JNDI API, included with Java SE, to bind entries in the
global namespaces (the standard java:comp, java:module and java:app namespaces are read-only,
as mandated by the Java EE Platform Specification).
There is no need to unbind entries created programatically, since WildFly tracks which bindings
belong to a deployment, and the bindings are automatically removed when the deployment is
undeployed.
The ServiceTarget removes the bind when uninstalled, thus using one out of the module/extension
domain usage should be avoided, unless entries are removed using unbind().
WildFly 9
/subsystem=naming/binding=java\:global\/mybinding:add(binding-type=simple, type=long,
value=1000)
WildFly's Administrator Guide includes a section describing in detail the Naming subsystem
configuration.
WildFly 9
@Resource(lookup = "java:global/mystring")
private String myString;
@Resource(name = "hello")
private String hello;
@Resource
ManagedExecutorService executor;
Note that @Resource is more than a JNDI lookup, it also binds an entry in the component's JNDI
environment. The new bind JNDI name is defined by @Resource's name attribute, which value, if
unspecified, is the Java type concatenated with / and the field's name, for instance
java.lang.String/myString. More, similar to when using deployment descriptors to bind JNDI entries.
unless the name is an absolute JNDI name, it is considered relative to java:comp/env. For instance, with
respect to the field named myString above, the @Resource's lookup attribute instructs WildFly to lookup
the value in java:global/mystring, bind it in java:comp/env/java.lang.String/myString, and
then inject such value into the field.
With respect to the field named hello, there is no lookup attribute value defined, so the responsibility to
provide the entry's value is delegated to the deployment descriptor. Considering that the deployment
descriptor was the web.xml previously shown, which defines an environment entry with same hello name,
then WildFly inject the valued defined in the deployment descriptor into the field.
The executor field has no attributes specified, so the bind's name would default to
java:comp/env/javax.enterprise.concurrent.ManagedExecutorService/executor, but
there is no such entry in the deployment descriptor, and when that happens it's up to WildFly to provide a
default value or null, depending on the field's Java type. In this particular case WildFly would inject the
default instance of a managed executor service, the value in
java:comp/DefaultManagedExecutorService, as mandated by the EE Concurrency Utilities 1.0
Specification (JSR 236).
WildFly 9
or simply
remote:
The remote: protocol uses the WildFly remoting protocol to lookup items from the servers local JNDI. To
use it, you must have the appropriate jars on the class path, if you are maven user can be done simply by
adding the following to your pom.xml:
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>8.0.0.Final</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
If you are not using maven a shaded jar that contains all required classes
can be found in the bin/client directory of WildFly's distribution.
WildFly 9
ejb:
The ejb: namespace is provided by the jboss-ejb-client library. This protocol allows you to look up EJB's,
using their application name, module name, ejb name and interface type.
This is a client side JNDI implementation. Instead of looking up an EJB on the server the lookup name
contains enough information for the client side library to generate a proxy with the EJB information. When
you invoke a method on this proxy it will use the current EJB client context to perform the invocation. If the
current context does not have a connection to a server with the specified EJB deployed then an error will
occur. Using this protocol it is possible to look up EJB's that do not actually exist, and no error will be thrown
until the proxy is actually used. The exception to this is stateful session beans, which need to connect to a
server when they are created in order to create the session bean instance on the server.
Some examples are:
ejb:myapp/myejbjar/MyEjbName!com.test.MyRemoteInterface
ejb:myapp/myejbjar/MyStatefulName!comp.test.MyStatefulRemoteInterface?stateful
The first example is a lookup of a singleton, stateless or EJB 2.x home interface. This lookup will not hit the
server, instead a proxy will be generated for the remote interface specified in the name. The second
example is for a stateful session bean, in this case the JNDI lookup will hit the server, in order to tell the
server to create the SFSB session.
For more details on how the server connections are configured, please see EJB invocations from a remote
client using JNDI.
Only entries within the java:jboss/exported context are accessible over remote JNDI.
For web deployments java:comp is aliased to java:module, so EJB's deployed in a war do not
have their own comp namespace.
WildFly 9
<web-app 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-app_3_1.xsd"
version="3.1">
<env-entry>
<env-entry-name>java:global/mystring</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello World</env-entry-value>
</env-entry>
<env-entry>
<env-entry-name>hello</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Hello Module</env-entry-value>
</env-entry>
</web-app>
WildFly 9
Programatically
Java EE Applications
Standard Java EE applications may use the standard JNDI API, included with Java SE, to bind entries in the
global namespaces (the standard java:comp, java:module and java:app namespaces are read-only,
as mandated by the Java EE Platform Specification).
There is no need to unbind entries created programatically, since WildFly tracks which bindings
belong to a deployment, and the bindings are automatically removed when the deployment is
undeployed.
The ServiceTarget removes the bind when uninstalled, thus using one out of the module/extension
domain usage should be avoided, unless entries are removed using unbind().
WildFly 9
/subsystem=naming/binding=java\:global\/mybinding:add(binding-type=simple, type=long,
value=1000)
WildFly's Administrator Guide includes a section describing in detail the Naming subsystem
configuration.
WildFly 9
@Resource(lookup = "java:global/mystring")
private String myString;
@Resource(name = "hello")
private String hello;
@Resource
ManagedExecutorService executor;
Note that @Resource is more than a JNDI lookup, it also binds an entry in the component's JNDI
environment. The new bind JNDI name is defined by @Resource's name attribute, which value, if
unspecified, is the Java type concatenated with / and the field's name, for instance
java.lang.String/myString. More, similar to when using deployment descriptors to bind JNDI entries.
unless the name is an absolute JNDI name, it is considered relative to java:comp/env. For instance, with
respect to the field named myString above, the @Resource's lookup attribute instructs WildFly to lookup
the value in java:global/mystring, bind it in java:comp/env/java.lang.String/myString, and
then inject such value into the field.
With respect to the field named hello, there is no lookup attribute value defined, so the responsibility to
provide the entry's value is delegated to the deployment descriptor. Considering that the deployment
descriptor was the web.xml previously shown, which defines an environment entry with same hello name,
then WildFly inject the valued defined in the deployment descriptor into the field.
The executor field has no attributes specified, so the bind's name would default to
java:comp/env/javax.enterprise.concurrent.ManagedExecutorService/executor, but
there is no such entry in the deployment descriptor, and when that happens it's up to WildFly to provide a
default value or null, depending on the field's Java type. In this particular case WildFly would inject the
default instance of a managed executor service, the value in
java:comp/DefaultManagedExecutorService, as mandated by the EE Concurrency Utilities 1.0
Specification (JSR 236).
WildFly 9
or simply
remote:
The remote: protocol uses the WildFly remoting protocol to lookup items from the servers local JNDI. To
use it, you must have the appropriate jars on the class path, if you are maven user can be done simply by
adding the following to your pom.xml:
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>8.0.0.Final</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
If you are not using maven a shaded jar that contains all required classes
can be found in the bin/client directory of WildFly's distribution.
WildFly 9
ejb:
The ejb: namespace is provided by the jboss-ejb-client library. This protocol allows you to look up EJB's,
using their application name, module name, ejb name and interface type.
This is a client side JNDI implementation. Instead of looking up an EJB on the server the lookup name
contains enough information for the client side library to generate a proxy with the EJB information. When
you invoke a method on this proxy it will use the current EJB client context to perform the invocation. If the
current context does not have a connection to a server with the specified EJB deployed then an error will
occur. Using this protocol it is possible to look up EJB's that do not actually exist, and no error will be thrown
until the proxy is actually used. The exception to this is stateful session beans, which need to connect to a
server when they are created in order to create the session bean instance on the server.
Some examples are:
ejb:myapp/myejbjar/MyEjbName!com.test.MyRemoteInterface
ejb:myapp/myejbjar/MyStatefulName!comp.test.MyStatefulRemoteInterface?stateful
The first example is a lookup of a singleton, stateless or EJB 2.x home interface. This lookup will not hit the
server, instead a proxy will be generated for the remote interface specified in the name. The second
example is for a stateful session bean, in this case the JNDI lookup will hit the server, in order to tell the
server to create the SFSB session.
For more details on how the server connections are configured, please see EJB invocations from a remote
client using JNDI.
WildFly 9
http-remoting:
The http-remoting: protocol implementation is provided by JBoss Remote Naming project, and uses http
upgrade to lookup items from the servers local JNDI. To use it, you must have the appropriate jars on the
class path, if you are maven user can be done simply by adding the following to your pom.xml
dependencies:
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>8.0.0.Final</version>
<type>pom</type>
</dependency>
If you are not using maven a shaded jar that contains all required classes
can be found in the bin/client directory of WildFly's distribution.
The http-remoting client assumes JNDI names in remote lookups are relative to
java:jboss/exported namespace, a lookup of an absolute JNDI name will fail.
WildFly 9
ejb:
The ejb: namespace implementation is provided by the jboss-ejb-client library, and allows the lookup of
EJB's using their application name, module name, ejb name and interface type. To use it, you must have the
appropriate jars on the class path, if you are maven user can be done simply by adding the following to your
pom.xml dependencies:
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>8.0.0.Final</version>
<type>pom</type>
</dependency>
If you are not using maven a shaded jar that contains all required classes
can be found in the bin/client directory of WildFly's distribution.
This is a client side JNDI implementation. Instead of looking up an EJB on the server the lookup name
contains enough information for the client side library to generate a proxy with the EJB information. When
you invoke a method on this proxy it will use the current EJB client context to perform the invocation. If the
current context does not have a connection to a server with the specified EJB deployed then an error will
occur. Using this protocol it is possible to look up EJB's that do not actually exist, and no error will be thrown
until the proxy is actually used. The exception to this is stateful session beans, which need to connect to a
server when they are created in order to create the session bean instance on the server.
The first example is a lookup of a singleton, stateless or EJB 2.x home interface. This lookup will not hit the
server, instead a proxy will be generated for the remote interface specified in the name. The second
example is for a stateful session bean, in this case the JNDI lookup will hit the server, in order to tell the
server to create the SFSB session.
For more details on how the server connections are configured, including the required jboss ejb
client setup, please see EJB invocations from a remote client using JNDI.
WildFly 9
WildFly 9
6.29.1 Introduction
The WildFly 8 JPA subsystem implements the JPA 2.0 container-managed requirements. Deploys the
persistence unit definitions, the persistence unit/context annotations and persistence unit/context references
in the deployment descriptor. JPA Applications use the Hibernate (core) 4.0 persistence provider, that is
included with WildFly. The JPA subsystem uses the standard SPI
(javax.persistence.spi.PersistenceProvider) to access the Hibernate persistence provider and some
additional extensions as well.
During application deployment, JPA use is detected (e.g. persistence.xml or @PersistenceContext/Unit
annotations) and injects Hibernate dependencies into the application deployment. This makes it easy to
deploy JPA applications.
In the remainder of this documentation, entity manager refers to an instance of the
javax.persistence.EntityManager class. Javadoc for the JPA interfaces
http://download.oracle.com/javaee/6/api/javax/persistence/package-summary.html and JPA 2.0 specification.
The index of Hibernate documentationis here.
WildFly 9
WildFly 9
return customer;
// return Customer entity (will be detached from the persistence
context when caller gets control)
} // Transaction.commit will be called, Customer entity will be persisted to the database and
"customerPU" persistence context closed
WildFly 9
By default, the current stateful session bean being created, will ( deeply) inherit the extended persistence
context from any stateful session bean executing in the current Java thread. The deep inheritance of
extended persistence context includes walking multiple levels up the stateful bean call stack (inheriting from
parent beans). The deep inheritance of extended persistence context includes sibling beans. For example,
parentA references child beans beanBwithXPC & beanCwithXPC. Even though parentA doesn't have an
extended persistence context, beanBwithXPC & beanCwithXPC will share the same extended persistence
context.
Some other EE application servers, use shallow inheritance, where stateful session bean only inherit from
the parent stateful session bean (if there is a parent bean). Sibling beans do not share the same extended
persistence context unless their (common) parent bean also has the same extended persistence context.
Applications can include a (top-level) jboss-all.xml deployment descriptor that specifies either the (default)
DEEP extended persistence context inheritance or SHALLOW.
The AS/docs/schema/jboss-jpa_1_0.xsd describes the jboss-jpa deployment descriptor that may be
included in the jboss-all.xml. Below is an example of using SHALLOW extended persistence context
inheritance:
<jboss>
<jboss-jpa xmlns="http://www.jboss.com/xml/ns/javaee">
<extended-persistence inheritance="SHALLOW"/>
</jboss-jpa>
</jboss>
Below is an example of using DEEP extended persistence inheritance:
<jboss>
<jboss-jpa xmlns="http://www.jboss.com/xml/ns/javaee">
<extended-persistence inheritance="DEEP"/>
</jboss-jpa>
</jboss>
The AS console/cli can change the default extended persistence context setting (DEEP or SHALLOW). The
following cli commands will read the current JPA settings and enable SHALLOW extended persistence
context inheritance for applications that do not include the jboss-jpa deployment descriptor:
WildFly 9
./jboss-cli.sh
cd subsystem=jpa
:read-resource
:write-attribute(name=default-extended-persistence-inheritance,value="SHALLOW")
6.29.9 Entities
JPA 2.0 makes it easy to use your (pojo) plain old Java class to represent a database table row.
WildFly 9
6.29.10 Deployment
The persistence.xml contains the persistence unit configuration (e.g. datasource name) and as described in
the JPA 2.0 spec (section 8.2), the jar file or directory whose META-INF directory contains the
persistence.xml file is termed the root of the persistence unit. In Java EE environments, the root of a
persistence unit must be one of the following (quoted directly from the JPA 2.0 specification):
"
an EJB-JAR file
the WEB-INF/classes directory of a WAR file
a jar file in the WEB-INF/lib directory of a WAR file
a jar file in the EAR library directory
an application client jar file
The persistence.xml can specify either a JTA datasource or a non-JTA datasource. The JTA datasource is
expected to be used within the EE environment (even when reading data without an active transaction). If a
datasource is not specified, the default-datasource will instead be used (must be configured).
NOTE: Java Persistence 1.0 supported use of a jar file in the root of the EAR as the root of a persistence
unit. This use is no longer supported. Portable applications should use the EAR library directory for this case
instead.
"
Question: Can you have a EAR/META-INF/persistence.xml?
Answer: No, the above may deploy but it could include other archives also in the EAR, so you may have
deployment issues for other reasons. Better to put the persistence.xml in an EAR/lib/somePuJar.jar.
6.29.11 Troubleshooting
The org.jboss.as.jpa logging can be enabled to get the following information:
INFO - when persistence.xml has been parsed, starting of persistence unit service (per deployed
persistence.xml), stopping of persistence unit service
DEBUG - informs about entity managers being injected, creating/reusing transaction scoped entity
manager for active transaction
TRACE - shows how long each entity manager operation took in milliseconds, application searches
for a persistence unit, parsing of persistence.xml
To enable TRACE, open the as/standalone/configuration/standalone.xml (or
as/domain/configuration/domain.xml) file. Search for <subsystem
xmlns="urn:jboss:domain:logging:1.0"> and add the org.jboss.as.jpa category. You need to change
the console-handler level from INFO to TRACE.
WildFly 9
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE">
<level name="TRACE" />
...
</console-handler>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN" />
</logger>
<logger category="org.jboss.as.jpa">
<level name="TRACE" />
</logger>
<logger category="org.apache.tomcat.util.modeler">
<level name="WARN" />
</logger>
...
To see what is going on at the JDBC level, enable jboss.jdbc.spy TRACE and add spy="true" to the
datasource.
To troubleshoot issues with the Hibernate second level cache, try enabling trace for org.hibernate.SQL +
org.hibernate.cache.infinispan + org.infinispan:
WildFly 9
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE">
<level name="TRACE" />
...
</console-handler>
</periodic-rotating-file-handler>
<logger category="com.arjuna">
<level name="WARN" />
</logger>
<logger category="org.hibernate.SQL">
<level name="TRACE" />
</logger>
<logger category="org.hibernate">
<level name="TRACE" />
</logger>
<logger category="org.infinispan">
<level name="TRACE" />
</logger>
<logger category="org.apache.tomcat.util.modeler">
<level name="WARN" />
</logger>
...
WildFly 9
Artifact ID
Version
8.1.0.Final
8.1.0.Final
org.jipijapa jipijapa-hibernate3
1.1.0.Final
EclipseLink
8.1.0.Final
org.jipijapa jipijapa-eclipselink
1.1.0.Final
OpenJPA
8.1.0.Final
org.jipijapa jipijapa-openjpa
1.1.0.Final
WildFly 9
Here is an example of enabling the second level cache for a Hibernate native API hibernate.cfg.xml file:
<property name="hibernate.cache.region.factory_class"
value="org.jboss.as.jpa.hibernate4.infinispan.InfinispanRegionFactory"/>
<property name="hibernate.cache.infinispan.cachemanager"
value="java:jboss/infinispan/container/hibernate"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
Dependencies: org.infinispan,org.hibernate
Infinispan Hibernate/JPA second level cache provider documentation contains advanced configuration
information but you should bear in mind that when Hibernate runs within WildFly 8, some of those
configuration options, such as region factory, are not needed. Moreover, the application server providers you
with option of selecting a different cache container for Infinispan via hibernate.cache.infinispan.container
persistence property. To reiterate, this property is not mandatory and a default container is already deployed
for by the application server to host the second level cache.
WildFly 9
WildFly 9
The WildFly testsuite contains a test that packages jars from the Hibernate 3.6.5.Final jars in the ear lib.
WildFly 9
1. In a command shell, go to the AS installation and change into the modules/org folder.
cd WF\modules\modules\system\layers\base\org\hibernate\3
2. Copy the Hibernate3 jars into this folder
(hibernate3-core.jar, hibernate3-commons-annotations.jar, hibernate3-entitymanager.jar needed for
Hibernate 3.x).
3. Update the module.xml file to name each jar you copied in as a "resource-root":
-->
<resource-root path="jipijapa-hibernate3-1.0.1.Final.jar"/>
<resource-root path="hibernate3-core.jar"/>
<resource-root path="hibernate3-commons-annotations.jar"/>
<resource-root path="hibernate3-entitymanager.jar"/>
</resources>
<dependencies>
<module name="asm.asm"/>
<module name="javax.api"/>
<module name="javax.annotation.api"/>
<module name="javax.enterprise.api"/>
<module name="javax.persistence.api"/>
<module name="javax.transaction.api"/>
<module name="javax.validation.api"/>
<module name="javax.xml.bind.api"/>
<module name="org.antlr"/>
<module name="org.apache.commons.collections"/>
<module name="org.dom4j"/>
<module name="org.javassist"/>
<module name="org.jboss.as.jpa.spi"/>
<module name="org.jboss.jandex"/>
<module name="org.jboss.logging"/>
<module name="org.slf4j"/>
<module name="org.jboss.vfs"/>
</dependencies>
</module>
1.
In your persistence.xml, you will refer to the Hibernate 3 persistence provider as follows:
WildFly 9
WildFly 9
<filter>
</resource-root>
</resources>
<dependencies>
<module name="asm.asm"/>
<module name="javax.api"/>
<module name="javax.annotation.api"/>
<module name="javax.enterprise.api"/>
<module name="javax.persistence.api"/>
<module name="javax.transaction.api"/>
<module name="javax.validation.api"/>
<module name="javax.xml.bind.api"/>
<module name="org.antlr"/>
<module name="org.apache.commons.collections"/>
<module name="org.dom4j"/>
<module name="org.javassist"/>
<module name="org.jboss.as.jpa.spi"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.vfs"/>
</dependencies>
</module>
jboss-cli.sh --connect
'/system-property=eclipselink.archive.factory:add(value=org.jipijapa.eclipselink.JBossArchiveFactoryImpl)'
. The following shows what the standalone.xml (or your WildFly configuration you are using) file might look
like after updating the system properties:
WildFly 9
<system-properties>
...
<property name="eclipselink.archive.factory"
value="org.jipijapa.eclipselink.JBossArchiveFactoryImpl"/>
</system-properties>
You should then be able to deploy applications with persistence.xml that include;
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
Also refer to page how to use EclipseLink with WildFly guide here.
WildFly 9
The AS7/modules/org/hibernate/ogm folder should contain the OGM jars and the following module.xml:
WildFly 9
Manifest-Version: 1.0
...
Dependencies: org.hibernate
If you use the Hibernate native api in your application and also use the JPA api to access the same entities
(from the same Hibernate session/EntityManager), you could get surprising results (e.g.
HibernateSession.saveOrUpdate(entity) is different than EntityManager.merge(entity). Each entity should be
managed by either Hibernate native API or JPA code.
import org.hibernate.Session;
import org.hibernate.SessionFactory;
@Stateful public class MyStatefulBean ... {
@PersistenceContext(unitName="crm") Session session1;
@PersistenceContext(unitName="crm2", type=EXTENDED) Session extendedpc;
@PersistenceUnit(unitName="crm") SessionFactory factory;
}
WildFly 9
Property
Purpose
hibernate.id.new_generator_mappings =true
hibernate.ejb.resource_scanner = instance of
org.hibernate.ejb.packaging.Scanner interface
hibernate.session_factory_name_is_jndi =
false
hibernate.ejb.entitymanager_factory_name
= qualified persistence unit name
WildFly 9
Purpose
jboss.as.jpa.providerModule
jboss.as.jpa.adapterModule
name of the integration classes that help WildFly to work with the
persistence provider. Current valid values are
org.jboss.as.jpa.hibernate:4 (Hibernate 4 integration classes) and
org.jboss.as.jpa.hibernate:3 (Hibernate 3 integration classes). Other
integration adapter modules are expected to be added.
jboss.as.jpa.adapterClass
jboss.as.jpa.managed
jboss.as.jpa.classtransformer
set to false to disable class transformers for the persistence unit. The
default is true, which allows class enhancing/rewriting. Hibernate also
needs persistence unit property hibernate.ejb.use_class_enhancer
to be true, for class enhancing to be enabled.
wildfly.jpa.default-unit
wildfly.jpa.twophasebootstrap
WildFly 9
wildfly.jpa.allowdefaultdatasourceuse set to false to prevent persistence unit from using the default data
source. Defaults to true. This is only important for persistence units
that do not specify a datasource.
jboss.as.jpa.deferdetach
Module name
blank
org.hibernate
org.hibernate.ejb.HibernatePersistence
org.hibernate
org.hibernate.ogm.jpa.HibernateOgmPersistence
org.hibernate:ogm
oracle.toplink.essentials.PersistenceProvider
oracle.toplink
oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
oracle.toplink
org.eclipse.persistence.jpa.PersistenceProvider
org.eclipse.persistence
org.datanucleus.api.jpa.PersistenceProviderImpl
org.datanucleus
org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider org.datanucleus:appengine
org.apache.openjpa.persistence.PersistenceProviderImpl
org.apache.openjpa
WildFly 9
As a reminder, a
@Stateful
public class ExampleSFSB {
public void createSomeEntityWithTransactionScopedEM(String name) {
Context context = new InitialContext();
javax.persistence.EntityManager entityManager = (javax.persistence.EntityManager)
context.lookup("java:/myEntityManager");
SomeEntity someEntity = new SomeEntity();
someEntity.setName(name);
entityManager.persist(name);
}
}
WildFly 9
6.29.30 Community
Many thanks to the community, for reporting issues, solutions and code changes. A number of people have
been answering Wildfly forum questions related to JPA usage. I would like to thank them for this, as well as
those reporting issues. For those of you that haven't downloaded the AS source code and started hacking
patches together. I would like to encourage you to start by reading Hacking on WildFly. You will find that it
easy very easy to find your way around the WildFly/JPA/* source tree and make changes. Also, new for
WildFly, is the JipiJapa project that contains additional integration code that makes EE JPA application
deployments work better. The following list of contributors should grow over time, I hope to see more of you
listed here.
6.30 OSGi
WildFly does not include support for OSGi, such functionality is now responsibility of JBoss OSGi project.
WildFly 9
6.31.2 History
Previous versions of JBoss AS (versions < WildFly 8) used JNP project (
http://anonsvn.jboss.org/repos/jbossas/projects/naming/) as the JNDI naming implementation. Developers of
client applications of previous versions of JBoss AS will be familiar with the jnp:// PROVIDER_URL URL
they used to use in their applications for communicating with the JNDI server on the JBoss server.
Starting WildFly 8, the JNP project is not used. Neither on the server side nor on the client side. The client
side of the JNP project has now been replaced by jboss-remote-naming project (
https://github.com/jbossas/jboss-remote-naming). There were various reasons why the JNP client was
replaced by jboss-remote-naming project. One of them was the JNP project did not allow fine grained
security configurations while communicating with the JNDI server. The jboss-remote-naming project is
backed by the jboss-remoting project (https://github.com/jboss-remoting/jboss-remoting) which allows much
more and better control over security.
6.31.3 Overview
Now that we know that for remote client JNDI communication with WildFly 8 requires jboss-remote-naming
project, let's quickly see what the code looks like.
As you can see, there's not much here in terms of code. We first create a InitialContext (
http://download.oracle.com/javase/6/docs/api/javax/naming/InitialContext.html) which as per the API will look
for a jndi.properties in the classpath of the application. We'll see what our jndi.properties looks like, later.
Once the InitialContext is created, we just use it to do a lookup on a JNDI name which we know is bound on
the server side. We'll come back to the details of this lookup string in a while.
Let's now see what the jndi.properties in our client classpath looks like:
java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory
java.naming.provider.url=http-remoting://localhost:8080
WildFly 9
Those 2 properties are important for jboss-remote-naming project to be used for communicating with the
WildFly server. The first property tells the JNDI API which initial context factory to use. In this case we are
pointing it to the InitailContextFactory class supplied by the jboss-remote-naming project. The other property
is the PROVIDER_URL. Developers familiar with previous JBoss AS versions would remember that they
used jnp://localhost:1099 (just an example). In WildFly, the URI protocol scheme for
jboss-remote-naming project is remote://. The rest of the PROVIDER_URL part is the server hostname or
IP and the port on which the remoting connector is exposed on the server side. By default the http-remoting
connector port in WildFly 8 is 8080. That's what we have used in our example. The hostname we have used
is localhost but that should point to the server IP or hostname where the server is running.
JNP client project in previous AS versions allowed a comma separated list for PROVIDER_URL
value, so that if one of the server isn't accessible then the JNDI API would use the next available
server. The jboss-remote-naming project has similar support starting 1.0.3.Final version of that
project (which is available in a WildFly release after 7.1.1.Final).
WildFly 8 can use the PROVIDER_URL like:
java.naming.provider.url=http-remoting://server1:8080,http-remoting://server2:8080
So we saw how to setup the JNDI properties in the jndi.properties file. The JNDI API also allows you to pass
these properties to the constructor of the InitialContext class (please check the javadoc of that class for more
details). Let's quickly see what the code would look like:
void doLookup() {
Properties jndiProps = new Properties();
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFactory");
jndiProps.put(Context.PROVIDER_URL,"http-remoting://localhost:8080");
// create a context passing these properties
Context ctx = new InitialContext(jndiProps);
// lookup
ctx.lookup("foo/bar");
...
}
That's it! You can see that the values that we pass to those properties are the same as what we did via the
jndi.properties. It's upto the client application to decide which approach they want to follow.
WildFly 9
Like previously mentioned, remote-naming internally uses jboss-remoting project. When the client code
creates an InitialContext backed by the org.jboss.naming.remote.client.InitialContextFactory class, the
org.jboss.naming.remote.client.InitialContextFactory internally looks for the
PROVIDER_URL (and other) properties that are applicable for that context ( doesn't matter whether it comes
from the jndi.properties file or whether passed explicitly to the constructor of the InitialContext). Once it
identifies the server and port to connect to, the remote-naming project internally sets up a connection using
the jboss-remoting APIs with the remoting connector which is exposed on that port.
We previously mentioned that remote-naming, backed by jboss-remoting project, has increased support for
security configurations. Starting WildFly 8, every service including the http remoting connector (which listens
by default on port 8080), is secured (see
https://community.jboss.org/wiki/AS710Beta1-SecurityEnabledByDefault for details). This means that when
trying to do JNDI operations like a lookup, the client has to pass appropriate user credentials. In our
examples so far we haven't passed any username/pass or any other credentials while creating the
InitialContext. That was just to keep the examples simple. But let's now take the code a step further and see
one of the ways how we pass the user credentials. Let's at the moment just assume that the remoting
connector on port 8080 is accessible to a user named "peter" whose password is expected to be "lois".
Note: The server side configurations for the remoting connector to allow "peter" to access the
connector, is out of the scope of this documentation. The WildFly 8 documentation already has
chapters on how to set that up.
void doLookup() {
Properties jndiProps = new Properties();
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFactory");
jndiProps.put(Context.PROVIDER_URL,"http-remoting://localhost:8080");
// username
jndiProps.put(Context.SECURITY_PRINCIPAL, "peter");
// password
jndiProps.put(Context.SECURITY_CREDENTIALS, "lois");
// create a context passing these properties
Context ctx = new InitialContext(jndiProps);
// lookup
ctx.lookup("foo/bar");
...
}
WildFly 9
The code is similar to our previous example, except that we now have added 2 additional properties that are
passed to the InitialContext constructor. The first is
http://docs.oracle.com/javase/6/docs/api/javax/naming/Context.html#SECURITY_PRINCIPAL which passes
the username (peter in this case) and the second is
http://docs.oracle.com/javase/6/docs/api/javax/naming/Context.html#SECURITY_CREDENTIALS which
passes the password (lois in this case). Of course the same properties can be configured in the
jndi.properties file (read the javadoc of the Context class for appropriate properties to be used in the
jndi.properties). This is one way of passing the security credentials for JNDI communication with WildFly.
There are some other ways to do this too. But we won't go into those details here for two reasons. One, it's
outside the scope of this article and two (which is kind of the real reason) I haven't looked fully at the
remote-naming implementation details to see what other ways are allowed.
WildFly 9
Note: Since the JNDI name that you use on the client side is always relative to java:jboss/exported
namespace, you shouldn't be prefixing the java:jboss/exported/ string to the JNDI name. For
example, if you use the following JNDI name:
ctx.lookup("java:jboss/exported/helloworld");
then remote-naming will translate it to
ctx.lookup("java:jboss/exported/java:jboss/exported/helloworld");
and as a result, will fail during lookup.
The remote-naming implementation perhaps should be smart enough to strip off the
java:jboss/exported/ namespace prefix if supplied. But let's not go into that here.
WildFly 9
6.31.4 Summary
That pretty much covers whatever is important to know, in the remote-naming project, for a typical client
application. Don't close the browser yet though, since we haven't yet come to the part of EJB invocations
from a remote client using the remote-naming project. In fact, the motivation behind writing this article was to
explain why not to use remote-naming project (in most cases) for doing EJB invocations against
WildFly server.
Those of you who don't have client applications doing remote EJB invocations, can just skip the rest of this
article if you aren't interested in those details.
WildFly 9
package org.myapp.ejb;
@Stateless
@Remote(Foo.class)
public class FooBean implements Foo {
...
public String sayBar() {
return "Baaaaaaaar";
}
}
Then the "Foo" remote view is exposed under the java:jboss/exported/ namespace under the
following JNDI name scheme (which is similar to that mandated by EJB3.1 spec for java:global/
namespace):app-name
app-name/module-name/bean-name!bean-interface
where,
app-name = the name of the .ear (without the .ear suffix) or the application name configured via
application.xml deployment descriptor. If the application isn't packaged in a .ear then there will be no
app-name part to the JNDI string.
module-name = the name of the .jar or .war (without the .jar/.war suffix) in which the bean is deployed or
the module-name configured in web.xml/ejb-jar.xml of the deployment. The module name is mandatory part
in the JNDI string.
bean-name = the name of the bean which by default is the simple name of the bean implementation class.
Of course it can be overridden either by using the "name" attribute of the bean definining annotation
(@Stateless(name="blah") in this case) or even the ejb-jar.xml deployment descriptor.
bean-interface = the fully qualified class name of the interface being exposed by the bean.
So in our example above, let's assume the bean is packaged in a myejbmodule.jar which is within a
myapp.ear. So the JNDI name for the Foo remote view under the java:jboss/exported/ namespace
would be:
java:jboss/exported/myapp/myejbmodule/FooBean!org.myapp.ejb.Foo
That's where WildFly will automatically expose the remote views of the EJBs under the
java:jboss/exported/ namespace, in addition to the java:global/ java:app/ java:module/ namespaces
mandated by the EJB 3.1 spec.
So the next logical question would be, are these remote views of EJBs accessible and invokable using the
remote-naming project on the client application. The answer is yes! Let's quickly see the client code for
invoking our FooBean. Again, let's just use "peter" and "lois" as username/pass for connecting to the
remoting connector.
WildFly 9
void doBeanLookup() {
...
Properties jndiProps = new Properties();
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFactory");
jndiProps.put(Context.PROVIDER_URL,"http-remoting://localhost:8080");
// username
jndiProps.put(Context.SECURITY_PRINCIPAL, "peter");
// password
jndiProps.put(Context.SECURITY_CREDENTIALS, "lois");
// This is an important property to set if you want to do EJB invocations via the
remote-naming project
jndiProps.put("jboss.naming.client.ejb.context", true);
// create a context passing these properties
Context ctx = new InitialContext(jndiProps);
// lookup the bean
Foo
As you can see, most of the code is similar to what we have been seeing so far for setting up a JNDI context
backed by the remote-naming project. The only parts that change are:
1) An additional "jboss.naming.client.ejb.context" property that is added to the properties passed
to the InitialContext constructor.
2) The JNDI name used for the lookup
3) And subsequently the invocation on the bean interface returned by the lookup.
Let's see what the "jboss.naming.client.ejb.context" does. In WildFly, remote access/invocations
on EJBs is facilitated by the JBoss specific EJB client API, which is a project on its own
https://github.com/jbossas/jboss-ejb-client. So no matter, what mechanism you use (remote-naming or core
EJB client API), the invocations are ultimately routed through the EJB client API project. In this case too, the
remote-naming internally uses EJB client API to handle EJB invocations. From a EJB client API project
perspective, for successful communication with the server, the project expects a EJBClientContext
backed by (atleast one) EJBReceiver(s). The EJBReceiver is responsible for handling the EJB
invocations. One type of a EJBReceiver is a RemotingConnectionEJBReceiver which internally uses
jboss-remoting project to communicate with the remote server to handle the EJB invocations. Such a
EJBReceiver expects a connection backed by the jboss-remoting project. Of course to be able to connect
to the server, such a EJBReceiver would have to know the server address, port, security credentials and
other similar parameters. If you were using the core EJB client API, then you would have configured all these
properties via the jboss-ejb-client.properties or via programatic API usage as explained here EJB invocations
from a remote client using JNDI. But in the example above, we are using remote-naming project and are not
directly interacting with the EJB client API project.
WildFly 9
If you look closely at what's being passed, via the JNDI properties, to the remote-naming project and if you
remember the details that we explained in a previous section about how the remote-naming project
establishes a connection to the remote server, you'll realize that these properties are indeed the same as
what the RemotingConnectionEJBReceiver would expect to be able to establish the connection to the
server. Now this is where the "jboss.naming.client.ejb.context" property comes into picture. When
this is set to true and passed to the InitialContext creation (either via jndi.properties or via the constructor of
that class), the remote-naming project internally will do whatever is necessary to setup a
EJBClientContext, containing a RemotingConnectionEJBReceiver which is created using the same
remoting connection that is created by and being used by remote-naming project for its own JNDI
communication usage. So effectively, the InitialContext creation via the remote-naming project has now
internally triggered the creation of a EJBClientContext containing a EJBReceiver capable of handling
the EJB invocations (remember, no remote EJB invocations are possible without the presence of a
EJBClientContext containing a EJBReceiver which can handle the EJB).
So we now know the importance of the "jboss.naming.client.ejb.context" property and its usage.
Let's move on the next part in that code, the JNDI name. Notice that we have used the JNDI name relative to
the java:jboss/exported/ namespace while doing the lookup. And since we know that the Foo view is
exposed on that JNDI name, we cast the returned object back to the Foo interface. Remember that we
earlier explained how each lookup via remote-naming triggers a server side communication and a
marshalling/unmarshalling process. This applies for EJB views too. In fact, the remote-naming project has no
clue (since that's not in the scope of that project to know) whether it's an EJB or some random object.
Once the unmarshalled object is returned (which actually is a proxy to the bean), the rest is straightforward,
we just invoke on that returned object. Now since the remote-naming implementation has done the
necessary setup for the EJBClientContext (due to the presence of "
jboss.naming.client.ejb.context" property), the invocation on that proxy will internally use the
EJBClientContext (the proxy is smart enough to do that) to interact with the server and return back the
result. We won't go into the details of how the EJB client API handles the communication/invocation.
Long story short, using the remote-naming project for doing remote EJB invocations against WildFly is
possible!
WildFly 9
ctx.lookup("foo/bar");
Now foo/bar JNDI name could potentially point to any type of object on the server side. The jndi name
itself won't have the type/semantic information of the object bound to that name on the server side. If the
context was setup using the remote-naming project (like we have seen earlier in our examples), then the
only way for remote-naming to return an object for that lookup operation is to communicate with the server
and marshal/unmarshal the object bound on the server side. And that's exactly what it does (remember, we
explained this earlier).
The EJB client API project on the other hand optimizes this lookup. In order to do so, it expects the client
application to let it know that a EJB is being looked up. It does this, by expecting the client application to use
the JNDI name of the format "ejb:" namespace and also expecting the client application to setup the JNDI
context by passing the "org.jboss.ejb.client.naming" value for the Context.URL_PKG_PREFIXES
property.
Example:
More details about such code can be found here EJB invocations from a remote client using JNDI
When a client application looks up anything under the "ejb:" namespace, it is a clear indication (for the EJB
client API project) to know that the client is looking up an EJB. That's where it steps in to do the necessary
optimizations that might be applicable. So unlike, in the case of remote-naming project (which has no clue
about the semantics of the object being looked up), the EJB client API project does not trigger a server side
communication or a marshal/unmarshal process when you do lookup for a remote view of a stateless bean
(it's important to note that we have specifically mentioned stateless bean here, we'll come to that later).
Instead, the EJB client API just returns a java.lang.reflect.Proxy instance of the remote view type that's being
looked up. This not just saves a network call, marshalling/unmarshalling step but it also means that you can
create an EJB proxy even when the server isn't up yet. Later on, when the invocation on the proxy happens,
the EJB client API does communicate with the server to carry out the invocation.
WildFly 9
context.lookup("ejb:myapp/myejbmodule//StatefulBean!org.myapp.ejb.Counter?stateful");
Notice the use of "?stateful" in that JNDI name. See EJB invocations from a remote client using JNDI for
more details about such lookup.
The presence of "?stateful" in the JNDI name lookup string is a directive to the EJB client API to let it
know that a stateful bean is being looked up and it's necessary to communicate with the server and create a
session during that lookup.
So as you can see, we have managed to optimize certain operations by using the EJB client API for EJB
lookup/invocation as against using the remote-naming project. There are other EJB client API
implementation details (and probably more might be added) which are superior when it is used for remote
EJB invocations in client applications as against remote-naming project which doesn't have the intelligence
to carry out such optimizations for EJB invocations. That's why the remote-naming project for remote EJB
invocations is considered "deprecated". Note that if you want to use remote-naming for looking up and
invoking on non-EJB remote objects then you are free to do so. In fact, that's why that project has been
provided. You can even use the remote-naming project for EJB invocations (like we just saw), if you are fine
with not wanting the optimizations that the EJB client API can do for you or if you have other restrictions that
force you to use that project.
WildFly 9
WildFly 9
Now, we have seen in this other chapter EJB invocations from a remote client using JNDI that the JNDI
lookups are (typically) backed by jboss-ejb-client.properties file which is used to setup the EJB client context
and the EJB receivers. Let's assume we have a jboss-ejb-client.properties with the relevant receivers
configurations. These configurations include the security credentials that will be used to create a EJB
receiver which connects to the AS7 server. Now when the above code is invoked, the EJB client API looks
for the EJB client context to pick a EJB receiver, to pass on the EJB invocation request. Since we just have a
single EJB client context, that context is used by the above code to invoke the bean.
Now let's consider a case where the user application wants to invoke on the bean more than once, but wants
to connect to the WildFly 8 server using different security credentials. Let's take a look at the following code:
WildFly 9
So we have the same application, which wants to connect to the same server instance for invoking the
EJB(s) hosted on that server, but wants to use two different credentials while connecting to the server.
Remember, the client application has a single EJB client context which can have atmost 1 EJB recevier for
each server instance. Which effectively means that the above code will end up using just one credential to
connect to the server. So there was no easy way to have the above code working.
That was one of the use cases which prompted the https://issues.jboss.org/browse/EJBCLIENT-34 feature
request. The proposal was to introduce a way, where you can have more control over the EJB client
contexts and their association with JNDI contexts which are typically used for EJB invocations.
WildFly 9
Notice any difference between this code and the earlier one? We now create and pass EJB client context
specific properties to the JNDI context. So what do the EJB client context properties look like? The
properties are the same that you would pass through the jboss-ejb-client.properties file, except for one
additional property which is required to scope the EJB client context to the JNDI context. The name of the
property is:
org.jboss.ejb.client.scoped.context
which is expected to have a value true. This property lets the EJB client API know that it has to created a
EJB client context (backed by EJB receiver(s)) and that created context is then scoped/visible to only that
JNDI context which created it. Lookup and invocation on any EJB proxies looked up using this JNDI context
will only know of the EJB client context associated with this JNDI context. This effectively means that the
other JNDI contexts which the application uses to lookup and invoke on EJBs will not know about the other
scoped EJB client contexts at all.
JNDI contexts which aren't scoped to a EJB client context (for example, not passing the
org.jboss.ejb.client.scoped.context property) will fallback to the default behaviour of using the "current" EJB
client context which typically is the one tied to the entire application.
This scoping of the EJB client context helps the user applications to have more control over which JNDI
context "talks to" which server and connects to that server in "what way". This gives the user applications the
flexibility that was associated with the JNP based JNDI invocations prior to WildFly 8 versions.
IMPORTANT: It is very important to remember that scoped EJB client contexts which are
scoped to the JNDI contexts are NOT fire and forget kind of contexts. What that means is
the application program which is using these contexts is solely responsible for managing
their lifecycle and the application itself is responsible for closing the context at the right
moment. After closing the context the proxies which are bound to this context are no longer
valid and any invocation will throw an Exception. Not closing the context will end in
resource problems as the underlying physical connection will stay open.
Read the rest of the sections in this article to understand more about the lifecycle
management of such scoped contexts.
WildFly 9
The connections thus created for a EJB client context are kept open as long as the EJB client context is
open. This allows the EJB client context to be usable for EJB invocations. The connections associated with
the EJB client context are closed when the EJB client context itself is closed.
The connections that were manually added by the application to the EJB client context are not
managed by the EJB client context. i.e. they won't be opened (obviously) nor closed by the EJB
client API when the EJB client context is closed.
So we first create a JNDI context and then use it to lookup an EJB. The bean lookup using the ejb: JNDI
name, although, is just one statement, involves a few more things under the hood. What's actually
happening when you lookup that string is that a separate javax.naming.Context gets created for the ejb: URL
string. This new javax.naming.Context is then used to lookup the rest of the string in that JNDI name.
Let's break up that one line into multiple statements to understand better:
// Remember, the ejb: is backed by a URL context factory which returns a Context for the ejb:
URL (that's why it's called a context factory)
final Context ejbNamingContext = (Context) jndiCtx.lookup("ejb:");
// Use the returned EJB naming context to lookup the rest of the JNDI string for EJB
final MyBean bean = ejbNamingContext.lookup("app/module/distinct/bean!interface");
WildFly 9
As you see above, we split up that single statement into a couple of statements for explaining the details
better. So as you can see when the ejb: URL string is parsed in a JNDI name, it gets hold of a
javax.naming.Context instance. This instance is different from the one which was used to do the lookup
(jndiCtx in this example). This is an important detail to understand (for reasons explained later). Now this
returned instance is used to lookup the rest of the JNDI string ("app/module/distinct/bean!interface"), which
then returns the EJB proxy. Irrespective of whether the lookup is done in a single statement or multiple parts,
the code works the same. i.e. an instance of javax.naming.Context gets created for the ejb: URL string.
So why am I explaining all this when the section is titled "How to close scoped EJB client
contexts"? The reason is because client applications dealing with scoped EJB client contexts which are
associated with a JNDI context would expect the following code to close the associated EJB client context,
but will be surprised that it won't:
Applications expect that the call to jndiCtx.close() will effectively close the EJB client context associated with
the JNDI context. That doesn't happen because as explained previously, the javax.naming.Context backing
the ejb: URL string is a different instance than the one the code is closing. The JNDI implementation in Java,
only just closes the context on which the close was called. As a result, the other javax.naming.Context that
backs the ejb: URL string is still not closed, which effectively means that the scoped EJB client context is not
closed too which then ultimately means that the connection to the server(s) in the EJB client context are not
closed too.
So now let's see how this can be done properly. We know that the ejb: URL string lookup returns us a
javax.naming.Context. All we have to do is keep a reference to this instance and close it when we are done
with the EJB invocations. So here's how it's going to look:
WildFly 9
As you see, we changed the code to first do a lookup on just the "ejb:" string to get hold of the EJB naming
context and then used that ejbRootNamingContext instance to lookup the rest of the EJB JNDI name to get
hold of the EJB proxy. Then when it was time to close the context, we closed the ejbRootNamingContext (as
well as the other JNDI context). Closing the ejbRootNamingContext ensures that the scoped EJB client
context associated with that JNDI context is closed too. Effectively, this closes the connection(s) to the
server(s) within that EJB client context.
WildFly 9
Notice that we no longer hold a reference to 2 JNDI contexts and instead just keep track of the
ejbRootNamingContext which is actually the root JNDI context for our "ejb:" URL string. Of course, this
means that you can only use this context for EJB lookups or any other EJB related JNDI lookups. So it
depends on your application and how it's coded.
WildFly 9
Can't the scoped EJB client context be automatically closed by the EJB
client API when the JNDI context is no longer in scope (i.e. on GC)?
That's one of the common questions that gets asked. No, the EJB client API can't take that decision. i.e. it
cannot automatically go ahead and close the scoped EJB client context by itself when the associated JNDI
context is eligible for GC. The reason is simple as illustrated by the following code:
void doEJBInvocation() {
final MyBean bean = lookupEJB();
bean.doSomething();
bean.doSomeOtherThing();
... // do some other work
bean.keepDoingSomething();
}
MyBean lookupEJB() {
final Properties props = new Properties();
// mark it for scoped EJB client context
props.put("org.jboss.ejb.client.scoped.context","true");
// add other properties
props.put(....);
...
Context ejbRootNamingContext = (Context) new InitialContext(props).lookup("ejb:");
final MyBean bean = ejbRootNamingContext.lookup("app/module/distinct/bean!interface"); //
rest of the EJB jndi string
return bean;
}
As you can see, the doEJBInvocation() method first calls a lookupEJB() method which does a lookup of the
bean using a JNDI context and then returns the bean (proxy). The doEJBInvocation() then uses that
returned proxy and keeps doing the invocations on the bean. As you might have noticed, the JNDI context
that was used for lookup (i.e. the ejbRootNamingContext) is eligible for GC. If the EJB client API had closed
the scoped EJB client context associated with that JNDI context, when that JNDI context was garbage
collected, then the subsequent EJB invocations on the returned EJB (proxy) would start failing in
doEJBInvocation() since the EJB client context is no longer available.
That's the reason why the EJB client API doesn't automatically close the EJB client context.
WildFly 9
WildFly 9
<persistence-context-ref>
<persistence-context-ref-name>persistence/petclinic-em</persistence-unit-ref-name>
<persistence-unit-name>petclinic</persistence-unit-name>
</persistence-context-ref>
or, respectively:
<persistence-unit-ref>
<persistence-unit-ref-name>persistence/petclinic-emf</persistence-unit-ref-name>
<persistence-unit-name>petclinic</persistence-unit-name>
</persistence-unit-ref>
When doing so, the persistence context or persistence unit are available to be looked up in JNDI, as follows:
or
JNDI binding
JNDI binding via persistence.xml properties is not supported in WildFly 8.
WildFly 9
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation"
value="classpath*:META-INF/jpa-persistence.xml"/>
<!-- other definitions -->
</bean>
Managing dependencies
Since the LocalContainerEntityManagerFactoryBean and the corresponding HibernateJpaVendorAdapter
are based on Hibernate 3, it is required to use that version with the application. Therefore, the Hibernate 3
jars must be included in the deployment. At the same time, due the presence of @PersistenceUnit or
@PersistenceContext annotations on the application classes, the application server will automatically add
the 'org.hibernate' module as a dependency.
This can be avoided by instructing the server to exclude the module from the deployment's list of
dependencies. In order to do so, include a META-INF/jboss-deployment-structure.xml or, for web
applications, WEB-INF/jboss-deployment-structure.xml with the following content:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
<deployment>
<exclusions>
<module name="org.hibernate"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
WildFly 9
<jboss umlns="urn:jboss:1.0">
<shared-session-config xmlns="urn:jboss:shared-session-config:1.0">
<session-config>
<cookie-config>
<path>/</path>
</cookie-config>
</session-config>
</shared-session-config>
</jboss>
This element is used to configure the shared session manager that will be used by all wars in the ear. For full
details of all the options provided by this file please see the schema at
https://github.com/wildfly/wildfly/blob/master/undertow/src/main/resources/schema/shared-session-config_1_0.xsd
, however in general it mimics the options that are available in jboss-web.xml for configuring the session.
WildFly 9
WildFly 9
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class JSEBean01
{
@WebMethod
public String echo(String input)
{
...
}
}
<web-app ...>
<servlet>
<servlet-name>TestService</servlet-name>
<servlet-class>org.jboss.test.ws.jaxws.samples.jsr181pojo.JSEBean01</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
<war warfile="${build.dir}/libs/jbossws-samples-jsr181pojo.war"
webxml="${build.resources.dir}/samples/jsr181pojo/WEB-INF/web.xml">
<classes dir="${build.dir}/classes">
<include name="org/jboss/test/ws/samples/jsr181pojo/JSEBean01.class"/>
</classes>
</war>
Note, only the endpoint implementation bean and web.xml are required.
Note, it is also possible to generate the abstract contract off line using JBossWS tools. For details
of that please see Bottom-Up (Java to WSDL).
WildFly 9
@Stateless
@Remote(EJB3RemoteInterface.class)
@RemoteBinding(jndiBinding = "/ejb3/EJB3EndpointInterface")
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class EJB3Bean01 implements EJB3RemoteInterface
{
@WebMethod
public String echo(String input)
{
...
}
}
Above you see an EJB-3.0 stateless session bean that exposes one method both on the remote interface
and as an endpoint operation.
<jar jarfile="${build.dir}/libs/jbossws-samples-jsr181ejb.jar">
<fileset dir="${build.dir}/classes">
<include name="org/jboss/test/ws/samples/jsr181ejb/EJB3Bean01.class"/>
<include name="org/jboss/test/ws/samples/jsr181ejb/EJB3RemoteInterface.class"/>
</fileset>
</jar>
Note, it is also possible to generate the abstract contract off line using JBossWS tools. For details
of that please see Bottom-Up (Java to WSDL).
WildFly 9
Endpoint Provider
JAX-WS services typically implement a native Java service endpoint interface (SEI), perhaps mapped from a
WSDL port type, either directly or via the use of annotations.
Java SEIs provide a high level Java-centric abstraction that hides the details of converting between Java
objects and their XML representations for use in XML-based messages. However, in some cases it is
desirable for services to be able to operate at the XML message level. The Provider interface offers an
alternative to SEIs and may be implemented by services wishing to work at the XML message level.
A Provider based service instances invoke method is called for each message received for the service.
@WebServiceProvider(wsdlLocation = "WEB-INF/wsdl/Provider.wsdl")
@ServiceMode(value = Service.Mode.PAYLOAD)
public class ProviderBeanPayload implements Provider<Source>
{
public Source invoke(Source req)
{
// Access the entire request PAYLOAD and return the response PAYLOAD
}
}
Note, Service.Mode.PAYLOAD is the default and does not have to be declared explicitly. You can also use
Service.Mode.MESSAGE to access the entire SOAP message (i.e. with MESSAGE the Provider can also
see SOAP Headers)
The abstract contract for a provider endpoint cannot be derived/generated automatically. Therefore it is
necessary to specify the wsdlLocation with the @WebServiceProvider annotation.
WildFly 9
Service Usage
Static case
Most clients will start with a WSDL file, and generate some stubs using JBossWS tools like wsconsume.
This usually gives a mass of files, one of which is the top of the tree. This is the service implementation
class.
The generated implementation class can be recognised as it will have two public constructors, one with no
arguments and one with two arguments, representing the wsdl location (a java.net.URL) and the service
name (a javax.xml.namespace.QName) respectively.
Usually you will use the no-argument constructor. In this case the WSDL location and service name are
those found in the WSDL. These are set implicitly from the @WebServiceClient annotation that decorates
the generated class.
The following code snippet shows the generated constructors from the generated class:
Section Dynamic Proxy explains how to obtain a port from the service and how to invoke an operation on the
port. If you need to work with the XML payload directly or with the XML representation of the entire SOAP
message, have a look at Dispatch.
Dynamic case
In the dynamic case, when nothing is generated, a web service client uses Service.create to create
Service instances, the following code illustrates this process.
WildFly 9
Handler Resolver
JAX-WS provides a flexible plug-in framework for message processing modules, known as handlers, that
may be used to extend the capabilities of a JAX-WS runtime system. Handler Framework describes the
handler framework in detail. A Service instance provides access to a HandlerResolver via a pair of
getHandlerResolver / setHandlerResolver methods that may be used to configure a set of handlers
on a per-service, per-port or per-protocol binding basis.
When a Service instance is used to create a proxy or a Dispatch instance then the handler resolver currently
registered with the service is used to create the required handler chain. Subsequent changes to the handler
resolver configured for a Service instance do not affect the handlers on previously created proxies, or
Dispatch instances.
Executor
Service instances can be configured with a java.util.concurrent.Executor. The executor will then
be used to invoke any asynchronous callbacks requested by the application. The setExecutor and
getExecutor methods of Service can be used to modify and retrieve the executor configured for a
service.
Dynamic Proxy
You can create an instance of a client proxy using one of getPort methods on the Service.
/**
* The getPort method returns a proxy. A service client
* uses this proxy to invoke operations on the target
* service endpoint. The <code>serviceEndpointInterface</code>
* specifies the service endpoint interface that is supported by
* the created dynamic proxy instance.
**/
public <T> T getPort(QName portName, Class<T> serviceEndpointInterface)
{
...
}
/**
* The getPort method returns a proxy. The parameter
* <code>serviceEndpointInterface</code> specifies the service
* endpoint interface that is supported by the returned proxy.
* In the implementation of this method, the JAX-WS
* runtime system takes the responsibility of selecting a protocol
* binding (and a port) and configuring the proxy accordingly.
* The returned proxy should not be reconfigured by the client.
*
**/
public <T> T getPort(Class<T> serviceEndpointInterface)
{
...
}
The service endpoint interface (SEI) is usually generated using tools. For details see Top Down (WSDL to
Java)
WildFly 9
A generated static Service usually also offers typed methods to get ports. These methods also return
dynamic proxies that implement the SEI.
WebServiceRef
The @WebServiceRef annotation is used to declare a reference to a Web service. It follows the resource
pattern exemplified by the javax.annotation.Resource annotation in JSR-250.
There are two uses to the WebServiceRef annotation:
1. To define a reference whose type is a generated service class. In this case, the type and value
element will both refer to the generated service class type. Moreover, if the reference type can be
inferred by the field/method declaration the annotation is applied to, the type and value elements MAY
have the default value (Object.class, that is). If the type cannot be inferred, then at least the type
element MUST be present with a non-default value.
2. To define a reference whose type is a SEI. In this case, the type element MAY be present with its
default value if the type of the reference can be inferred from the annotated field/method declaration,
but the value element MUST always be present and refer to a generated service class type (a
subtype of javax.xml.ws.Service). The wsdlLocation element, if present, overrides theWSDL location
information specified in the WebService annotation of the referenced generated service class.
WildFly 9
Dispatch
XMLWeb Services use XML messages for communication between services and service clients. The higher
level JAX-WS APIs are designed to hide the details of converting between Java method invocations and the
corresponding XML messages, but in some cases operating at the XML message level is desirable. The
Dispatch interface provides support for this mode of interaction.
Dispatch supports two usage modes, identified by the constants
javax.xml.ws.Service.Mode.MESSAGE and javax.xml.ws.Service.Mode.PAYLOAD respectively:
Message In this mode, client applications work directly with protocol-specific message structures. E.g., when
used with a SOAP protocol binding, a client application would work directly with a SOAP message.
Message Payload In this mode, client applications work with the payload of messages rather than the
messages themselves. E.g., when used with a SOAP protocol binding, a client application would work with
the contents of the SOAP Body rather than the SOAP message as a whole.
Dispatch is a low level API that requires clients to construct messages or message payloads as XML and
requires an intimate knowledge of the desired message or payload structure. Dispatch is a generic class that
supports input and output of messages or message payloads of any type.
WildFly 9
Asynchronous Invocations
The BindingProvider interface represents a component that provides a protocol binding for use by
clients, it is implemented by proxies and is extended by the Dispatch interface.
BindingProvider instances may provide asynchronous operation capabilities. When used, asynchronous
operation invocations are decoupled from the BindingProvider instance at invocation time such that the
response context is not updated when the operation completes. Instead a separate response context is
made available using the Response interface.
Oneway Invocations
@Oneway indicates that the given web method has only an input message and no output. Typically, a
oneway method returns the thread of control to the calling application prior to executing the actual business
method.
@WebService (name="PingEndpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class PingEndpointImpl
{
private static String feedback;
@WebMethod
@Oneway
publicvoid ping()
{
log.info("ping");
feedback = "ok";
}
@WebMethod
public String feedback()
{
log.info("feedback");
return feedback;
}
}
WildFly 9
Timeout Configuration
There are two properties to configure the http connection timeout and client receive time out:
Common API
This sections describes concepts that apply equally to Web Service Endpoints and Web Service Clients.
Handler Framework
The handler framework is implemented by a JAX-WS protocol binding in both client and server side
runtimes. Proxies, and Dispatch instances, known collectively as binding providers, each use protocol
bindings to bind their abstract functionality to specific protocols.
Client and server-side handlers are organized into an ordered list known as a handler chain. The handlers
within a handler chain are invoked each time a message is sent or received. Inbound messages are
processed by handlers prior to binding provider processing. Outbound messages are processed by handlers
after any binding provider processing.
Handlers are invoked with a message context that provides methods to access and modify inbound and
outbound messages and to manage a set of properties. Message context properties may be used to
facilitate communication between individual handlers and between handlers and client and service
implementations. Different types of handlers are invoked with different types of message context.
Logical Handler
Handlers that only operate on message context properties and message payloads. Logical handlers are
protocol agnostic and are unable to affect protocol specific parts of a message. Logical handlers are
handlers that implement javax.xml.ws.handler.LogicalHandler.
Protocol Handler
Handlers that operate on message context properties and protocol specific messages. Protocol handlers are
specific to a particular protocol and may access and change protocol specific aspects of a message.
Protocol handlers are handlers that implement any interface derived from
javax.xml.ws.handler.Handler except javax.xml.ws.handler.LogicalHandler.
WildFly 9
@WebService
@HandlerChain(file = "jaxws-server-source-handlers.xml")
public class SOAPEndpointSourceImpl
{
...
}
WildFly 9
Message Context
MessageContext is the super interface for all JAX-WS message contexts. It extends
Map<String,Object> with additional methods and constants to manage a set of properties that enable
handlers in a handler chain to share processing related state. For example, a handler may use the put
method to insert a property in the message context that one or more other handlers in the handler chain may
subsequently obtain via the get method.
Properties are scoped as either APPLICATION or HANDLER. All properties are available to all handlers for
an instance of an MEP on a particular endpoint. E.g., if a logical handler puts a property in the message
context, that property will also be available to any protocol handlers in the chain during the execution of an
MEP instance. APPLICATION scoped properties are also made available to client applications (see section
4.2.1) and service endpoint implementations. The defaultscope for a property is HANDLER.
WildFly 9
Fault Handling
An implementation may thow a SOAPFaultException
In case of the latter, JBossWS generates the required fault wrapper beans at runtime if they are not
part of the deployment
WS Annotations
For details, see JSR-224 - Java API for XML-Based Web Services (JAX-WS) 2.2
javax.xml.ws.ServiceMode
The ServiceMode annotation is used to specify the mode for a provider class, i.e. whether a provider wants
to have access to protocol message payloads (e.g. a SOAP body) or the entire protocol messages (e.g. a
SOAP envelope).
javax.xml.ws.WebFault
The WebFault annotation is used when mapping WSDL faults to Java exceptions, see section 2.5. It is
used to capture the name of the fault element used when marshalling the JAXB type generated from the
global element referenced by the WSDL fault message. It can also be used to customize the mapping of
service specific exceptions to WSDL faults.
WildFly 9
javax.xml.ws.RequestWrapper
The RequestWrapper annotation is applied to the methods of an SEI. It is used to capture the JAXB
generated request wrapper bean and the element name and namespace for marshalling / unmarshalling the
bean. The default value of localName element is the operationName as defined in WebMethod annotation
and the default value for the targetNamespace element is the target namespace of the SEI.When starting
from Java, this annotation is used to resolve overloading conflicts in document literal mode. Only the
className element is required in this case.
javax.xml.ws.ResponseWrapper
The ResponseWrapper annotation is applied to the methods of an SEI. It is used to capture the JAXB
generated response wrapper bean and the element name and namespace for marshalling / unmarshalling
the bean. The default value of the localName element is the operationName as defined in the WebMethod
appended with Response and the default value of the targetNamespace element is the target namespace
of the SEI. When starting from Java, this annotation is used to resolve overloading conflicts in document
literal mode. Only the className element is required in this case.
javax.xml.ws.WebServiceClient
The WebServiceClient annotation is specified on a generated service class (see 2.7). It is used to
associate a class with a specific Web service, identify by a URL to a WSDL document and the qualified
name of a wsdl:service element.
javax.xml.ws.WebEndpoint
The WebEndpoint annotation is specified on the getPortName() methods of a generated service class (see
2.7). It is used to associate a get method with a specific wsdl:port, identified by its local name (a NCName).
javax.xml.ws.WebServiceProvider
The WebServiceProvider annotation is specified on classes that implement a strongly typed
javax.xml.ws.Provider. It is used to declare that a class that satisfies the requirements for a provider
(see 5.1) does indeed define a Web service endpoint, much like the WebService annotation does for
SEI-based endpoints.
The WebServiceProvider and WebService annotations are mutually exclusive.
javax.xml.ws.BindingType
The BindingType annotation is applied to an endpoint implementation class. It specifies the binding to use
when publishing an endpoint of this type.
The default binding for an endpoint is the SOAP 1.1/HTTP one.
javax.xml.ws.WebServiceRef
The WebServiceRef annotation is used to declare a reference to a Web service. It follows the resource
pattern exemplified by the javax.annotation.Resource annotation in JSR-250 [JBWS:32]. The
WebServiceRef annotation is required to be honored when running on the Java EE 5 platform, where it is
subject to the common resource injection rules described by the platform specification [JBWS:33].
WildFly 9
javax.xml.ws.WebServiceRefs
The WebServiceRefs annotation is used to declare multiple references to Web services on a single class.
It is necessary to work around the limition against specifying repeated annotations of the same type on any
given class, which prevents listing multiple javax.ws.WebServiceRef annotations one after the other.
This annotation follows the resource pattern exemplified by the javax.annotation.Resources
annotation in JSR-250.
Since no name and type can be inferred in this case, each WebServiceRef annotation inside a
WebServiceRefs MUST contain name and type elements with non-default values. The WebServiceRef
annotation is required to be honored when running on the Java EE 5 platform, where it is subject to the
common resource injection rules described by the platform specification.
javax.xml.ws.Action
The Action annotation is applied to the methods of a SEI. It used to generate the wsa:Action on wsdl:input
and wsdl:output of each wsdl:operation mapped from the annotated methods.
javax.xml.ws.FaultAction
The FaultAction annotation is used within the Action annotation to generate the wsa:Action element on
the wsdl:fault element of each wsdl:operation mapped from the annotated methods.
WildFly 9
181 Annotations
JSR-181 defines the syntax and semantics of Java Web Service (JWS) metadata and default values.
For details, see JSR 181 - Web Services Metadata for the Java Platform.
javax.jws.WebService
Marks a Java class as implementing a Web Service, or a Java interface as defining a Web Service interface.
javax.jws.WebMethod
Customizes a method that is exposed as a Web Service operation.
javax.jws.OneWay
Indicates that the given web method has only an input message and no output. Typically, a oneway method
returns the thread of control to the calling application prior to executing the actual business method. A
JSR-181 processor is REQUIRED to report an error if an operation marked @Oneway has a return value,
declares any checked exceptions or has any INOUT or OUT parameters.
javax.jws.WebParam
Customizes the mapping of an individual parameter to a Web Service message part and XML element.
javax.jws.WebResult
Customizes the mapping of the return value to a WSDL part and XML element.
javax.jws.SOAPBinding
Specifies the mapping of the Web Service onto the SOAP message protocol.
The SOAPBinding annotation has a target of TYPE and METHOD. The annotation may be placed on a
method if and only if the SOAPBinding.style is DOCUMENT. Implementations MUST report an error if the
SOAPBinding annotation is placed on a method with a SOAPBinding.style of RPC. Methods that do not
have a SOAPBinding annotation accept the SOAPBinding behavior defined on the type.
javax.jws.HandlerChain
The @HandlerChain annotation associates the Web Service with an externally defined handler chain.
It is an error to combine this annotation with the @SOAPMessageHandlers annotation.
The @HandlerChain annotation MAY be present on the endpoint interface and service implementation
bean. The service implementation bean's @HandlerChain is used if @HandlerChain is present on both.
The @HandlerChain annotation MAY be specified on the type only. The annotation target includes METHOD
and FIELD for use by JAX-WS-2.x.
WildFly 9
6.35.2 WS Tools
The JAX-WS tools provided by JBossWS can be used in a variety of ways. First we will look at server-side
development strategies, and then proceed to the client.
Server side
When developing a Web Service Endpoint (the server-side) you have the option of starting from Java (
bottom-up development), or from the abstact contract (WSDL) that defines your service ( top-down
development). If this is a new service (no existing contract), the bottom-up approach is the fastest route; you
only need to add a few annotations to your classes to get a service up and running. However, if you are
developing a service with an already defined contract, it is far simpler to use the top-down approach, since
the provided tool will generate the annotated code for you.
Bottom-up use cases:
Exposing an already existing EJB3 bean as a Web Service
Providing a new service, and you want the contract to be generated for you
Top-down use cases:
Replacing the implementation of an existing Web Service, and you can't break compatibility with older
clients
Exposing a service that conforms to a contract specified by a third party (e.g. a vender that calls you
back using an already defined protocol).
Creating a service that adheres to the XML Schema and WSDL you developed by hand up front
The following JAX-WS command line tools are included in JBossWS:
Command
Description
wsprovide
Generates JAX-WS portable artifacts, and provides the abstract contract. Used for bottom-up
development.
wsconsume Consumes the abstract contract (WSDL and Schema files), and produces artifacts for both a
server and client. Used for top-down and client development
WildFly 9
package echo;
@javax.jws.WebService
public class Echo
{
public String echo(String input)
{
return input;
}
}
A JSE or EJB3 deployment can be built using this class, and it is the only Java code needed to deploy on
JBossWS. The WSDL, and all other Java artifacts called "wrapper classes" will be generated for you at
deploy time. This actually goes beyond the JAX-WS specification, which requires that wrapper classes be
generated using an offline tool. The reason for this requirement is purely a vender implementation problem,
and since we do not believe in burdening a developer with a bunch of additional steps, we generate these as
well. However, if you want your deployment to be portable to other application servers, you will unfortunately
need to use a tool and add the generated classes to your deployment.
This is the primary purpose of the wsprovide tool, to generate portable JAX-WS artifacts. Additionally, it can
be used to "provide" the abstract contract (WSDL file) for your service. This can be obtained by invoking
wsprovide using the "-w" option:
<service name='EchoService'>
<port binding='tns:EchoBinding' name='EchoPort'>
<soap:address location='REPLACE_WITH_ACTUAL_URL'/>
</port>
</service>
<portType name='Echo'>
<operation name='echo' parameterOrder='echo'>
<input message='tns:Echo_echo'/>
<output message='tns:Echo_echoResponse'/>
</operation>
</portType>
WildFly 9
Remember that when deploying on JBossWS you do not need to run this tool. You only need it for
generating portable artifacts and/or the abstract contract for your service.
Let's create a POJO endpoint for deployment on WildFly. A simple web.xml needs to be created:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>Echo</servlet-name>
<servlet-class>echo.Echo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Echo</servlet-name>
<url-pattern>/Echo</url-pattern>
</servlet-mapping>
</web-app>
The web.xml and the single class can now be used to create a war:
$ mkdir -p WEB-INF/classes
$ cp -rp echo WEB-INF/classes/
$ cp web.xml WEB-INF
$ jar cvf echo.war WEB-INF
added manifest
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/echo/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/echo/Echo.class(in = 340) (out= 247)(deflated 27%)
adding: WEB-INF/web.xml(in = 576) (out= 271)(deflated 52%)
The war can then be deployed to the JBoss Application Server.The war can then be deployed to the JBoss
Application Server; this will internally invoke wsprovide, which will generate the WSDL. If deployment was
successful, and you are using the default settings, it should be available in the server management console.
For a portable JAX-WS deployment, the wrapper classes generated earlier could be added to the
deployment.
WildFly 9
Using the WSDL file from the bottom-up example, a new Java implementation that adheres to this service
can be generated. The "-k" option is passed to wsconsume to preserve the Java source files that are
generated, instead of providing just classes:
$ wsconsume -k EchoService.wsdl
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
Purpose
Echo.java
Echo_Type.java
package-info.java
EchoService.java
Examining the Service Endpoint Interface reveals annotations that are more explicit than in the class written
by hand in the bottom-up example, however, these evaluate to the same contract:
WildFly 9
The only missing piece (besides for packaging) is the implementation class, which can now be written, using
the above interface.
package echo;
@javax.jws.WebService(endpointInterface="echo.Echo")
public class EchoImpl implements Echo
{
public String echo(String arg0)
{
return arg0;
}
}
Client Side
Before going to detail on the client-side it is important to understand the decoupling concept that is central to
Web Services. Web Services are not the best fit for internal RPC, even though they can be used in this way.
There are much better technologies for this (CORBA, and RMI for example). Web Services were designed
specifically for interoperable coarse-grained correspondence. There is no expectation or guarantee that any
party participating in a Web Service interaction will be at any particular location, running on any particular
OS, or written in any particular programming language. So because of this, it is important to clearly separate
client and server implementations. The only thing they should have in common is the abstract contract
definition. If, for whatever reason, your software does not adhere to this principal, then you should not be
using Web Services. For the above reasons, the recommended methodology for developing a client is
to follow the top-down approach, even if the client is running on the same server.
Let's repeat the process of the top-down section, although using the deployed WSDL, instead of the one
generated offline by wsprovide. The reason why we do this is just to get the right value for soap:address.
This value must be computed at deploy time, since it is based on container configuration specifics. You
could of course edit the WSDL file yourself, although you need to ensure that the path is correct.
Offline version:
WildFly 9
<service name='EchoService'>
<port binding='tns:EchoBinding' name='EchoPort'>
<soap:address location='REPLACE_WITH_ACTUAL_URL'/>
</port>
</service>
Online version:
<service name="EchoService">
<port binding="tns:EchoBinding" name="EchoPort">
<soap:address location="http://localhost.localdomain:8080/echo/Echo"/>
</port>
</service>
$ wsconsume -k http://localhost:8080/echo/Echo?wsdl
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
The one class that was not examined in the top-down section, was EchoService.java. Notice how it
stores the location the WSDL was obtained from.
WildFly 9
As you can see, this generated class extends the main client entry point in JAX-WS,
javax.xml.ws.Service. While you can use Service directly, this is far simpler since it provides the
configuration info for you. The only method we really care about is the getEchoPort() method, which
returns an instance of our Service Endpoint Interface. Any WS operation can then be called by just invoking
a method on the returned interface.
It's not recommended to refer to a remote WSDL URL in a production application. This causes
network I/O every time you instantiate the Service Object. Instead, use the tool on a saved local
copy, or use the URL version of the constructor to provide a new WSDL location.
WildFly 9
import echo.*;
public class EchoClient
{
public static void main(String args[])
{
if (args.length != 1)
{
System.err.println("usage: EchoClient <message>");
System.exit(1);
}
EchoService service = new EchoService();
Echo echo = service.getEchoPort();
System.out.println("Server said: " + echo.echo(args0));
}
}
It is easy to change the endpoint address of your operation at runtime, setting the
ENDPOINT_ADDRESS_PROPERTY as shown below:
wsconsume
wsconsume is a command line tool and ant task that "consumes" the abstract contract (WSDL file) and
produces portable JAX-WS service and client artifacts.
WildFly 9
-c
--catalog=<file>
-j --clientjar=<name>
webservice
-p --package=<name>
-w
--wsdlLocation=<loc>
-o, --output=<directory>
-s, --source=<directory>
-t, --target=<2.0|2.1|2.2>
-q, --quiet
-v, --verbose
-l, --load-consumer
-e, --extension
-a, --additionalHeaders
-n, --nocompile
The wsdlLocation is used when creating the Service to be used by clients and will be added to the
@WebServiceClient annotation, for an endpoint implementation based on the generated service
endpoint interface you will need to manually add the wsdlLocation to the @WebService annotation
on your web service implementation and not the service endpoint interface.
WildFly 9
Examples
Generate artifacts in Java class form only:
wsconsume Example.wsdl
wsconsume -k Example.wsdl
Maven Plugin
The wsconsume tools is included in the org.jboss.ws.plugins:jaxws-tools-maven-plugin plugin. The
plugin has two goals for running the tool, wsconsume and wsconsume-test, which basically do the same
during different maven build phases (the former triggers the sources generation during generate-sources
phase, the latter during the generate-test-sources one).
The wsconsume plugin has the following parameters:
WildFly 9
Attribute
Description
Default
bindingFiles
true
${project.compileClasspathElements}
or
${project.testClasspathElements}
catalog
none
targetPackage
generated
bindingFiles
none
wsdlLocation
generated
outputDirectory
${project.build.outputDirectory}
or
${project.build.testOutputDirectory}
sourceDirectory
${project.build.directory}/wsconsume/jav
verbose
false
progress.
wsdls
n/a
extension
false
encoding
${project.build.sourceEncoding}
argLine
none
Example
<argLine>-Djava.endorsed.dirs=...</argLine>
fork
false
VM.
target
Examples
You can use wsconsume in your own project build simply referencing the jaxws-tools-maven-plugin in the
configured plugins in your pom.xml file.
The following example makes the plugin consume the test.wsdl file and generate SEI and wrappers' java
sources. The generated sources are then compiled together with the other project classes.
WildFly 9
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>jaxws-tools-maven-plugin</artifactId>
<version>1.2.0.Beta1</version>
<configuration>
<wsdls>
<wsdl>${basedir}/test.wsdl</wsdl>
</wsdls>
</configuration>
<executions>
<execution>
<goals>
<goal>wsconsume</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You can also specify multiple wsdl files, as well as force the target package, enable SOAP 1.2 binding and
turn the tool's verbose mode on:
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>jaxws-tools-maven-plugin</artifactId>
<version>1.2.0.Beta1</version>
<configuration>
<wsdls>
<wsdl>${basedir}/test.wsdl</wsdl>
<wsdl>${basedir}/test2.wsdl</wsdl>
</wsdls>
<targetPackage>foo.bar</targetPackage>
<extension>true</extension>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>wsconsume</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Finally, if the wsconsume invocation is required for consuming a wsdl to be used in your testsuite only, you
might want to use the wsconsume-test goal as follows:
WildFly 9
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>jaxws-tools-maven-plugin</artifactId>
<version>1.2.0.Beta1</version>
<configuration>
<wsdls>
<wsdl>${basedir}/test.wsdl</wsdl>
</wsdls>
</configuration>
<executions>
<execution>
<goals>
<goal>wsconsume-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Plugin stack dependencyThe plugin itself does not have an explicit dependency to a JBossWS stack, as it's
meant for being used with implementations of any supported version of the JBossWS SPI. So the user is
expected to set a dependency in his own pom.xml to the desired JBossWS stack version. The plugin will
rely on the that for using the proper tooling.
<dependencies>
<dependency>
<groupId>org.jboss.ws.cxf</groupId>
<artifactId>jbossws-cxf-client</artifactId>
<version>4.0.0.GA</version>
</dependency>
</dependencies>
Be careful when using this plugin with the Maven War Plugin as that include any project
dependency into the generated application war archive. You might want to set
<scope>provided</scope> for the JBossWS stack dependency to avoid that.
Ant Task
The wsconsume Ant task (org.jboss.ws.tools.ant.WSConsumeTask) has the following attributes:
WildFly 9
Attribute
Description
Default
fork
true
keep
false
catalog
none
package
generated
binding
none
wsdlLocation
generated
encoding
n/a
destdir
"output"
sourcedestdir
value of destdir
target
The JAX-WS specification target. Allowed values are 2.0, 2.1 and 2.2
verbose
false
wsdl
n/a
extension
false
false
Users also need to put streamBuffer.jar and stax-ex.jar to the classpath of the ant task to generate
the appropriate artefacts.
The wsdlLocation is used when creating the Service to be used by clients and will be added to the
@WebServiceClient annotation, for an endpoint implementation based on the generated service
endpoint interface you will need to manually add the wsdlLocation to the @WebService annotation
on your web service implementation and not the service endpoint interface.
Default
binding
none
jvmarg
WildFly 9
Examples
Generate JAX-WS source and classes in a separate JVM with separate directories, a custom wsdl location
attribute, and a list of binding files from foo.wsdl:
<wsconsume
fork="true"
verbose="true"
destdir="output"
sourcedestdir="gen-src"
keep="true"
wsdllocation="handEdited.wsdl"
wsdl="foo.wsdl">
<binding dir="binding-files" includes="*.xml" excludes="bad.xml"/>
</wsconsume>
wsprovide
wsprovide is a command line tool, Maven plugin and Ant task that generates portable JAX-WS artifacts for a
service endpoint implementation. It also has the option to "provide" the abstract contract for offline usage.
WildFly 9
-k, --keep
Keep/Generate Java source
-w, --wsdl
Enable WSDL file generation
-a, --address The generated port soap:address in wsdl
-c. --classpath=<path>
-o, --output=<directory>
-r, --resource=<directory>
-s, --source=<directory>
-e, --extension
-q, --quiet
-t, --show-traces
Examples
Generating wrapper classes for portable artifacts in the "generated" directory:
Maven Plugin
The wsprovide tools is included in the org.jboss.ws.plugins:jaxws-tools-maven-plugin plugin. The plugin
has two goals for running the tool, wsprovide and wsprovide-test, which basically do the same during
different Maven build phases (the former triggers the sources generation during process-classes phase, the
latter during the process-test-classes one).
The wsprovide plugin has the following parameters:
WildFly 9
Attribute
Description
resourceDirectory
Default
${project.compileClasspathElements}
or
${project.testClasspathElements}
or
${project.build.testOutputDirectory}
${project.build.directory}/wsprovide/resources
artifacts (WSDL/XSD).
sourceDirectory
${project.build.directory}/wsprovide/java
extension
false
extension.
generateWsdl
false
verbose
portSoapAddress
endpointClass
Service Endpoint
Implementation.
Examples
You can use wsprovide in your own project build simply referencing the maven-jaxws-tools-plugin in the
configured plugins in your pom.xml file.
The following example makes the plugin provide the wsdl file and artifact sources for the specified endpoint
class:
WildFly 9
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>jaxws-tools-maven-plugin</artifactId>
<version>1.2.0.Beta1</version>
<configuration>
<verbose>true</verbose>
<endpointClass>org.jboss.test.ws.plugins.tools.wsprovide.TestEndpoint</endpointClass>
<generateWsdl>true</generateWsdl>
</configuration>
<executions>
<execution>
<goals>
<goal>wsprovide</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The following example does the same, but is meant for use in your own testsuite:
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>jaxws-tools-maven-plugin</artifactId>
<version>1.2.0.Beta1</version>
<configuration>
<verbose>true</verbose>
<endpointClass>org.jboss.test.ws.plugins.tools.wsprovide.TestEndpoint2</endpointClass>
<generateWsdl>true</generateWsdl>
</configuration>
<executions>
<execution>
<goals>
<goal>wsprovide-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Plugin stack dependencyThe plugin itself does not have an explicit dependency to a JBossWS stack, as it's
meant for being used with implementations of any supported version of the JBossWS SPI. So the user is
expected to set a dependency in his ownpom.xml to the desired JBossWS stack version. The plugin will
rely on the that for using the proper tooling.
WildFly 9
<dependencies>
<dependency>
<groupId>org.jboss.ws.cxf</groupId>
<artifactId>jbossws-cxf-client</artifactId>
<version>5.0.0.CR1</version>
</dependency>
</dependencies>
Be careful when using this plugin with the Maven War Plugin as that include any project
dependency into the generated application war archive. You might want to set
<scope>provided</scope> for the JBossWS stack dependency to avoid that.
WildFly 9
Ant Task
The wsprovide ant task (org.jboss.ws.tools.ant.WSProvideTask) has the following attributes:
Attribute
Description
Default
fork
true
keep
false
destdir
"output"
value of destdir
sourcedestdir
value of destdir
extension
false
genwsdl
false
address
verbose
sei
classpath
false
Examples
Executing wsprovide in verbose mode with separate output directories for source, resources, and classes:
WildFly 9
WildFly 9
Logging
Logging of inbound and outbound messages is a common need. Different approaches are available for
achieving that:
WS Handler approach
A portable way of performing logging is writing a simple JAX-WS handler dumping the messages that are
passed in it; the handler can be added to the desired client/endpoints (programmatically / using
@HandlerChain JAX-WS annotation).
The predefined client and endpoint configuration mechanism allows user to add the logging handler to any
client/endpoint or to some of them only (in which case the @EndpointConfig annotation / JBossWS API is
required though).
System property
Setting the org.apache.cxf.logging.enabled system property to true causes the logging interceptors
to be added to any Bus instance being created on the JVM.
On WildFly, the system property is easily set by adding what follows to the standalone / domain
server configuration just after the extensions section:
<system-properties>
<property name="org.apache.cxf.logging.enabled" value="true"/>
</system-properties>
WildFly 9
* support
JBossWS includes most of the WS-* specification functionalities through the integration with Apache CXF. In
particular, the whole WS-Security Policy framework is fully supported, enabling full contract driven
configuration of complex features like WS-Security.
In details information available further down in this documentation book.
WildFly 9
Address rewrite
JBossWS allows users to configure the soap:address attribute in the wsdl contract of deployed services.
<subsystem xmlns="urn:jboss:domain:webservices:1.1"
xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:jaxwsconfig="urn:jboss:jbossws-jaxws-config:4.0">
<wsdl-host>localhost</wsdl-host>
<modify-wsdl-address>true</modify-wsdl-address>
<!-<wsdl-port>8080</wsdl-port>
<wsdl-secure-port>8443</wsdl-secure-port>
-->
</subsystem>
If the content of <soap:address> in the wsdl is a valid URL, JBossWS will not rewrite it unless
modify-wsdl-address is true. If the content of <soap:address> is not a valid URL instead, JBossWS will
always rewrite it using the attribute values given below. Please note that the variable ${jboss.bind.address}
can be used to set the address which the application is bound to at each startup.
The wsdl-secure-port and wsdl-port attributes are used to explicitly define the ports to be used for rewriting
the SOAP address. If these attributes are not set, the ports will be identified by querying the list of installed
connectors. If multiple connectors are found the port of the first connector is used.
Dynamic rewrite
When the application server is bound to multiple addresses or non-trivial real-world network architectures
cause request for different external addresses to hit the same endpoint, a static rewrite of the soap:address
may not be enough. JBossWS allows for both the soap:address in the wsdl and the wsdl address in the
console to be rewritten with the host use in the client request. This way, users always get the right wsdl
address assuming they're connecting to an instance having the endpoint they're looking for. To trigger this
behaviour, the jbossws.undefined.host value has to be specified for the wsdl-host element.
<wsdl-host>jbossws.undefined.host</wsdl-host>
<modify-wsdl-address>true</modify-wsdl-address>
Of course, when a confidential transport address is required, the addresses are always rewritten using https
protocol and the port currently configured for the https/ssl connector.
WildFly 9
<webservices>
<context-root/>?
<config-name/>?
<config-file/>?
<property>*
<name/>
<value/>
</property>
<port-component>*
<ejb-name/>
<port-component-name/>
<port-component-uri/>?
<auth-method/>?
<transport-guarantee/>?
<secure-wsdl-access/>?
</port-component>
<webservice-description>*
<webservice-description-name/>
<wsdl-publish-location/>?
</webservice-description>
</webservices>
context-root element
Element <context-root> can be used to customize context root of webservices deployment.
<webservices>
<context-root>foo</context-root>
</webservices>
<webservices>
<config-name>Standard WSSecurity Endpoint</config-name>
<config-file>META-INF/custom.xml</config-file>
</webservices>
WildFly 9
property element
<property> elements can be used to setup simple property values to configure the ws stack behavior.
Allowed property names and values are mentioned in the guide under related topics.
<property>
<name>prop.name</name>
<value>prop.value</value>
</property>
port-component element
Element <port-component> can be used to customize EJB endpoint target URI or to configure security
related properties.
<webservices>
<port-component>
<ejb-name>TestService</ejb-name>
<port-component-name>TestServicePort</port-component-name>
<port-component-uri>/*</port-component-uri>
<auth-method>BASIC</auth-method>
<transport-guarantee>NONE</transport-guarantee>
<secure-wsdl-access>true</secure-wsdl-access>
</port-component>
</webservices>
webservice-description element
Element <webservice-description> can be used to customize (override) webservice WSDL publish
location.
<webservices>
<webservice-description>
<webservice-description-name>TestService</webservice-description-name>
<wsdl-publish-location>file:///bar/foo.wsdl</wsdl-publish-location>
</webservice-description>
</webservices>
WildFly 9
((BindingProvider)proxy).getRequestContext().put("schema-validation-enabled", true);
import javax.jws.WebService;
import org.apache.cxf.annotations.SchemaValidation;
@WebService(...)
@SchemaValidation
public class ValidatingHelloImpl implements Hello {
...
}
Alternatively, any endpoint and client running in-container can be associated to a JBossWS predefined
configuration having the schema-validation-enabled property set to true in the referenced config file.
Finally, JBossWS also allows for server-wide (default) setup of schema validation by using the
Standard-Endpoint-Config and Standard-Client-Config special configurations (which apply to any client /
endpoint unless a different configuration is specified for them)
<subsystem xmlns="urn:jboss:domain:webservices:1.2">
...
<endpoint-config name="Standard-Endpoint-Config">
<property name="schema-validation-enabled" value="true"/>
</endpoint-config>
...
<client-config name="Standard-Client-Config">
<property name="schema-validation-enabled" value="true"/>
</client-config>
</subsystem>
WildFly 9
JAXB Introductions
As Kohsuke Kawaguchi wrote on his blog, one common complaint from the JAXB users is the lack of
support for binding 3rd party classes. The scenario is this: you are trying to annotate your classes with JAXB
annotations to make it XML bindable, but some of the classes are coming from libraries and JDK, and thus
you cannot put necessary JAXB annotations on it.
To solve this JAXB has been designed to provide hooks for programmatic introduction of annotations to the
runtime.
This is currently leveraged by the JBoss JAXB Introductions project, using which users can define
annotations in XML and make JAXB see those as if those were in the class files (perhaps coming from 3rd
party libraries).
Take a look at the JAXB Introductions page on the wiki and at the examples in the sources.
WildFly 9
Overview
JBossWS permits extra setup configuration data to be predefined and associated with an endpoint or a
client. Configurations can include JAX-WS handlers and key/value property declarations that control
JBossWS and Apache CXF internals. Predefined configurations can be used for JAX-WS client and JAX-WS
endpoint setup.
Configurations can be defined in the webservice subsystem and in an application's deployment descriptor
file. There can be many configuration definitions in the webservice subsystem and in an application. Each
configuration must have a name that is unique within the server. Configurations defined in an application are
local to the application. Endpoint implementations declare the use of a specific configuration through the use
of the org.jboss.ws.api.annotation.EndpointConfig annotation. An endpoint configuration
defined in the webservices subsystem is available to all deployed applications on the server container and
can be referenced by name in the annotation. An endpoint configuration defined in an application must be
referenced by both deployment descriptor file name and configuration name by the annotation.
Handlers
Each endpoint configuration may be associated with zero or more PRE and POST handler chains. Each
handler chain may include JAXWS handlers. For outbound messages the PRE handler chains are executed
before any handler that is attached to the endpoint using the standard means, such as with annotation
@HandlerChain, and POST handler chains are executed after those objects have executed. For inbound
messages the POST handler chains are executed before any handler that is attached to the endpoint using
the standard means and the PRE handler chains are executed after those objects have executed.
Assigning configurations
Endpoints and clients are assigned configuration through different means. Users can explicitly require a
given configuration or rely on container defaults. The assignment process can be split up as follows:
Explicit assignment through annotations (for endpoints) or API programmatic usage (for clients)
Automatic assignment of configurations from default descriptors
Automatic assignment of configurations from container
WildFly 9
<javaee:handler-name>Authorization Handler</javaee:handler-name>
<javaee:handler-class>org.jboss.test.ws.jaxws.jbws3282.AuthorizationHandler</javaee:handler-class></javaee:han
Similarly, client configurations can be specified in descriptors (still implementing the schema mentioned
above):
WildFly 9
WildFly 9
Handlers classloading
When setting a server-wide handler, please note the handler class needs to be available through each ws
deployment classloader. As a consequence proper module dependencies might need to be specified in the
deployments that are going to leverage a given predefined configuration. A shortcut is to add a dependency
to the module containing the handler class in one of the modules which are already automatically set as
dependencies to any deployment, for instance org.jboss.ws.spi.
Examples
JBoss AS 7.2 default configurations
<subsystem xmlns="urn:jboss:domain:webservices:2.0">
<!-- ... -->
<endpoint-config name="Standard-Endpoint-Config"/>
<endpoint-config name="Recording-Endpoint-Config">
<pre-handler-chain name="recording-handlers" protocol-bindings="##SOAP11_HTTP ##SOAP11_HTTP_MTOM
##SOAP12_HTTP ##SOAP12_HTTP_MTOM">
<handler name="RecordingHandler" class="org.jboss.ws.common.invocation.RecordingServerHandler"/>
</pre-handler-chain>
</endpoint-config>
<client-config name="Standard-Client-Config"/>
</subsystem>
<property>
<property-name>ws-security.callback-handler</property-name>
<property-value>org.jboss.test.ws.jaxws.samples.wsse.policy.basic.KeystorePasswordCallback</property-value></p
WildFly 9
EndpointConfig annotation
Once a configuration is available to a given application, the
org.jboss.ws.api.annotation.EndpointConfig annotation is used to assign an endpoint
configuration to a JAX-WS endpoint implementation. When assigning a configuration that is defined in the
webservices subsystem only the configuration name is specified. When assigning a configuration that is
defined in the application, the relative path to the deployment descriptor and the configuration name must be
specified.
WildFly 9
JAXWS Feature
The most practical way of setting a configuration is using
org.jboss.ws.api.configuration.ClientConfigFeature, a JAXWS Feature extension provided
by JBossWS:
import org.jboss.ws.api.configuration.ClientConfigFeature;
...
Service service = Service.create(wsdlURL, serviceName);
Endpoint port = service.getPort(Endpoint.class, new
ClientConfigFeature("META-INF/my-client-config.xml", "Custom Client Config"));
port.echo("Kermit");
... or ....
port = service.getPort(Endpoint.class, new ClientConfigFeature("META-INF/my-client-config.xml",
"Custom Client Config"), true); //setup properties too from the configuration
port.echo("Kermit");
... or ...
port = service.getPort(Endpoint.class, new ClientConfigFeature(null, testConfigName)); //reads
from current container configurations if available
port.echo("Kermit");
JBossWS parses the specified configuration file. The configuration file must be found as a resource by the
classloader of the current thread. The jbossws-jaxws-config schema defines the descriptor contents and is
included in the jbossws-spi artifact.
Explicit setup through API
Alternatively, JBossWS API comes with facility classes that can be used for assigning configurations when
building a client. JAXWS handlers read from client configurations as follows:
WildFly 9
import org.jboss.ws.api.configuration.ClientConfigUtil;
import org.jboss.ws.api.configuration.ClientConfigurer;
...
Service service = Service.create(wsdlURL, serviceName);
Endpoint port = service.getPort(Endpoint.class);
BindingProvider bp = (BindingProvider)port;
ClientConfigUtil.setConfigHandlers(bp, "META-INF/my-client-config.xml", "Custom Client Config
1");
port.echo("Kermit");
...
ClientConfigurer configurer = ClientConfigUtil.resolveClientConfigurer();
configurer.setConfigHandlers(bp, "META-INF/my-client-config.xml", "Custom Client Config 2");
port.echo("Kermit");
...
configurer.setConfigHandlers(bp, "META-INF/my-client-config.xml", "Custom Client Config 3");
port.echo("Kermit");
...
configurer.setConfigHandlers(bp, null, "Container Custom Client Config"); //reads from current
container configurations if available
port.echo("Kermit");
WildFly 9
import org.jboss.ws.api.configuration.ClientConfigUtil;
import org.jboss.ws.api.configuration.ClientConfigurer;
...
Service service = Service.create(wsdlURL, serviceName);
Endpoint port = service.getPort(Endpoint.class);
ClientConfigUtil.setConfigProperties(port, "META-INF/my-client-config.xml", "Custom Client
Config 1");
port.echo("Kermit");
...
ClientConfigurer configurer = ClientConfigUtil.resolveClientConfigurer();
configurer.setConfigProperties(port, "META-INF/my-client-config.xml", "Custom Client Config 2");
port.echo("Kermit");
...
configurer.setConfigProperties(port, "META-INF/my-client-config.xml", "Custom Client Config 3");
port.echo("Kermit");
...
configurer.setConfigProperties(port, null, "Container Custom Client Config"); //reads from
current container configurations if available
port.echo("Kermit");
The default ClientConfigurer implementation parses the specified configuration file, if any, after having
resolved it as a resources using the current thread context classloader. The jbossws-jaxws-config schema
defines the descriptor contents and is included in the jbossws-spi artifact.
WildFly 9
Authentication
Authentication
Specify the security domain
Use BindingProvider to set principal/credential
Using HTTP Basic Auth for security
JASPI Authentication
WildFly 9
Authentication
Here the simplest way to authenticate a web service user with JBossWS is explained.
First we secure the access to the SLSB as we would do for normal (non web service) invocations: this can
be easily done through the @RolesAllowed, @PermitAll, @DenyAll annotation. The allowed user roles can
be set with these annotations both on the bean class and on any of its business methods.
@Stateless
@RolesAllowed("friend")
public class EndpointEJB implements EndpointInterface
{
...
}
Similarly POJO endpoints are secured the same way as we do for normal web applications in web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>friend</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>friend</role-name>
</security-role>
WildFly 9
@Stateless
@SecurityDomain("JBossWS")
@RolesAllowed("friend")
public class EndpointEJB implements EndpointInterface
{
...
}
<jboss-web>
<security-domain>JBossWS</security-domain>
</jboss-web>
The security domain as well as its the authentication and authorization mechanisms are defined differently
depending on the application server version in use.
WildFly 9
@Stateless
@SecurityDomain("JBossWS")
@RolesAllowed("friend")
@WebContext(contextRoot="/my-cxt", urlPattern="/*", authMethod="BASIC",
transportGuarantee="NONE", secureWSDLAccess=false)
public class EndpointEJB implements EndpointInterface
{
...
}
For POJO endpoints, we modify the web.xml adding the auth-method element:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Test Realm</realm-name>
</login-config>
JASPI Authentication
A Java Authentication SPI (JASPI) provider can be configured in WildFly security subsystem to authenticate
SOAP messages:
<security-domain name="jaspi">
<authentication-jaspi>
<login-module-stack name="jaas-lm-stack">
<login-module code="UsersRoles" flag="required">
<module-option name="usersProperties" value="jbossws-users.properties"/>
<module-option name="rolesProperties" value="jbossws-roles.properties"/>
</login-module>
</login-module-stack>
<auth-module code="org.jboss.wsf.stack.cxf.jaspi.module.UsernameTokenServerAuthModule"
login-module-stack-ref="jaas-lm-stack"/>
</authentication-jaspi>
</security-domain>
For further information on configuring security domains in WildFly, please refer to here.
WildFly 9
To enable JASPI authentication, the endpoint deployment needs to specify the security domain to use; that
can be done in two different ways:
Setting the jaspi.security.domain property in the jboss-webservices.xml descriptor
If the JASPI security domain is specified in both jboss-webservices.xml and config file
referenced by @EndpointConfig annotation, the JASPI security domain specified in
jboss-webservices.xml will take precedence.
WildFly 9
WildFly 9
WildFly 9
Portable applications
WildFly is much more then a servlet container; it actually provides users with a fully compliant target platform
for Java EE applications.
Generally speaking, users are encouraged to write portable applications by relying only on JAX-WS
specification whenever possible. That would by the way ensure easy migrations to and from other compliant
platforms. Being a Java EE container, WildFly already comes with a JAX-WS compliant implementation,
which is basically Apache CXF plus the JBossWS-CXF integration layer. So users just need to write their
JAX-WS application; no need for embedding any Apache CXF or any ws related dependency library in user
deployments. Please refer to the JAX-WS User Guide section of the documentation for getting started.
WS-* usage (including WS-Security, WS-Addressing, WS-ReliableMessaging, ...) should also be configured
in the most portable way; that is by relying on proper WS-Policy assertions on the endpoint WSDL contracts,
so that client and endpoint configuration is basically a matter of setting few ws context properties. The WS-*
related sections of this documentation cover all the details on configuring applications making use of WS-*
through policies.
As a consequence of the reasoning above, the JBossWS-CXF integration is currently built directly on the
Apache CXF API and aims at allowing users to configure webservice clients and endpoints without Spring
descriptors.
WildFly 9
Bus usage
Creating a Bus instance
Most of the Apache CXF features are configurable using the org.apache.cxf.Bus class. While for basic
JAX-WS usage the user might never need to explicitly deal with Bus, using Apache CXF specific features
generally requires getting a handle to a org.apache.cxf.Bus instance. This can happen on client side as
well as in a ws endpoint or handler business code.
New Bus instances are produced by the currently configured org.apache.cxf.BusFactory
implementation the following way:
The algorithm for selecting the actual implementation of BusFactory to be used leverages the Service API,
basically looking for optional configurations in META-INF/services/... location using the current thread
context classloader. JBossWS-CXF integration comes with its own implementation of BusFactory,
org.jboss.wsf.stack.cxf.client.configuration.JBossWSBusFactory, that allows for
seamless setup of JBossWS customizations on top of Apache CXF. So, assuming the JBossWS-CXF
libraries are available in the current thread context classloader, the JBossWSBusFactory is automatically
retrieved by the BusFactory.newInstance() call above.
JBossWS users willing to explicitly use functionalities of org.apache.cxf.bus.CXFBusFactory, get the
same API with JBossWS additions through JBossWSBusFactory:
WildFly 9
WildFly 9
Thread bus strategy (THREAD_BUS)
Each time the vanilla JAXWS api is used to create a Bus, the JBossWS-CXF integration will automatically
make sure a Bus is currently associated to the current thread in the BusFactory. If that's not the case, a new
Bus is created and linked to the current thread (to prevent the user from relying on the default Bus). The
Apache CXF engine will then create the client using the current thread Bus.
This is the default strategy, and the most straightforward one in Java SE environments; it lets users
automatically reuse a previously created Bus instance and allows using customized Bus that can possibly be
created and associated to the thread before building up a JAXWS client.
The drawback of the strategy is that the link between the Bus instance and the thread needs to be eventually
cleaned up (when not needed anymore). This is really evident in a Java EE environment (hence when
running in-container), as threads from pools (e.g. serving web requests) are re-used.
When relying on this strategy, the safest approach to be sure of cleaning up the link is to surround the
JAXWS client with a try/finally block as below:
try {
Service service = Service.create(wsdlURL, serviceQName);
MyEndpoint port = service.getPort(MyEndpoint.class);
//...
} finally {
BusFactory.setThreadDefaultBus(null);
// OR (if you don't need the bus and the client anymore)
Bus bus = BusFactory.getThreadDefaultBus(false);
bus.shutdown(true);
}
WildFly 9
Thread context classloader bus strategy (TCCL_BUS)
The last strategy is to have the bus created for serving the client be associated to the current thread context
classloader (TCCL). That basically means the same Bus instance is shared by JAXWS clients running when
the same TCCL is set. This is particularly interesting as each web application deployment usually has its
own context classloader, so this strategy is possibly a way to keep the number of created Bus instances
bound to the application number in WildFly container.
If there's a bus already associated to the current thread before the JAXWS client creation, that is
automatically restored when returning control to the user; in other words, the bus corresponding to the
current thread context classloader will be used only for the created JAXWS client but won't stay associated
to the current thread at the end of the process. If the thread was not associated to any bus before the client
creation, a new bus will be created (and later user for any other client built with this strategy and the same
TCCL in place); no bus will be associated to the thread at the end of the client creation.
Strategy configuration
Users can request a given Bus selection strategy to be used for the client being built by specifying one of the
following JBossWS features (which extend javax.xml.ws.WebServiceFeature):
Feature
Strategy
org.jboss.wsf.stack.cxf.client.UseThreadBusFeature THREAD_BUS
org.jboss.wsf.stack.cxf.client.UseNewBusFeature
NEW_BUS
org.jboss.wsf.stack.cxf.client.UseTCCLBusFeature
TCCL_BUS
If no feature is explicitly specified, the system default strategy is used, which can be modified through the
org.jboss.ws.cxf.jaxws-client.bus.strategy system property when starting the JVM. The valid
values for the property are THREAD_BUS, NEW_BUS and TCCL_BUS. The default is THREAD_BUS.
WildFly 9
JBossWS-CXF integration comes with a set of allowed property names to control Apache CXF internals.
WorkQueue configuration
Apache CXF uses WorkQueue instances for dealing with some operations (e.g. @Oneway requests
processing). A WorkQueueManager is installed in the Bus as an extension and allows for adding / removing
queues as well as controlling the existing ones.
On server side, queues can be provided by using the cxf.queue.<queue-name>.* properties in
jboss-webservices.xml (e.g. cxf.queue.default.maxQueueSize for controlling the max queue
size of the default workqueue). At deployment time, the JBossWS integration can add new instances of
AutomaticWorkQueueImpl to the currently configured WorkQueueManager; the properties below are used to
fill in parameter into the AutomaticWorkQueueImpl constructor:
Property
Default value
cxf.queue.<queue-name>.maxQueueSize
256
cxf.queue.<queue-name>.initialThreads 0
cxf.queue.<queue-name>.highWaterMark
25
cxf.queue.<queue-name>.lowWaterMark
cxf.queue.<queue-name>.dequeueTimeout 120000
Policy alternative selector
The Apache CXF policy engine supports different strategies to deal with policy alternatives. JBossWS-CXF
integration currently defaults to the MaximalAlternativeSelector, but still allows for setting different selector
implementation using the cxf.policy.alternativeSelector property in jboss-webservices.xml.
WildFly 9
MBean management
Apache CXF allows managing its MBean objects that are installed into the WildFly MBean server. The
feature is enabled on a deployment basis through the cxf.management.enabled property in
jboss-webservices.xml. The cxf.management.installResponseTimeInterceptors property
can also be used to control installation of CXF response time interceptors, which are added by default when
enabling MBean management, but might not be desired in some cases. Here is an example:
Schema validation
Schema validation of exchanged messages can also be enabled in jboss-webservices.xml. Further
details available here.
Interceptors
The jboss-webservices.xml descriptor also allows specifying the cxf.interceptors.in and
cxf.interceptors.out properties; those allows declaring interceptors to be attached to the Bus instance
that's created for serving the deployment.
WildFly 9
Features
The jboss-webservices.xml descriptor also allows specifying the cxf.features property; that allows
declaring features to be attached to any endpoint belonging to the Bus instance that's created for serving the
deployment.
Discovery enablement
WS-Discovery support can be turned on in jboss-webservices for the current deployment. Further
details available here.
<property>
<property-name>cxf.interceptors.in</property-name>
<property-value>org.jboss.test.ws.jaxws.cxf.interceptors.EndpointInterceptor,org.jboss.test.ws.jaxws.cxf.inter
A new instance of each specified interceptor class will be added to the client or endpoint the configuration is
assigned to. The interceptor classes must have a no-argument constructor.
WildFly 9
A new instance of each specified feature class will be added to the client or endpoint the configuration is
assigned to. The feature classes must have a no-argument constructor.
WildFly 9
Value
org.jboss.Foo
##foo.par
34
##bar
org.jboss.Bar
##bar.color blue
would result into the stack installing two feature instances, the same that would have been created by
import org.Bar;
import org.Foo;
...
Foo foo = new Foo();
foo.setPar(34);
Bar bar = new Bar();
bar.setColor("blue");
The mechanism assumes that the classes are valid beans with proper getter and setter methods; value
objects are cast to the correct primitive type by inspecting the class definition. Nested beans can of course
be configured.
WildFly 9
HTTPConduit configuration
HTTP transport setup in Apache CXF is achieved through
org.apache.cxf.transport.http.HTTPConduit configurations. When running on top of the
JBossWS integration, conduits can be programmatically modified using the Apache CXF API as follows:
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
//set chunking threshold before using a JAX-WS port client
...
HTTPConduit conduit = (HTTPConduit)ClientProxy.getClient(port).getConduit();
HTTPClientPolicy client = conduit.getClient();
client.setChunkingThreshold(8192);
...
Users can also control the default values for the most common HTTPConduit parameters by setting specific
system properties; the provided values will override Apache CXF defaut values.
Property
Description
cxf.client.allowChunking
cxf.client.chunkingThreshold
An integer value to tell Apache CXF the threshold at which switching from
non-chunking to chunking mode.
cxf.client.connectionTimeout
A long value to tell Apache CXF how many milliseconds to set the
connection timeout to
cxf.client.receiveTimeout
A long value to tell Apache CXF how many milliseconds to set the receive
timeout to
cxf.client.connection
cxf.tls-client.disableCNCheck A boolean to tell Apache CXF whether disabling CN host name check or
not
The vanilla Apache CXF defaults apply when the system properties above are not set.
Addressing
JBoss Web Services inherits full WS-Addressing capabilities from the underlying Apache CXF
implementation. Apache CXF provides support for 2004-08 and 1.0 versions of WS-Addressing.
WildFly 9
Enabling WS-Addressing
WS-Addressing can be turned on in multiple standard ways:
consuming a WSDL contract that specifies a WS-Addressing assertion / policy
using the @javax.xml.ws.soap.Addressing annotation
using the javax.xml.ws.soap.AddressingFeature feature
[http://www.w3.org/2005/02/addressing/wsdl]UsingAddressing
[http://schemas.xmlsoap.org/ws/2004/08/addressing/policy]UsingAddressing
[http://www.w3.org/2006/05/addressing/wsdl]UsingAddressing
[http://www.w3.org/2007/05/addressing/metadata]Addressing
Addressing Policy
The WS-Addressing support is also perfectly integrated with the Apache CXF WS-Policy engine.
This basically means that the WSDL contract generation for code-first endpoint deployment is policy-aware:
users can annotate endpoints with the @javax.xml.ws.soap.Addressing annotation and expect the
published WSDL contract to contain proper WS-Addressing policy (assuming no wsdlLocation is specified
in the endpoint's @WebService annotation).
Similarly, on client side users do not need to manually specify the
javax.xml.ws.soap.AddressingFeature feature, as the policy engine is able to properly process the
WS-Addressing policy in the consumed WSDL and turn on addressing as requested.
Example
Here is an example showing how to simply enable WS-Addressing through WS-Policy.
Endpoint
WildFly 9
A simple JAX-WS endpoint is prepared using a java-first approach; WS-Addressing is enforced through
@Addressing annotation and no wsdlLocation is provided in @WebService:
package org.jboss.test.ws.jaxws.samples.wsa;
import javax.jws.WebService;
import javax.xml.ws.soap.Addressing;
import org.jboss.logging.Logger;
@WebService
(
portName = "AddressingServicePort",
serviceName = "AddressingService",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsaddressing",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsa.ServiceIface"
)
@Addressing(enabled=true, required=true)
public class ServiceImpl implements ServiceIface
{
private Logger log = Logger.getLogger(this.getClass());
public String sayHello(String name)
{
return "Hello " + name + "!";
}
}
The WSDL contract that's generated at deploy time and published looks like this:
WildFly 9
<wsdl:definitions ....>
...
<wsdl:binding name="AddressingServiceSoapBinding" type="tns:ServiceIface">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsaw:UsingAddressing wsdl:required="true"/>
<wsp:PolicyReference URI="#AddressingServiceSoapBinding_WSAM_Addressing_Policy"/>
<wsdl:operation name="sayHello">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="sayHello">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHelloResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="AddressingService">
<wsdl:port binding="tns:AddressingServiceSoapBinding" name="AddressingServicePort">
<soap:address location="http://localhost:8080/jaxws-samples-wsa"/>
</wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="AddressingServiceSoapBinding_WSAM_Addressing_Policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsam:Addressing xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
<wsp:Policy/>
</wsam:Addressing>
</wsp:Policy>
</wsdl:definitions>
Client
Since the WS-Policy engine is on by default, the client side code is basically a pure JAX-WS client app:
WildFly 9
Security
WS-Security overview
JBoss WS-Security support
Apache CXF WS-Security implementation
WS-Security Policy support
JBossWS configuration additions
Apache CXF annotations
Examples
Signature and encryption
Endpoint
Client
Endpoint serving multiple clients
Authentication and authorization
Endpoint
Client
Secure transport
Secure conversation
Security overview
WS-Security provides the means to secure your services beyond transport level protocols such as HTTPS.
Through a number of standards such as XML-Encryption, and headers defined in the WS-Security standard,
it allows you to:
Pass authentication tokens between services.
Encrypt messages or parts of messages.
Sign messages.
Timestamp messages.
WS-Security makes heavy use of public and private key cryptography. It is helpful to understand these
basics to really understand how to configure WS-Security. With public key cryptography, a user has a pair of
public and private keys. These are generated using a large prime number and a key function.
The keys are related mathematically, but cannot be derived from one another. With these keys we can
encrypt messages. For example, if Bob wants to send a message to Alice, he can encrypt a message using
her public key. Alice can then decrypt this message using her private key. Only Alice can decrypt this
message as she is the only one with the private key.
WildFly 9
Messages can also be signed. This allows you to ensure the authenticity of the message. If Alice wants to
send a message to Bob, and Bob wants to be sure that it is from Alice, Alice can sign the message using her
private key. Bob can then verify that the message is from Alice by using her public key.
WildFly 9
WS-SecurityPolicy describes the actions that are required to securely communicate with a service advertised
in a given WSDL contract. The WSDL bindings / operations reference WS-Policy fragments with the security
requirements to interact with the service. The WS-SecurityPolicy specification allows for specifying things
like asymmetric/symmetric keys, using transports (https) for encryption, which parts/headers to encrypt or
sign, whether to sign then encrypt or encrypt then sign, whether to include timestamps, whether to use
derived keys, etc.
However some mandatory configuration elements are not covered by WS-SecurityPolicy, basically because
they're not meant to be public / part of the published endpoint contract; those include things such as
keystore locations, usernames and passwords, etc. Apache CXF allows configuring these elements either
through Spring xml descriptors or using the client API / annotations. Below is the list of supported
configuration properties:
ws-security.username
ws-security.password
ws-security.callback-handler
ws-security.signature.properties
ws-security.encryption.properties The properties file/object that contains the WSS4J properties for
configuring the encryption keystore and crypto objects
ws-security.signature.username
The username or alias for the key in the signature keystore that will be
used. If not specified, it uses the the default alias set in the properties
file. If that's also not set, and the keystore only contains a single key,
that key will be used.
ws-security.encryption.username The username or alias for the key in the encryption keystore that will be
used. If not specified, it uses the the default alias set in the properties
file. If that's also not set, and the keystore only contains a single key,
that key will be used. For the web service provider, the useReqSigCert
keyword can be used to accept (encrypt to) any client whose public key
is in the service's truststore (defined in
ws-security.encryption.properties.)
ws-security.signature.crypto
Instead of specifying the signature properties, this can point to the full
WSS4J Crypto object. This can allow easier "programmatic"
configuration of the Crypto information."
ws-security.encryption.crypto
Instead of specifying the encryption properties, this can point to the full
WSS4J Crypto object. This can allow easier "programmatic"
configuration of the Crypto information."
ws-security.enable.streaming
WildFly 9
Here is an example of configuration using the client API:
Please refer to the Apache CXF documentation for additional configuration details.
WildFly 9
import javax.jws.WebService;
import org.jboss.ws.api.annotation.EndpointConfig;
@WebService
(
portName = "SecurityServicePort",
serviceName = "SecurityService",
wsdlLocation = "WEB-INF/wsdl/SecurityService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.basic.ServiceIface"
)
@EndpointConfig(configFile = "WEB-INF/jaxws-endpoint-config.xml", configName = "Custom
WS-Security Endpoint")
public class ServiceImpl implements ServiceIface
{
public String sayHello()
{
return "Secure Hello World!";
}
}
@WebService(
...
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.properties", value = "bob.properties"),
@EndpointProperty(key = "ws-security.encryption.properties", value = "bob.properties"),
@EndpointProperty(key = "ws-security.signature.username", value = "bob"),
@EndpointProperty(key = "ws-security.encryption.username", value = "alice"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.basic.KeystorePasswordCallback")
}
)
public class ServiceImpl implements ServiceIface {
...
}
Examples
In this section some sample of WS-Security service endpoints and clients are provided. Please note they're
only meant as tutorials; you should really careful isolate the ws-security policies / assertion that best suite
your security needs before going to production environment.
WildFly 9
The following sections provide directions and examples on understanding some of the
configuration options for WS-Security engine. Please note the implementor remains responsible for
assessing the application requirements and choosing the most suitable security policy for them.
WildFly 9
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SecurityService">
<port name="SecurityServicePort" binding="tns:SecurityServicePortBinding">
<soap:address location="http://localhost:8080/jaxws-samples-wssePolicy-sign-encrypt"/>
</port>
</service>
<wsp:Policy wsu:Id="SecurityServiceSignThenEncryptPolicy"
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:AsymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssX509V1Token11/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
<wsp:Policy>
<sp:WssX509V1Token11/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:TripleDesRsa15/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:EncryptSignature/>
<sp:OnlySignEntireHeadersAndBody/>
<sp:SignBeforeEncrypting/>
</wsp:Policy>
</sp:AsymmetricBinding>
<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<sp:Body/>
</sp:SignedParts>
<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<sp:Body/>
</sp:EncryptedParts>
WildFly 9
<sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:MustSupportRefIssuerSerial/>
</wsp:Policy>
</sp:Wss10>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</definitions>
The service endpoint can be generated using the wsconsume tool and then enriched with a
@EndpointConfig annotation:
package org.jboss.test.ws.jaxws.samples.wsse.policy.basic;
import javax.jws.WebService;
import org.jboss.ws.api.annotation.EndpointConfig;
@WebService
(
portName = "SecurityServicePort",
serviceName = "SecurityService",
wsdlLocation = "WEB-INF/wsdl/SecurityService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.basic.ServiceIface"
)
@EndpointConfig(configFile = "WEB-INF/jaxws-endpoint-config.xml", configName = "Custom
WS-Security Endpoint")
public class ServiceImpl implements ServiceIface
{
public String sayHello()
{
return "Secure Hello World!";
}
}
The referenced jaxws-endpoint-config.xml descriptor is used to provide a custom endpoint configuration with
the required server side configuration properties; this tells the engine which certificate / key to use for
signature / signature verification and for encryption / decryption:
WildFly 9
... the bob.properties configuration file is also referenced above; it includes the WSS4J Crypto properties
which in turn link to the keystore file, type and the alias/password to use for accessing it:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=password
org.apache.ws.security.crypto.merlin.keystore.alias=bob
org.apache.ws.security.crypto.merlin.keystore.file=bob.jks
A callback handler for the letting Apache CXF access the keystore is also provided:
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsse.policy.basic;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class KeystorePasswordCallback implements CallbackHandler {
private Map<String, String> passwords = new HashMap<String, String>();
public KeystorePasswordCallback() {
passwords.put("alice", "password");
passwords.put("bob", "password");
}
/**
* It attempts to get the password from the private
* alias/passwords map.
*/
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
String pass = passwords.get(pc.getIdentifier());
if (pass != null) {
pc.setPassword(pass);
return;
}
}
}
/**
* Add an alias/password pair to the callback mechanism.
*/
public void setAliasPassword(String alias, String password) {
passwords.put(alias, password);
}
}
Assuming the bob.jks keystore has been properly generated and contains Bob's (server) full key
(private/certificate + public key) as well as Alice's (client) public key, we can proceed to packaging the
endpoint. Here is the expected content (the endpoint is a POJO one in a war archive, but EJB3 endpoints in
jar archives are of course also supported):
WildFly 9
As you can see, the jaxws classes generated by the tools are of course also included, as well as a basic
web.xml referencing the endpoint bean:
WildFly 9
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 17.0-b16 (Sun Microsystems Inc.)
Dependencies: org.apache.ws.security
WildFly 9
Client
You start by consuming the published WSDL contract using the wsconsume tool on client side too. Then you
simply invoke the the endpoint as a standard JAX-WS one:
As you can see, the WS-Security properties are set in the request context. Here the
KeystorePasswordCallback is the same as on server side above, you might want/need different
implementation in real world scenarios, of course.
The alice.properties file is the client side equivalent of the server side bob.properties and references the
alice.jks keystore file, which has been populated with Alice's (client) full key (private/certificate + public key)
as well as Bob's (server) public key.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=password
org.apache.ws.security.crypto.merlin.keystore.alias=alice
org.apache.ws.security.crypto.merlin.keystore.file=META-INF/alice.jks
The Apache CXF WS-Policy engine will digest the security requirements in the contract and ensure a valid
secure communication is in place for interacting with the server endpoint.
Endpoint serving multiple clients
The server side configuration described above implies the endpoint is configured for serving a given client
which a service agreement has been established for. In some real world scenarios though, the same server
might be expected to be able to deal with (including decrypting and encrypting) messages coming from and
being sent to multiple clients. Apache CXF supports that through the useReqSigCert value for the
ws-security.encryption.username configuration parameter.
Of course the referenced server side keystore then needs to contain the public key of all the clients that are
expected to be served.
WildFly 9
Apache CXF provides means for setting basic password callback handlers on both client and server sides to
set/check passwords; the ws-security.username and ws-security.callback-handler properties can be used
similarly as shown in the signature and encryption example. Things become more interesting when requiring
a given user to be authenticated (and authorized) against a security domain on the target application server.
On server side, you need to install two additional interceptors that act as bridges towards the application
server authentication layer:
an interceptor for performing authentication and populating a valid SecurityContext; the provided
interceptor should extend
org.apache.cxf.ws.interceptor.security.AbstractUsernameTokenInInterceptor, in particular JBossWS
integration comes with org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingInterceptor for
this;
an interceptor for performing authorization; CXF requires that to extend
org.apache.cxf.interceptor.security.AbstractAuthorizingInInterceptor, for instance the
SimpleAuthorizingInterceptor can be used for simply mapping endpoint operations to allowed roles.
So, here follows an example of WS-SecurityPolicy endpoint using Username Token Profile for authenticating
through the application server security domain system.
Endpoint
As in the other example, we start with a wsdl contract containing the proper WS-Security Policy:
WildFly 9
<operation name="sayHello">
<input message="tns:sayHello"/>
<output message="tns:sayHelloResponse"/>
</operation>
<operation name="greetMe">
<input message="tns:greetMe"/>
<output message="tns:greetMeResponse"/>
</operation>
</portType>
<binding name="SecurityServicePortBinding" type="tns:ServiceIface">
<wsp:PolicyReference URI="#SecurityServiceUsernameUnsecureTransportPolicy"/>
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="sayHello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="greetMe">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SecurityService">
<port name="SecurityServicePort" binding="tns:SecurityServicePortBinding">
<soap:address location="http://localhost:8080/jaxws-samples-wsse-username-jaas"/>
</port>
</service>
<wsp:Policy wsu:Id="SecurityServiceUsernameUnsecureTransportPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</definitions>
WildFly 9
If you want to send hash / digest passwords, you can use a policy such as what follows:
<wsp:Policy wsu:Id="SecurityServiceUsernameHashPasswordPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipien
<wsp:Policy>
<sp:HashPassword/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Please note the specified JBoss security domain needs to be properly configured for computing
digests.
The service endpoint can be generated using the wsconsume tool and then enriched with a
@EndpointConfig annotation and @InInterceptors annotation to add the two interceptors mentioned
above for JAAS integration:
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsse.policy.jaas;
import javax.jws.WebService;
import org.apache.cxf.interceptor.InInterceptors;
import org.jboss.ws.api.annotation.EndpointConfig;
@WebService
(
portName = "SecurityServicePort",
serviceName = "SecurityService",
wsdlLocation = "WEB-INF/wsdl/SecurityService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.jaas.ServiceIface"
)
@EndpointConfig(configFile = "WEB-INF/jaxws-endpoint-config.xml", configName = "Custom
WS-Security Endpoint")
@InInterceptors(interceptors = {
"org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingPolicyInterceptor",
"org.jboss.test.ws.jaxws.samples.wsse.policy.jaas.POJOEndpointAuthorizationInterceptor"}
)
public class ServiceImpl implements ServiceIface
{
public String sayHello()
{
return "Secure Hello World!";
}
public String greetMe()
{
return "Greetings!";
}
}
The POJOEndpointAuthorizationInterceptor is included into the deployment and deals with the
roles cheks:
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsse.policy.jaas;
import java.util.HashMap;
import java.util.Map;
import org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor;
public class POJOEndpointAuthorizationInterceptor extends SimpleAuthorizingInterceptor
{
public POJOEndpointAuthorizationInterceptor()
{
super();
readRoles();
}
private void readRoles()
{
//just an example, this might read from a configuration file or such
Map<String, String> roles = new HashMap<String, String>();
roles.put("sayHello", "friend");
roles.put("greetMe", "snoopies");
setMethodRolesMap(roles);
}
}
The jaxws-endpoint-config.xml descriptor is used to provide a custom endpoint configuration with the
required server side configuration properties; in particular for this Username Token case that's just a CXF
configuration option for leaving the username token validation to the configured interceptors:
In order for requiring a given JBoss security domain to be used to protect access to the endpoint (a POJO
one in this case), we declare that in a jboss-web.xml descriptor (the JBossWS security domain is used):
WildFly 9
The endpoint is packaged into a war archive, including the JAXWS classes generated by wsconsume:
WildFly 9
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 17.0-b16 (Sun Microsystems Inc.)
Dependencies: org.apache.ws.security,org.apache.cxf
WildFly 9
Client
Here too you start by consuming the published WSDL contract using the wsconsume tool. Then you simply
invoke the the endpoint as a standard JAX-WS one:
The UsernamePasswordCallback class is shown below and is responsible for setting the passwords on
client side just before performing the invocations:
package org.jboss.test.ws.jaxws.samples.wsse.policy.jaas;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class UsernamePasswordCallback implements CallbackHandler
{
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
WSPasswordCallback pc = (WSPasswordCallback)callbacks[0];
if ("kermit".equals(pc.getIdentifier()))
pc.setPassword("thefrog");
}
}
If everything has been done properly, you should expect to calls to sayHello() fail when done with user
"snoopy" and pass with user "kermit" (and credential "thefrog"); moreover, you should get an authorization
error when trying to call greetMe() with user "kermit", as that does not have the "snoopies" role.
Secure transport
Another quite common use case is using WS-Security Username Token Profile over a secure transport
(HTTPS). A scenario like this is implemented similarly to what's described in the previous example, except
for few differences explained below.
First of all, here is an excerpt of a wsdl wth a sample security policy for Username Token over HTTPS:
...
WildFly 9
<binding name="SecurityServicePortBinding" type="tns:ServiceIface">
<wsp:PolicyReference URI="#SecurityServiceBindingPolicy"/>
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="sayHello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="SecurityService">
<port name="SecurityServicePort" binding="tns:SecurityServicePortBinding">
<soap:address location="https://localhost:8443/jaxws-samples-wsse-policy-username"/>
</port>
</service>
<wsp:Policy wsu:Id="SecurityServiceBindingPolicy">
<wsp:ExactlyOne>
<wsp:All>
<foo:unknownPolicy xmlns:foo="http://cxf.apache.org/not/a/policy"/>
</wsp:All>
<wsp:All>
<wsaws:UsingAddressing xmlns:wsaws="http://www.w3.org/2006/05/addressing/wsdl"/>
<sp:TransportBinding>
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128/>
</wsp:Policy>
</sp:AlgorithmSuite>
</wsp:Policy>
</sp:TransportBinding>
<sp:Wss10>
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier/>
</wsp:Policy>
</sp:Wss10>
<sp:SignedSupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
WildFly 9
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
The endpoint then needs of course to be actually available on HTTPS only, so we have a web.xml setting
the transport-guarantee such as below:
WildFly 9
Secure conversation
Apache CXF supports WS-SecureConversation specification, which is about improving performance by
allowing client and server to negotiate initial security keys to be used for later communication
encryption/signature. This is done by having two policies in the wsdl contract, an outer one setting the
security requirements to actually communicate with the endpoint and a bootstrap one, related to the
communication for establishing the secure conversation keys. The client will be automatically sending an
initial message to the server for negotiating the keys, then the actual communication to the endpoint takes
place. As a consequence, Apache CXF needs a way to specify which WS-Security configuration properties
are intended for the bootstrap policy and which are intended for the actual service policy. To accomplish this,
properties intended for the bootstrap policy are appended with .sct.
...
((BindingProvider)proxy).getRequestContext().put("ws-security.signature.username.sct", "alice");
((BindingProvider)proxy).getRequestContext().put("ws-security.encryption.username.sct", "bob");
...
@WebService(
...
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.encryption.properties.sct", value =
"bob.properties"),
@EndpointProperty(key = "ws-security.signature.properties.sct", value = "bob.properties"),
...
}
)
public class ServiceImpl implements ServiceIface {
...
}
WildFly 9
WildFly 9
Trust overview
WS-Trust is a Web service specification that defines extensions to WS-Security. It is a general framework
for implementing security in a distributed system. The standard is based on a centralized Security Token
Service, STS, which is capable of authenticating clients and issuing tokens containing various kinds of
authentication and authorization data. The specification describes a protocol used for issuance, exchange,
and validation of security tokens, however the following specifications play an important role in the WS-Trust
architecture: WS-SecurityPolicy 1.2, SAML 2.0, Username Token Profile, X.509 Token Profile, SAML Token
Profile, and Kerberos Token Profile.
The WS-Trust extensions address the needs of applications that span multiple domains and requires the
sharing of security keys by providing a standards based trusted third party web service (STS) to broker trust
relationships between a Web service requester and a Web service provider. This architecture also alleviates
the pain of service updates that require credential changes by providing a common location for this
information. The STS is the common access point from which both the requester and provider retrieves and
verifies security tokens.
There are three main components of the WS-Trust specification.
The Security Token Service (STS), a web service that issues, renews, and validates security tokens.
The message formats for security token requests and responses.
The mechanisms for key exchange
WildFly 9
WildFly 9
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsaws="http://www.w3.org/2005/08/addressing"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
xmlns:t="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
<types>
<xsd:schema>
<xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy"
schemaLocation="SecurityService_schema1.xsd"/>
</xsd:schema>
</types>
<message name="sayHello">
<part name="parameters" element="tns:sayHello"/>
</message>
<message name="sayHelloResponse">
<part name="parameters" element="tns:sayHelloResponse"/>
</message>
<portType name="ServiceIface">
<operation name="sayHello">
<input message="tns:sayHello"/>
<output message="tns:sayHelloResponse"/>
</operation>
</portType>
<!-The wsp:PolicyReference binds the security requirments on all the STS endpoints.
The wsp:Policy wsu:Id="#AsymmetricSAML2Policy" element is defined later in this file.
-->
<binding name="SecurityServicePortBinding" type="tns:ServiceIface">
<wsp:PolicyReference URI="#AsymmetricSAML2Policy" />
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="sayHello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
<wsp:PolicyReference URI="#Input_Policy" />
</input>
<output>
<soap:body use="literal"/>
<wsp:PolicyReference URI="#Output_Policy" />
</output>
</operation>
</binding>
<service name="SecurityService">
<port name="SecurityServicePort" binding="tns:SecurityServicePortBinding">
<soap:address
location="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust/SecurityService"/>
</port>
</service>
<wsp:Policy wsu:Id="AsymmetricSAML2Policy">
<wsp:ExactlyOne>
<wsp:All>
<!-The wsam:Addressing element, indicates that the endpoints of this
web service MUST conform to the WS-Addressing specification.
The
WildFly 9
attribute wsp:Optional="false" enforces this assertion.
-->
<wsam:Addressing wsp:Optional="false">
<wsp:Policy />
</wsam:Addressing>
<!-The sp:AsymmetricBinding element indicates that security is provided
at the SOAP layer. A public/private key combinations is required to
protect the message. The initiator will use its private key to sign
the message and the recipients public key is used to encrypt the message.
The recipient of the message will use its private key to decrypt it and
initiators public key to verify the signature.
-->
<sp:AsymmetricBinding>
<wsp:Policy>
<!-The sp:InitiatorToken element specifies the elements required in
generating the initiator request to the ws-provider's service.
-->
<sp:InitiatorToken>
<wsp:Policy>
<!-The sp:IssuedToken element asserts that a SAML 2.0 security token is
expected from the STS using a public key type.
The
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
attribute instructs the runtime to include the initiator's public key
with every message sent to the recipient.
The sp:RequestSecurityTokenTemplate element directs that all of the
children of this element will be copied directly into the body of the
RequestSecurityToken (RST) message that is sent to the STS when the
initiator asks the STS to issue a token.
-->
<sp:IssuedToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<sp:RequestSecurityTokenTemplate>
<t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType>
<t:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey</t:KeyType>
</sp:RequestSecurityTokenTemplate>
<wsp:Policy>
<sp:RequireInternalReference />
</wsp:Policy>
<!-The sp:Issuer element defines the STS's address and endpoint information
This information is used by the STSClient.
-->
<sp:Issuer>
<wsaws:Address>http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts/SecurityTokenService</wsaw
<wsaws:Metadata xmlns:wsdli="http://www.w3.org/2006/01/wsdl-instance"
wsdli:wsdlLocation="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts/SecurityTokenService?
<wsaw:ServiceName xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:stsns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/"
WildFly 9
EndpointName="UT_Port">stsns:SecurityTokenService</wsaw:ServiceName>
</wsaws:Metadata>
</sp:Issuer>
</sp:IssuedToken>
</wsp:Policy>
</sp:InitiatorToken>
<!-The sp:RecipientToken element asserts the type of public/private key-pair
expected from the recipient.
The
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
attribute indicates that the initiator's public key will never be included
in the reply messages.
The sp:WssX509V3Token10 element indicates that an X509 Version 3 token
should be used in the message.
-->
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:WssX509V3Token10 />
<sp:RequireIssuerSerialReference />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
<!-The sp:Layout element,
WildFly 9
handled by CXF.
-->
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefIssuerSerial />
<sp:MustSupportRefThumbprint />
<sp:MustSupportRefEncryptedKey />
</wsp:Policy>
</sp:Wss11>
<!-The sp:Trust13 element declares controls for WS-Trust 1.3 options.
They are policy assertions related to exchanges specifically with
client and server challenges and entropy behaviors. Again these are
normally handled by CXF.
-->
<sp:Trust13>
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust13>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Input_Policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body />
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Output_Policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body />
WildFly 9
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"
/>
<sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</definitions>
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy"
)
public interface ServiceIface
{
@WebMethod
String sayHello();
}
WildFly 9
The first EndpointProperty statement in the listing is declaring the user's name to use for the message
signature. It is used as the alias name in the keystore to get the user's cert and private key for signature.
The next two EndpointProperty statements declares the Java properties file that contains the (Merlin) crypto
configuration information. In this case both for signing and encrypting the messages. WSS4J reads this file
and extra required information for message handling. The last EndpointProperty statement declares the
ServerCallbackHandler implementation class. It is used to obtain the user's password for the certificates in
the keystore file.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service;
import javax.jws.WebService;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
@WebService
(
portName = "SecurityServicePort",
serviceName = "SecurityService",
wsdlLocation = "WEB-INF/wsdl/SecurityService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServiceIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "myservicekey"),
@EndpointProperty(key = "ws-security.signature.properties", value =
"serviceKeystore.properties"),
@EndpointProperty(key = "ws-security.encryption.properties", value =
"serviceKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServerCallbackHandler")
})
public class ServiceImpl implements ServiceIface
{
public String sayHello()
{
return "WS-Trust Hello World!";
}
}
WildFly 9
ServerCallbackHandler
ServerCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the password for
the private key in the keystore. This class enables CXF to retrieve the password of the user name to use for
the message signature. A certificates' password is not discoverable. The creator of the certificate must
record the password he assigns and provide it when requested through the CallbackHandler. In this
scenario skpass is the password for user myservicekey.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service;
import java.util.HashMap;
import java.util.Map;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
public class ServerCallbackHandler extends PasswordCallbackHandler
{
public ServerCallbackHandler()
{
super(getInitMap());
}
private static Map<String, String> getInitMap()
{
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("myservicekey", "skpass");
return passwords;
}
}
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=sspass
org.apache.ws.security.crypto.merlin.keystore.alias=myservicekey
org.apache.ws.security.crypto.merlin.keystore.file=servicestore.jks
WildFly 9
MANIFEST.MF
When deployed on WildFly this application requires access to the JBossWs and CXF APIs provided in
module org.jboss.ws.cxf.jbossws-cxf-client. The dependency statement directs the server to provide them at
deployment.
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client
WildFly 9
<xs:element name='RequestSecurityTokenResponse'
type='wst:AbstractRequestSecurityTokenType' />
<xs:complexType name='AbstractRequestSecurityTokenType' >
<xs:sequence>
<xs:any namespace='##any' processContents='lax' minOccurs='0' maxOccurs='unbounded' />
</xs:sequence>
<xs:attribute name='Context' type='xs:anyURI' use='optional' />
<xs:anyAttribute namespace='##other' processContents='lax' />
</xs:complexType>
<xs:element name='RequestSecurityTokenCollection'
type='wst:RequestSecurityTokenCollectionType' />
<xs:complexType name='RequestSecurityTokenCollectionType' >
<xs:sequence>
<xs:element name='RequestSecurityToken' type='wst:AbstractRequestSecurityTokenType'
minOccurs='2' maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
<xs:element name='RequestSecurityTokenResponseCollection'
type='wst:RequestSecurityTokenResponseCollectionType' />
<xs:complexType name='RequestSecurityTokenResponseCollectionType' >
<xs:sequence>
<xs:element ref='wst:RequestSecurityTokenResponse' minOccurs='1' maxOccurs='unbounded'
/>
</xs:sequence>
<xs:anyAttribute namespace='##other' processContents='lax' />
</xs:complexType>
</xs:schema>
</wsdl:types>
<!-- WS-Trust defines the following GEDs -->
<wsdl:message name="RequestSecurityTokenMsg">
<wsdl:part name="request" element="wst:RequestSecurityToken" />
</wsdl:message>
<wsdl:message name="RequestSecurityTokenResponseMsg">
<wsdl:part name="response"
element="wst:RequestSecurityTokenResponse" />
</wsdl:message>
<wsdl:message name="RequestSecurityTokenCollectionMsg">
<wsdl:part name="requestCollection"
element="wst:RequestSecurityTokenCollection"/>
</wsdl:message>
<wsdl:message name="RequestSecurityTokenResponseCollectionMsg">
<wsdl:part name="responseCollection"
element="wst:RequestSecurityTokenResponseCollection"/>
</wsdl:message>
<!-- This portType an example of a Requestor (or other) endpoint that
Accepts SOAP-based challenges from a Security Token Service -->
<wsdl:portType name="WSSecurityRequestor">
<wsdl:operation name="Challenge">
<wsdl:input message="tns:RequestSecurityTokenResponseMsg"/>
<wsdl:output message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
</wsdl:portType>
WildFly 9
WildFly 9
The wsp:PolicyReference binds the security requirments on all the STS endpoints.
The wsp:Policy wsu:Id="UT_policy" element is later in this file.
-->
<wsdl:binding name="UT_Binding" type="wstrust:STS">
<wsp:PolicyReference URI="#UT_policy" />
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Issue">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue" />
<wsdl:input>
<wsp:PolicyReference
URI="#Input_policy" />
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference
URI="#Output_policy" />
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Validate">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Validate" />
<wsdl:input>
<wsp:PolicyReference
URI="#Input_policy" />
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference
URI="#Output_policy" />
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Cancel">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Cancel" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Renew">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Renew" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeyExchangeToken">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/KeyExchangeToken"
WildFly 9
/>
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="RequestCollection">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/RequestCollection" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SecurityTokenService">
<wsdl:port name="UT_Port" binding="tns:UT_Binding">
<soap:address location="http://localhost:8080/SecurityTokenService/UT" />
</wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="UT_policy">
<wsp:ExactlyOne>
<wsp:All>
<!-The sp:UsingAddressing element, indicates that the endpoints of this
web service conforms to the WS-Addressing specification. More detail
can be found here: [http://www.w3.org/TR/2006/CR-ws-addr-wsdl-20060529]
-->
<wsap10:UsingAddressing/>
<!-The sp:SymmetricBinding element indicates that security is provided
at the SOAP layer and any initiator must authenticate itself by providing
WSS UsernameToken credentials.
-->
<sp:SymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<!-In a symmetric binding, the keys used for encrypting and signing in both
directions are derived from a single key, the one specified by the
sp:ProtectionToken element. The sp:X509Token sub-element declares this
key to be a X.509 certificate and the
IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never"
attribute adds the requirement that the token MUST NOT be included in
any messages sent between the initiator and the recipient; rather, an
external reference to the token should be used. Lastly the WssX509V3Token10
sub-element declares that the Username token presented by the initiator
should be compliant with Web Services Security UsernameToken Profile
1.0 specification. [
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf ]
-->
WildFly 9
<sp:ProtectionToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:RequireDerivedKeys />
<sp:RequireThumbprintReference />
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:ProtectionToken>
<!-The sp:AlgorithmSuite element, requires the Basic256 algorithm suite
be used in performing cryptographic operations.
-->
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<!-The sp:Layout element,
WildFly 9
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<!-The sp:Wss11 element declares WSS: SOAP Message Security 1.1 options
to be supported by the STS.
-->
<sp:Wss11
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier />
<sp:MustSupportRefIssuerSerial />
<sp:MustSupportRefThumbprint />
<sp:MustSupportRefEncryptedKey />
</wsp:Policy>
</sp:Wss11>
<!-The sp:Trust13 element declares controls for WS-Trust 1.3 options.
They are policy assertions related to exchanges specifically with
client and server challenges and entropy behaviors.
WildFly 9
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Output_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="From"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="Action"
Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</wsdl:definitions>
STS Implementation
The Apache CXF's STS, SecurityTokenServiceProvider, is a web service provider that is compliant with the
protocols and functionality defined by the WS-Trust specification. It has a modular architecture. Many of its
components are configurable or replaceable and there are many optional features that are enabled by
implementing and configuring plug-ins. Users can customize their own STS by extending from
SecurityTokenServiceProvider and overriding the default settings. Extensive information about the CXF's
STS configurable and pluggable components can be found here.
WildFly 9
This STS implementation class, SimpleSTS, is a POJO that extends from SecurityTokenServiceProvider.
Note that the class is defined with a WebServiceProvider annotation and not a WebService annotation. This
annotation defines the service as a Provider-based endpoint, meaning it supports a more
messaging-oriented approach to Web services. In particular, it signals that the exchanged messages will be
XML documents of some type. SecurityTokenServiceProvider is an implementation of the
javax.xml.ws.Provider interface. In comparison the WebService annotation defines a (service endpoint
interface) SEI-based endpoint which supports message exchange via SOAP envelopes.
As was done in the ServiceImpl class, the WSS4J annotations EndpointProperties and EndpointProperty are
providing endpoint configuration for the CXF runtime. This was previous described here.
The InInterceptors annotation is used to specify a JBossWS integration interceptor to be used for
authenticating incoming requests; JAAS integration is used here for authentication, the username/passoword
coming from the UsernameToken in the ws-requester message are used for authenticating the requester
against a security domain on the application server hosting the STS deployment.
In this implementation we are customizing the operations of token issuance, token validation and their static
properties.
StaticSTSProperties is used to set select properties for configuring resources in the STS. You may think this
is a duplication of the settings made with the WSS4J annotations. The values are the same but the
underlaying structures being set are different, thus this information must be declared in both places.
The setIssuer setting is important because it uniquely identifies the issuing STS. The issuer string is
embedded in issued tokens and, when validating tokens, the STS checks the issuer string value.
Consequently, it is important to use the issuer string in a consistent way, so that the STS can recognize the
tokens that it has issued.
The setEndpoints call allows the declaration of a set of allowed token recipients by address. The addresses
are specified as reg-ex patterns.
TokenIssueOperation and TokenValidateOperation have a modular structure. This allows custom behaviors
to be injected into the processing of messages. In this case we are overriding the
SecurityTokenServiceProvider's default behavior and performing SAML token processing and validation.
CXF provides an implementation of a SAMLTokenProvider and SAMLTokenValidator which we are using
rather than writing our own.
Learn more about the SAMLTokenProvider here.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.xml.ws.WebServiceProvider;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.interceptor.InInterceptors;
import org.apache.cxf.sts.StaticSTSProperties;
WildFly 9
import org.apache.cxf.sts.operation.TokenIssueOperation;
import org.apache.cxf.sts.operation.TokenValidateOperation;
import org.apache.cxf.sts.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
import org.apache.cxf.sts.token.validator.SAMLTokenValidator;
import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider;
@WebServiceProvider(serviceName = "SecurityTokenService",
portName = "UT_Port",
targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/",
wsdlLocation = "WEB-INF/wsdl/ws-trust-1.4-service.wsdl")
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "mystskey"),
@EndpointProperty(key = "ws-security.signature.properties", value =
"stsKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.STSCallbackHandler"),
//to let the JAAS integration deal with validation through the interceptor below
@EndpointProperty(key = "ws-security.validate.token", value = "false")
})
@InInterceptors(interceptors =
{"org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingPolicyInterceptor"})
public class SampleSTS extends SecurityTokenServiceProvider
{
public SampleSTS() throws Exception
{
super();
StaticSTSProperties props = new StaticSTSProperties();
props.setSignaturePropertiesFile("stsKeystore.properties");
props.setSignatureUsername("mystskey");
props.setCallbackHandlerClass(STSCallbackHandler.class.getName());
props.setIssuer("DoubleItSTSIssuer");
List<ServiceMBean> services = new LinkedList<ServiceMBean>();
StaticService service = new StaticService();
service.setEndpoints(Arrays.asList(
"http://localhost:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService",
"http://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService",
"http://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService"
));
services.add(service);
TokenIssueOperation issueOperation = new TokenIssueOperation();
issueOperation.setServices(services);
issueOperation.getTokenProviders().add(new SAMLTokenProvider());
issueOperation.setStsProperties(props);
TokenValidateOperation validateOperation = new TokenValidateOperation();
validateOperation.getTokenValidators().add(new SAMLTokenValidator());
validateOperation.setStsProperties(props);
this.setIssueOperation(issueOperation);
this.setValidateOperation(validateOperation);
}
WildFly 9
}
STSCallbackHandler
STSCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the password for
the private key in the keystore. This class enables CXF to retrieve the password of the user name to use for
the message signature.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.sts;
import java.util.HashMap;
import java.util.Map;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
public class STSCallbackHandler extends PasswordCallbackHandler
{
public STSCallbackHandler()
{
super(getInitMap());
}
private static Map<String, String> getInitMap()
{
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("mystskey", "stskpass");
return passwords;
}
}
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=stsspass
org.apache.ws.security.crypto.merlin.keystore.file=stsstore.jks
WildFly 9
MANIFEST.MF
When deployed on WildFly, this application requires access to the JBossWs and CXF APIs provided in
modules org.jboss.ws.cxf.jbossws-cxf-client and org.apache.cxf. The Apache CXF internals,
org.apache.cxf.impl, are needed to build the STS configuration in the SampleSTS constructor. The
dependency statement directs the server to provide them at deployment.
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client,org.apache.cxf.impl
Security Domain
The STS requires a JBoss security domain be configured. The jboss-web.xml descriptor declares a named
security domain,"JBossWS-trust-sts" to be used by this service for authentication. This security domain
requires two properties files and the addition of a security-domain declaration in the JBoss server
configuration file.
For this scenario the domain needs to contain user alice, password clarinet, and role friend. See the listings
below for jbossws-users.properties and jbossws-roles.properties. In addition the following XML must be
added to the JBoss security subsystem in the server configuration file. Replace " SOME_PATH" with
appropriate information.
<security-domain name="JBossWS-trust-sts">
<authentication>
<login-module code="UsersRoles" flag="required">
<module-option name="usersProperties" value="/SOME_PATH/jbossws-users.properties"/>
<module-option name="unauthenticatedIdentity" value="anonymous"/>
<module-option name="rolesProperties" value="/SOME_PATH/jbossws-roles.properties"/>
</login-module>
</authentication>
</security-domain>
jboss-web.xml
jbossws-users.properties
jbossws-roles.properties
WildFly 9
WildFly 9
There is an alternate method of setting up the STSCLient. The user may provide their own instance of the
STSClient. The CXF code will use this object and not auto-generate one. This is used in the ActAs and
OnBehalfOf examples. When providing the STSClient in this way, the user must provide a
org.apache.cxf.Bus for it and the configuration keys must not have the ".it" suffix.
WildFly 9
ClientCallbackHandler
ClientCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the password for
the private key in the keystore. This class enables CXF to retrieve the password of the user name to use for
the message signature. Note that "alice" and her password have been provided here. This information is
not in the (JKS) keystore but provided in the WildFly security domain. It was declared in file
jbossws-users.properties.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class ClientCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
if ("myclientkey".equals(pc.getIdentifier())) {
pc.setPassword("ckpass");
break;
} else if ("alice".equals(pc.getIdentifier())) {
pc.setPassword("clarinet");
break;
}
}
}
}
}
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=cspass
org.apache.ws.security.crypto.merlin.keystore.alias=myclientkey
org.apache.ws.security.crypto.merlin.keystore.file=META-INF/clientstore.jks
PicketLink STS
WildFly 9
PicketLink provides facilities for building up an alternative to the Apache CXF Security Token Service
implementation.
Similarly to the previous implementation, the STS is served through a WebServiceProvider annotated POJO:
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust;
import javax.annotation.Resource;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.WebServiceProvider;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.interceptor.InInterceptors;
import org.picketlink.identity.federation.core.wstrust.PicketLinkSTS;
@WebServiceProvider(serviceName = "PicketLinkSTS", portName = "PicketLinkSTSPort",
targetNamespace = "urn:picketlink:identity-federation:sts", wsdlLocation =
"WEB-INF/wsdl/PicketLinkSTS.wsdl")
@ServiceMode(value = Service.Mode.MESSAGE)
//be sure to have dependency on org.apache.cxf module when on AS7, otherwise Apache CXF
annotations are ignored
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "mystskey"),
@EndpointProperty(key = "ws-security.signature.properties", value = "stsKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.STSCallbackHandler"),
@EndpointProperty(key = "ws-security.validate.token", value = "false") //to let the JAAS
integration deal with validation through the interceptor below
})
@InInterceptors(interceptors =
)
public class PicketLinkSTService extends PicketLinkSTS {
@Resource
public void setWSC(WebServiceContext wctx)
Unknown macro: { this.context = wctx; }
}
The @WebServiceProvider annotation references the following WS-Policy enabled wsdl contract; please
note the wsdl operations, messages and such must match the PicketLinkSTS implementation:
<?xml version="1.0"?>
<wsdl:definitions name="PicketLinkSTS" targetNamespace="urn:picketlink:identity-federation:sts"
xmlns:tns="urn:picketlink:identity-federation:sts"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsap10="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
WildFly 9
xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/">
<wsdl:types>
<xs:schema elementFormDefault="qualified"
targetNamespace='http://docs.oasis-open.org/ws-sx/ws-trust/200512'
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name='RequestSecurityToken' type='wst:AbstractRequestSecurityTokenType' />
<xs:element name='RequestSecurityTokenResponse'
type='wst:AbstractRequestSecurityTokenType' />
<xs:complexType name='AbstractRequestSecurityTokenType' >
<xs:sequence>
<xs:any namespace='##any' processContents='lax' minOccurs='0' maxOccurs='unbounded' />
</xs:sequence>
<xs:attribute name='Context' type='xs:anyURI' use='optional' />
<xs:anyAttribute namespace='##other' processContents='lax' />
</xs:complexType>
<xs:element name='RequestSecurityTokenCollection'
type='wst:RequestSecurityTokenCollectionType' />
<xs:complexType name='RequestSecurityTokenCollectionType' >
<xs:sequence>
<xs:element name='RequestSecurityToken' type='wst:AbstractRequestSecurityTokenType'
minOccurs='2' maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
<xs:element name='RequestSecurityTokenResponseCollection'
type='wst:RequestSecurityTokenResponseCollectionType' />
<xs:complexType name='RequestSecurityTokenResponseCollectionType' >
<xs:sequence>
<xs:element ref='wst:RequestSecurityTokenResponse' minOccurs='1' maxOccurs='unbounded'
/>
</xs:sequence>
<xs:anyAttribute namespace='##other' processContents='lax' />
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="RequestSecurityTokenMsg">
<wsdl:part name="request" element="wst:RequestSecurityToken" />
</wsdl:message>
<wsdl:message name="RequestSecurityTokenResponseCollectionMsg">
<wsdl:part name="responseCollection"
element="wst:RequestSecurityTokenResponseCollection"/>
</wsdl:message>
<wsdl:portType name="SecureTokenService">
<wsdl:operation name="IssueToken">
<wsdl:input wsap10:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsap10:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTRC/IssueFinal"
message="tns:RequestSecurityTokenResponseCollectionMsg"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="STSBinding" type="tns:SecureTokenService">
<wsp:PolicyReference URI="#UT_policy" />
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="IssueToken">
<soap12:operation soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"
WildFly 9
style="document"/>
<wsdl:input>
<wsp:PolicyReference URI="#Input_policy" />
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference URI="#Output_policy" />
<soap12:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="PicketLinkSTS">
<wsdl:port name="PicketLinkSTSPort" binding="tns:STSBinding">
<soap12:address location="http://localhost:8080/picketlink-sts/PicketLinkSTS"/>
</wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="UT_policy">
<wsp:ExactlyOne>
<wsp:All>
<wsap10:UsingAddressing/>
<sp:SymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:RequireDerivedKeys />
<sp:RequireThumbprintReference />
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:ProtectionToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
<sp:EncryptSignature />
<sp:OnlySignEntireHeadersAndBody />
</wsp:Policy>
</sp:SymmetricBinding>
<sp:SignedSupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
WildFly 9
<wsp:Policy>
<sp:WssUsernameToken10 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss11
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier />
<sp:MustSupportRefIssuerSerial />
<sp:MustSupportRefThumbprint />
<sp:MustSupportRefEncryptedKey />
</wsp:Policy>
</sp:Wss11>
<sp:Trust13
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust13>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Input_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="From"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="Action"
Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Output_policy">
<wsp:ExactlyOne>
WildFly 9
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="From"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing" />
<sp:Header Name="Action"
Namespace="http://www.w3.org/2005/08/addressing" />
</sp:SignedParts>
<sp:EncryptedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body />
</sp:EncryptedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</wsdl:definitions>
Differently from the Apache CXF STS example described above, the PicketLink based STS gets its
configuration from a picketlink-sts.xml descriptor which must be added in WEB-INF into the deployment;
please refer to the PicketLink documentation for further information:
WildFly 9
<PicketLinkSTS xmlns="urn:picketlink:identity-federation:config:1.0"
STSName="PicketLinkSTS" TokenTimeout="7200" EncryptToken="false">
<KeyProvider ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
<Auth Key="KeyStoreURL" Value="stsstore.jks"/>
<Auth Key="KeyStorePass" Value="stsspass"/>
<Auth Key="SigningKeyAlias" Value="mystskey"/>
<Auth Key="SigningKeyPass" Value="stskpass"/>
<ValidatingAlias
Key="http://localhost:8080/jaxws-samples-wsse-policy-trust/SecurityService"
Value="myservicekey"/>
</KeyProvider>
<TokenProviders>
<TokenProvider
ProviderClass="org.picketlink.identity.federation.core.wstrust.plugins.saml.SAML11TokenProvider"
TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"
TokenElement="Assertion"
TokenElementNS="urn:oasis:names:tc:SAML:1.0:assertion"/>
<TokenProvider
ProviderClass="org.picketlink.identity.federation.core.wstrust.plugins.saml.SAML20TokenProvider"
TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"
TokenElement="Assertion"
TokenElementNS="urn:oasis:names:tc:SAML:2.0:assertion"/>
</TokenProviders>
</PicketLinkSTS>
Finally, the PicketLink alternative approach of course requires different WildFly module dependencies to be
declared in the MANIFEST.MF:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.6.0_26-b03 (Sun Microsystems Inc.)
Dependencies: org.apache.ws.security,org.apache.cxf,org.picketlink
WildFly 9
WildFly 9
The ActAs feature is used in scenarios that require composite delegation. It is commonly used in multi-tiered
systems where an application calls a service on behalf of a logged in user or a service calls another service
on behalf of the original caller.
ActAs is nothing more than a new sub-element in the RequestSecurityToken (RST). It provides additional
information about the original caller when a token is negotiated with the STS. The ActAs element usually
takes the form of a token with identity claims such as name, role, and authorization code, for the client to
access the service.
The ActAs scenario is an extension of the basic WS-Trust scenario. In this example the ActAs service calls
the ws-service on behalf of a user. There are only a couple of additions to the basic scenario's code. An
ActAs web service provider and callback handler have been added. The ActAs web services' WSDL
imposes the same security policies as the ws-provider. UsernameTokenCallbackHandler is new. It is a utility
that generates the content for the ActAs element. And lastly there are a couple of code additions in the STS
to support the ActAs request.
Web service provider
This section examines the web service elements from the basic WS-Trust scenario that have been changed
to address the needs of the ActAs example. The components are
ActAs web service provider's WSDL
ActAs web service provider's Interface and Implementation classes.
ActAsCallbackHandler class
UsernameTokenCallbackHandler
Crypto properties and keystore files
MANIFEST.MF
Web service provider WSDL
The ActAs web service provider's WSDL is a clone of the ws-provider's WSDL. The wsp:Policy section is
the same. There are changes to the service endpoint, targetNamespace, portType, binding name, and
service.
WildFly 9
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy"
)
public interface ActAsServiceIface
{
@WebMethod
String sayHello();
}
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.trust.STSClient;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServiceIface;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared.WSTrustAppUtils;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
@WebService
(
portName = "ActAsServicePort",
serviceName = "ActAsService",
wsdlLocation = "WEB-INF/wsdl/ActAsService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/actaswssecuritypolicy",
WildFly 9
endpointInterface =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas.ActAsServiceIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "myactaskey"),
@EndpointProperty(key = "ws-security.signature.properties", value =
"actasKeystore.properties"),
@EndpointProperty(key = "ws-security.encryption.properties", value =
"actasKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas.ActAsCallbackHandler")
})
public class ActAsServiceImpl implements ActAsServiceIface
{
public String sayHello() {
try {
ServiceIface proxy = setupService();
return "ActAs " + proxy.sayHello();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
private ServiceIface setupService()throws MalformedURLException {
ServiceIface proxy = null;
Bus bus = BusFactory.newInstance().createBus();
try {
BusFactory.setThreadDefaultBus(bus);
final String serviceURL = "http://" + WSTrustAppUtils.getServerHost() +
":8080/jaxws-samples-wsse-policy-trust/SecurityService";
final QName serviceName = new
QName("http://www.jboss.org/jbossws/ws-extensions/wssecuritypolicy", "SecurityService");
final URL wsdlURL = new URL(serviceURL + "?wsdl");
Service service = Service.create(wsdlURL, serviceName);
proxy = (ServiceIface) service.getPort(ServiceIface.class);
Map<String, Object> ctx = ((BindingProvider) proxy).getRequestContext();
ctx.put(SecurityConstants.CALLBACK_HANDLER, new ActAsCallbackHandler());
ctx.put(SecurityConstants.SIGNATURE_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource("actasKeystore.properties" ));
ctx.put(SecurityConstants.SIGNATURE_USERNAME, "myactaskey" );
ctx.put(SecurityConstants.ENCRYPT_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource("../../META-INF/clientKeystore.properties"
));
ctx.put(SecurityConstants.ENCRYPT_USERNAME, "myservicekey");
STSClient stsClient = new STSClient(bus);
Map<String, Object> props = stsClient.getProperties();
props.put(SecurityConstants.USERNAME, "alice");
props.put(SecurityConstants.ENCRYPT_USERNAME, "mystskey");
WildFly 9
props.put(SecurityConstants.STS_TOKEN_USERNAME, "myactaskey" );
props.put(SecurityConstants.STS_TOKEN_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource("actasKeystore.properties" ));
props.put(SecurityConstants.STS_TOKEN_USE_CERT_FOR_KEYINFO, "true");
ctx.put(SecurityConstants.STS_CLIENT, stsClient);
} finally {
bus.shutdown(true);
}
return proxy;
}
}
ActAsCallbackHandler
ActAsCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the password for
the private key in the keystore. This class enables CXF to retrieve the password of the user name to use for
the message signature. This class has been revised to return the passwords for this service, myactaskey
and the "actas" user, alice.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.actas;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
import java.util.HashMap;
import java.util.Map;
public class ActAsCallbackHandler extends PasswordCallbackHandler {
public ActAsCallbackHandler()
{
super(getInitMap());
}
private static Map<String, String> getInitMap()
{
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("myactaskey", "aspass");
passwords.put("alice", "clarinet");
return passwords;
}
}
UsernameTokenCallbackHandler
The ActAs and OnBeholdOf sub-elements of the RequestSecurityToken are required to be defined as WSSE
Username Tokens. This utility generates the properly formated element.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared;
import org.apache.cxf.helpers.DOMUtils;
WildFly 9
import org.apache.cxf.message.Message;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.trust.delegation.DelegationCallback;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.message.token.UsernameToken;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;
import java.util.Map;
/**
* A utility to provide the 3 different input parameter types for jaxws property
* "ws-security.sts.token.act-as" and "ws-security.sts.token.on-behalf-of".
* This implementation obtains a username and password via the jaxws property
* "ws-security.username" and "ws-security.password" respectively, as defined
* in SecurityConstants. It creates a wss UsernameToken to be used as the
* delegation token.
*/
public class UsernameTokenCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof DelegationCallback) {
DelegationCallback callback = (DelegationCallback) callbacks[i];
Message message = callback.getCurrentMessage();
String username =
(String)message.getContextualProperty(SecurityConstants.USERNAME);
String password =
(String)message.getContextualProperty(SecurityConstants.PASSWORD);
if (username != null) {
Node contentNode = message.getContent(Node.class);
Document doc = null;
if (contentNode != null) {
doc = contentNode.getOwnerDocument();
} else {
doc = DOMUtils.createDocument();
}
UsernameToken usernameToken = createWSSEUsernameToken(username,password, doc);
callback.setToken(usernameToken.getElement());
}
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
}
}
/**
* Provide UsernameToken as a string.
WildFly 9
* @param ctx
* @return
*/
public String getUsernameTokenString(Map<String, Object> ctx){
Document doc = DOMUtils.createDocument();
String result = null;
String username = (String)ctx.get(SecurityConstants.USERNAME);
String password = (String)ctx.get(SecurityConstants.PASSWORD);
if (username != null) {
UsernameToken usernameToken = createWSSEUsernameToken(username,password, doc);
result = toString(usernameToken.getElement().getFirstChild().getParentNode());
}
return result;
}
/**
*
* @param username
* @param password
* @return
*/
public String getUsernameTokenString(String username, String password){
Document doc = DOMUtils.createDocument();
String result = null;
if (username != null) {
UsernameToken usernameToken = createWSSEUsernameToken(username,password, doc);
result = toString(usernameToken.getElement().getFirstChild().getParentNode());
}
return result;
}
/**
* Provide UsernameToken as a DOM Element.
* @param ctx
* @return
*/
public Element getUsernameTokenElement(Map<String, Object> ctx){
Document doc = DOMUtils.createDocument();
Element result = null;
UsernameToken usernameToken = null;
String username = (String)ctx.get(SecurityConstants.USERNAME);
String password = (String)ctx.get(SecurityConstants.PASSWORD);
if (username != null) {
usernameToken = createWSSEUsernameToken(username,password, doc);
result = usernameToken.getElement();
}
return result;
}
/**
*
* @param username
* @param password
* @return
*/
public Element getUsernameTokenElement(String username, String password){
Document doc = DOMUtils.createDocument();
Element result = null;
WildFly 9
UsernameToken usernameToken = null;
if (username != null) {
usernameToken = createWSSEUsernameToken(username,password, doc);
result = usernameToken.getElement();
}
return result;
}
private UsernameToken createWSSEUsernameToken(String username, String password, Document doc)
{
UsernameToken usernameToken = new UsernameToken(true, doc,
(password == null)? null: WSConstants.PASSWORD_TEXT);
usernameToken.setName(username);
usernameToken.addWSUNamespace();
usernameToken.addWSSENamespace();
usernameToken.setID("id-" + username);
if (password != null){
usernameToken.setPassword(password);
}
return usernameToken;
}
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=aapass
org.apache.ws.security.crypto.merlin.keystore.alias=myactaskey
org.apache.ws.security.crypto.merlin.keystore.file=actasstore.jks
WildFly 9
MANIFEST.MF
When deployed on WildFly this application requires access to the JBossWs and CXF APIs provided in
modules org.jboss.ws.cxf.jbossws-cxf-client and org.apache.cxf. The Apache CXF internals,
org.apache.cxf.impl, are needed in handling the ActAs and OnBehalfOf extensions. The dependency
statement directs the server to provide them at deployment.
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client, org.apache.cxf.impl
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.sts;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import javax.xml.ws.WebServiceProvider;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.interceptor.InInterceptors;
import org.apache.cxf.sts.StaticSTSProperties;
import org.apache.cxf.sts.operation.TokenIssueOperation;
import org.apache.cxf.sts.operation.TokenValidateOperation;
import org.apache.cxf.sts.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.delegation.UsernameTokenDelegationHandler;
import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
import org.apache.cxf.sts.token.validator.SAMLTokenValidator;
import org.apache.cxf.sts.token.validator.UsernameTokenValidator;
import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider;
@WebServiceProvider(serviceName = "SecurityTokenService",
WildFly 9
portName = "UT_Port",
targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/",
wsdlLocation = "WEB-INF/wsdl/ws-trust-1.4-service.wsdl")
//be sure to have dependency on org.apache.cxf module when on AS7, otherwise Apache CXF
annotations are ignored
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "mystskey"),
@EndpointProperty(key = "ws-security.signature.properties", value =
"stsKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.sts.STSCallbackHandler"),
@EndpointProperty(key = "ws-security.validate.token", value = "false") //to let the JAAS
integration deal with validation through the interceptor below
})
@InInterceptors(interceptors =
{"org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingPolicyInterceptor"})
public class SampleSTS extends SecurityTokenServiceProvider
{
public SampleSTS() throws Exception
{
super();
StaticSTSProperties props = new StaticSTSProperties();
props.setSignatureCryptoProperties("stsKeystore.properties");
props.setSignatureUsername("mystskey");
props.setCallbackHandlerClass(STSCallbackHandler.class.getName());
props.setIssuer("DoubleItSTSIssuer");
List<ServiceMBean> services = new LinkedList<ServiceMBean>();
StaticService service = new StaticService();
service.setEndpoints(Arrays.asList(
"http://localhost:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService",
"http://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService",
"http://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust/SecurityService",
"http://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-actas/ActAsService",
"http://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-actas/ActAsService",
"http://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-actas/ActAsService",
"http://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService",
"http://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService",
"http://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-onbehalfof/OnBehalfOfService"
));
services.add(service);
TokenIssueOperation issueOperation = new TokenIssueOperation();
issueOperation.setServices(services);
issueOperation.getTokenProviders().add(new SAMLTokenProvider());
// required for OnBehalfOf
issueOperation.getTokenValidators().add(new UsernameTokenValidator());
// added for OnBehalfOf and ActAs
issueOperation.getDelegationHandlers().add(new UsernameTokenDelegationHandler());
issueOperation.setStsProperties(props);
TokenValidateOperation validateOperation = new TokenValidateOperation();
validateOperation.getTokenValidators().add(new SAMLTokenValidator());
WildFly 9
validateOperation.setStsProperties(props);
this.setIssueOperation(issueOperation);
this.setValidateOperation(validateOperation);
}
}
STSCallbackHandler
The user, alice, and corresponding password was required to be added for the ActAs example.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.sts;
import java.util.HashMap;
import java.util.Map;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
public class STSCallbackHandler extends PasswordCallbackHandler
{
public STSCallbackHandler()
{
super(getInitMap());
}
private static Map<String, String> getInitMap()
{
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("mystskey", "stskpass");
passwords.put("alice", "clarinet");
return passwords;
}
}
WildFly 9
WildFly 9
WildFly 9
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy"
)
public interface OnBehalfOfServiceIface
{
@WebMethod
String sayHello();
}
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.trust.STSClient;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.service.ServiceIface;
import org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared.WSTrustAppUtils;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Service;
import java.net.*;
import java.util.Map;
@WebService
(
portName = "OnBehalfOfServicePort",
serviceName = "OnBehalfOfService",
wsdlLocation = "WEB-INF/wsdl/OnBehalfOfService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/onbehalfofwssecuritypolicy",
endpointInterface =
WildFly 9
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfServiceIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "myactaskey"),
@EndpointProperty(key = "ws-security.signature.properties", value =
"actasKeystore.properties"),
@EndpointProperty(key = "ws-security.encryption.properties", value =
"actasKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof.OnBehalfOfCallbackHandler")
})
public class OnBehalfOfServiceImpl implements OnBehalfOfServiceIface
{
public String sayHello() {
try {
ServiceIface proxy = setupService();
return "OnBehalfOf " + proxy.sayHello();
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
/**
*
* @return
* @throws MalformedURLException
*/
private
WildFly 9
WildFly 9
OnBehalfOfCallbackHandler
OnBehalfOfCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the
password for the private key in the keystore. This class enables CXF to retrieve the password of the user
name to use for the message signature. This class has been revised to return the passwords for this
service, myactaskey and the "OnBehalfOf" user, alice.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.onbehalfof;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
import java.util.HashMap;
import java.util.Map;
public class OnBehalfOfCallbackHandler extends PasswordCallbackHandler {
public OnBehalfOfCallbackHandler()
{
super(getInitMap());
}
private static Map<String, String> getInitMap()
{
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("myactaskey", "aspass");
passwords.put("alice", "clarinet");
passwords.put("bob", "trombone");
return passwords;
}
}
WildFly 9
WildFly 9
WildFly 9
Web service provider WSDL
The web service provider is a contract-first endpoint. All the WS-trust and security policies for it are declared
in WSDL, BearerService.wsdl. For this scenario a ws-requester is required to present a SAML 2.0 Bearer
token issued from a designed STS. The address of the STS is provided in the WSDL. HTTPS, a
TransportBinding and HttpsToken policy are used to protect the SOAP body of messages that pass back
and forth between ws-requester and ws-provider. A detailed explanation of the security settings are
provided in the comments in the listing below.
WildFly 9
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<!-The soap:address has been defined to use JBoss's https port, 8443.
This is
<wsp:Policy wsu:Id="TransportSAML2BearerPolicy">
<wsp:ExactlyOne>
<wsp:All>
<!-The wsam:Addressing element, indicates that the endpoints of this
web service MUST conform to the WS-Addressing specification.
The
WildFly 9
are added to the security header in any order that conforms to
WSS: SOAP Message Security.
-->
<sp:Layout>
<wsp:Policy>
<sp:Lax />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
</wsp:Policy>
</sp:TransportBinding>
<!-The sp:SignedSupportingTokens element causes the supporting tokens
to be signed using the primary token that is used to sign the message.
-->
<sp:SignedSupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<!-The sp:IssuedToken element asserts that a SAML 2.0 security token of type
Bearer is expected from the STS. The
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
attribute instructs the runtime to include the initiator's public key
with every message sent to the recipient.
The sp:RequestSecurityTokenTemplate element directs that all of the
children of this element will be copied directly into the body of the
RequestSecurityToken (RST) message that is sent to the STS when the
initiator asks the STS to issue a token.
-->
<sp:IssuedToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<sp:RequestSecurityTokenTemplate>
<t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType>
<t:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</t:KeyType>
</sp:RequestSecurityTokenTemplate>
<wsp:Policy>
<sp:RequireInternalReference />
</wsp:Policy>
<!-The sp:Issuer element defines the STS's address and endpoint information
This information is used by the STSClient.
-->
<sp:Issuer>
<wsaws:Address>http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-bearer/SecurityTokenServic
<wsaws:Metadata
xmlns:wsdli="http://www.w3.org/2006/01/wsdl-instance"
wsdli:wsdlLocation="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-bearer/SecurityTokenS
<wsaw:ServiceName
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:stsns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/"
EndpointName="UT_Port">stsns:SecurityTokenService</wsaw:ServiceName>
WildFly 9
</wsaws:Metadata>
</sp:Issuer>
</sp:IssuedToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<!-The sp:Wss11 element declares WSS: SOAP Message Security 1.1 options
to be supported by the STS.
-->
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefIssuerSerial />
<sp:MustSupportRefThumbprint />
<sp:MustSupportRefEncryptedKey />
</wsp:Policy>
</sp:Wss11>
<!-The sp:Trust13 element declares controls for WS-Trust 1.3 options.
They are policy assertions related to exchanges specifically with
client and server challenges and entropy behaviors. Again these are
normally handled by CXF.
-->
<sp:Trust13>
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust13>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</definitions>
WildFly 9
SSL configuration
This web service is using https, therefore the JBoss server must be configured to provide SSL support in the
Web subsystem. There are 2 components to SSL configuration.
create a certificate keystore
declare an SSL connector in the Web subsystem of the JBoss server configuration file.
Follow the directions in the, "Using the pure Java implementation supplied by JSSE" section in the SSL
Setup Guide.
Here is an example of an SSL connector declaration.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.bearer;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy"
)
public interface BearerIface
{
@WebMethod
String sayHello();
}
WildFly 9
Web service Implementation
The web service provider implementation class, BearerImpl, is a simple POJO. It uses the standard
WebService annotation to define the service endpoint. In addition there are two Apache CXF annotations,
EndpointProperties and EndpointProperty used for configuring the endpoint for the CXF runtime. These
annotations come from the Apache WSS4J project, which provides a Java implementation of the primary
WS-Security standards for Web Services. These annotations are programmatically adding properties to the
endpoint. With plain Apache CXF, these properties are often set via the <jaxws:properties> element on the
<jaxws:endpoint> element in the Spring config; these annotations allow the properties to be configured in the
code.
WSS4J uses the Crypto interface to get keys and certificates for signature creation/verification, as is
asserted by the WSDL for this service. The WSS4J configuration information being provided by BearerImpl
is for Crypto's Merlin implementation. More information will be provided about this in the keystore section.
Because the web service provider automatically trusts that the incoming SOAP request came from the
subject defined in the SAML token there is no need for a Crypto callbackHandler class or a signature
username, unlike in prior examples, however in order to verify the message signature, the Java properties
file that contains the (Merlin) crypto configuration information is still required.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.bearer;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import javax.jws.WebService;
@WebService
(
portName = "BearerServicePort",
serviceName = "BearerService",
wsdlLocation = "WEB-INF/wsdl/BearerService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/bearerwssecuritypolicy",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.bearer.BearerIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.properties", value =
"serviceKeystore.properties")
})
public class BearerImpl implements BearerIface
{
public String sayHello()
{
return "Bearer WS-Trust Hello World!";
}
}
WildFly 9
Crypto properties and keystore files
WSS4J's Crypto implementation is loaded and configured via a Java properties file that contains Crypto
configuration data. The file contains implementation-specific properties such as a keystore location,
password, default alias and the like. This application is using the Merlin implementation. File
serviceKeystore.properties contains this information.
File servicestore.jks, is a Java KeyStore (JKS) repository. It contains self signed certificates for
myservicekey and mystskey. Self signed certificates are not appropriate for production use.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=sspass
org.apache.ws.security.crypto.merlin.keystore.alias=myservicekey
org.apache.ws.security.crypto.merlin.keystore.file=servicestore.jks
MANIFEST.MF
When deployed on WildFly this application requires access to the JBossWs and CXF APIs provided in
module org.jboss.ws.cxf.jbossws-cxf-client. The dependency statement directs the server to provide them at
deployment.
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client
WildFly 9
Security Domain
The STS requires a JBoss security domain be configured. The jboss-web.xml descriptor declares a named
security domain,"JBossWS-trust-sts" to be used by this service for authentication. This security domain
requires two properties files and the addition of a security-domain declaration in the JBoss server
configuration file.
For this scenario the domain needs to contain user alice, password clarinet, and role friend. See the listings
below for jbossws-users.properties and jbossws-roles.properties. In addition the following XML must be
added to the JBoss security subsystem in the server configuration file. Replace " SOME_PATH" with
appropriate information.
<security-domain name="JBossWS-trust-sts">
<authentication>
<login-module code="UsersRoles" flag="required">
<module-option name="usersProperties" value="/SOME_PATH/jbossws-users.properties"/>
<module-option name="unauthenticatedIdentity" value="anonymous"/>
<module-option name="rolesProperties" value="/SOME_PATH/jbossws-roles.properties"/>
</login-module>
</authentication>
</security-domain>
jboss-web.xml
jbossws-users.properties
jbossws-roles.properties
STS's WSDL
WildFly 9
xmlns:wsap10="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
<wsdl:types>
<xs:schema elementFormDefault="qualified"
targetNamespace='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>
<xs:element name='RequestSecurityToken'
type='wst:AbstractRequestSecurityTokenType'/>
<xs:element name='RequestSecurityTokenResponse'
type='wst:AbstractRequestSecurityTokenType'/>
<xs:complexType name='AbstractRequestSecurityTokenType'>
<xs:sequence>
<xs:any namespace='##any' processContents='lax' minOccurs='0'
maxOccurs='unbounded'/>
</xs:sequence>
<xs:attribute name='Context' type='xs:anyURI' use='optional'/>
<xs:anyAttribute namespace='##other' processContents='lax'/>
</xs:complexType>
<xs:element name='RequestSecurityTokenCollection'
type='wst:RequestSecurityTokenCollectionType'/>
<xs:complexType name='RequestSecurityTokenCollectionType'>
<xs:sequence>
<xs:element name='RequestSecurityToken'
type='wst:AbstractRequestSecurityTokenType' minOccurs='2'
maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
<xs:element name='RequestSecurityTokenResponseCollection'
type='wst:RequestSecurityTokenResponseCollectionType'/>
<xs:complexType name='RequestSecurityTokenResponseCollectionType'>
<xs:sequence>
<xs:element ref='wst:RequestSecurityTokenResponse' minOccurs='1'
maxOccurs='unbounded'/>
</xs:sequence>
<xs:anyAttribute namespace='##other' processContents='lax'/>
</xs:complexType>
</xs:schema>
</wsdl:types>
<!-- WS-Trust defines the following GEDs -->
<wsdl:message name="RequestSecurityTokenMsg">
<wsdl:part name="request" element="wst:RequestSecurityToken"/>
</wsdl:message>
<wsdl:message name="RequestSecurityTokenResponseMsg">
<wsdl:part name="response"
element="wst:RequestSecurityTokenResponse"/>
</wsdl:message>
<wsdl:message name="RequestSecurityTokenCollectionMsg">
<wsdl:part name="requestCollection"
element="wst:RequestSecurityTokenCollection"/>
WildFly 9
</wsdl:message>
<wsdl:message name="RequestSecurityTokenResponseCollectionMsg">
<wsdl:part name="responseCollection"
element="wst:RequestSecurityTokenResponseCollection"/>
</wsdl:message>
<!-- This portType an example of a Requestor (or other) endpoint that
Accepts SOAP-based challenges from a Security Token Service -->
<wsdl:portType name="WSSecurityRequestor">
<wsdl:operation name="Challenge">
<wsdl:input message="tns:RequestSecurityTokenResponseMsg"/>
<wsdl:output message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
</wsdl:portType>
<!-- This portType is an example of an STS supporting full protocol -->
<!-The wsdl:portType and data types are XML elements defined by the
WS_Trust specification. The wsdl:portType defines the endpoints
supported in the STS implementation. This WSDL defines all operations
that an STS implementation can support.
-->
<wsdl:portType name="STS">
<wsdl:operation name="Cancel">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Cancel"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/CancelFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="Issue">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTRC/IssueFinal"
message="tns:RequestSecurityTokenResponseCollectionMsg"/>
</wsdl:operation>
<wsdl:operation name="Renew">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Renew"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/RenewFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="Validate">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Validate"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/ValidateFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="KeyExchangeToken">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/KET"
WildFly 9
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/KETFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="RequestCollection">
<wsdl:input message="tns:RequestSecurityTokenCollectionMsg"/>
<wsdl:output message="tns:RequestSecurityTokenResponseCollectionMsg"/>
</wsdl:operation>
</wsdl:portType>
<!-- This portType is an example of an endpoint that accepts
Unsolicited RequestSecurityTokenResponse messages -->
<wsdl:portType name="SecurityTokenResponseService">
<wsdl:operation name="RequestSecurityTokenResponse">
<wsdl:input message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
</wsdl:portType>
<!-The wsp:PolicyReference binds the security requirments on all the STS endpoints.
The wsp:Policy wsu:Id="UT_policy" element is later in this file.
-->
<wsdl:binding name="UT_Binding" type="wstrust:STS">
<wsp:PolicyReference URI="#UT_policy"/>
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Issue">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"/>
<wsdl:input>
<wsp:PolicyReference
URI="#Input_policy"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference
URI="#Output_policy"/>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Validate">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Validate"/>
<wsdl:input>
<wsp:PolicyReference
URI="#Input_policy"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference
URI="#Output_policy"/>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Cancel">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Cancel"/>
WildFly 9
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Renew">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Renew"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeyExchangeToken">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/KeyExchangeToken"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="RequestCollection">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/RequestCollection"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SecurityTokenService">
<wsdl:port name="UT_Port" binding="tns:UT_Binding">
<soap:address location="http://localhost:8080/SecurityTokenService/UT"/>
</wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="UT_policy">
<wsp:ExactlyOne>
<wsp:All>
<!-The sp:UsingAddressing element, indicates that the endpoints of this
web service conforms to the WS-Addressing specification. More detail
can be found here: [http://www.w3.org/TR/2006/CR-ws-addr-wsdl-20060529]
-->
<wsap10:UsingAddressing/>
<!-The sp:SymmetricBinding element indicates that security is provided
at the SOAP layer and any initiator must authenticate itself by providing
WildFly 9
WSS UsernameToken credentials.
-->
<sp:SymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<!-In a symmetric binding, the keys used for encrypting and signing in both
directions are derived from a single key, the one specified by the
sp:ProtectionToken element. The sp:X509Token sub-element declares this
key to be a X.509 certificate and the
IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never"
attribute adds the requirement that the token MUST NOT be included in
any messages sent between the initiator and the recipient; rather, an
external reference to the token should be used.
WildFly 9
handled by CXF.
-->
<sp:Wss11
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier/>
<sp:MustSupportRefIssuerSerial/>
<sp:MustSupportRefThumbprint/>
<sp:MustSupportRefEncryptedKey/>
</wsp:Policy>
</sp:Wss11>
<!-The sp:Trust13 element declares controls for WS-Trust 1.3 options.
They are policy assertions related to exchanges specifically with
client and server challenges and entropy behaviors. Again these are
normally handled by CXF.
-->
<sp:Trust13
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust13>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
WildFly 9
<wsp:Policy wsu:Id="Input_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="From"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="Action"
Namespace="http://www.w3.org/2005/08/addressing"/>
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Output_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="From"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="Action"
Namespace="http://www.w3.org/2005/08/addressing"/>
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</wsdl:definitions>
WildFly 9
The Apache CXF's STS, SecurityTokenServiceProvider, is a web service provider that is compliant with the
protocols and functionality defined by the WS-Trust specification. It has a modular architecture. Many of its
components are configurable or replaceable and there are many optional features that are enabled by
implementing and configuring plug-ins. Users can customize their own STS by extending from
SecurityTokenServiceProvider and overriding the default settings. Extensive information about the CXF's
STS configurable and pluggable components can be found here.
This STS implementation class, SampleSTSBearer, is a POJO that extends from
SecurityTokenServiceProvider. Note that the class is defined with a WebServiceProvider annotation and not
a WebService annotation. This annotation defines the service as a Provider-based endpoint, meaning it
supports a more messaging-oriented approach to Web services. In particular, it signals that the exchanged
messages will be XML documents of some type. SecurityTokenServiceProvider is an implementation of the
javax.xml.ws.Provider interface. In comparison the WebService annotation defines a (service endpoint
interface) SEI-based endpoint which supports message exchange via SOAP envelopes.
As was done in the BearerImpl class, the WSS4J annotations EndpointProperties and EndpointProperty are
providing endpoint configuration for the CXF runtime. The first EndpointProperty statement in the listing is
declaring the user's name to use for the message signature. It is used as the alias name in the keystore to
get the user's cert and private key for signature. The next two EndpointProperty statements declares the
Java properties file that contains the (Merlin) crypto configuration information. In this case both for signing
and encrypting the messages. WSS4J reads this file and extra required information for message handling.
The last EndpointProperty statement declares the STSBearerCallbackHandler implementation class. It is
used to obtain the user's password for the certificates in the keystore file.
In this implementation we are customizing the operations of token issuance, token validation and their static
properties.
StaticSTSProperties is used to set select properties for configuring resources in the STS. You may think this
is a duplication of the settings made with the WSS4J annotations. The values are the same but the
underlaying structures being set are different, thus this information must be declared in both places.
The setIssuer setting is important because it uniquely identifies the issuing STS. The issuer string is
embedded in issued tokens and, when validating tokens, the STS checks the issuer string value.
Consequently, it is important to use the issuer string in a consistent way, so that the STS can recognize the
tokens that it has issued.
The setEndpoints call allows the declaration of a set of allowed token recipients by address. The addresses
are specified as reg-ex patterns.
TokenIssueOperation has a modular structure. This allows custom behaviors to be injected into the
processing of messages. In this case we are overriding the SecurityTokenServiceProvider's default behavior
and performing SAML token processing. CXF provides an implementation of a SAMLTokenProvider which
we are using rather than writing our own.
Learn more about the SAMLTokenProvider here.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsbearer;
import org.apache.cxf.annotations.EndpointProperties;
WildFly 9
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.sts.StaticSTSProperties;
import org.apache.cxf.sts.operation.TokenIssueOperation;
import org.apache.cxf.sts.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider;
import javax.xml.ws.WebServiceProvider;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@WebServiceProvider(serviceName = "SecurityTokenService",
portName = "UT_Port",
targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/",
wsdlLocation = "WEB-INF/wsdl/bearer-ws-trust-1.4-service.wsdl")
//be sure to have dependency on org.apache.cxf module when on AS7, otherwise Apache CXF
annotations are ignored
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.username", value = "mystskey"),
@EndpointProperty(key = "ws-security.signature.properties", value =
"stsKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsbearer.STSBearerCallbackHandler")
})
public class SampleSTSBearer extends SecurityTokenServiceProvider
{
public SampleSTSBearer() throws Exception
{
super();
StaticSTSProperties props = new StaticSTSProperties();
props.setSignatureCryptoProperties("stsKeystore.properties");
props.setSignatureUsername("mystskey");
props.setCallbackHandlerClass(STSBearerCallbackHandler.class.getName());
props.setEncryptionCryptoProperties("stsKeystore.properties");
props.setEncryptionUsername("myservicekey");
props.setIssuer("DoubleItSTSIssuer");
List<ServiceMBean> services = new LinkedList<ServiceMBean>();
StaticService service = new StaticService();
service.setEndpoints(Arrays.asList(
"https://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService",
"https://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService",
"https://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-bearer/BearerService"
));
services.add(service);
TokenIssueOperation issueOperation = new TokenIssueOperation();
issueOperation.getTokenProviders().add(new SAMLTokenProvider());
issueOperation.setServices(services);
issueOperation.setStsProperties(props);
this.setIssueOperation(issueOperation);
}
}
WildFly 9
STSBearerCallbackHandler
STSBearerCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the
password for the private key in the keystore. This class enables CXF to retrieve the password of the user
name to use for the message signature.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsbearer;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
import java.util.HashMap;
import java.util.Map;
public class STSBearerCallbackHandler extends PasswordCallbackHandler
{
public STSBearerCallbackHandler()
{
super(getInitMap());
}
private static Map<String, String> getInitMap()
{
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("mystskey", "stskpass");
passwords.put("alice", "clarinet");
return passwords;
}
}
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=stsspass
org.apache.ws.security.crypto.merlin.keystore.file=stsstore.jks
WildFly 9
MANIFEST.MF
When deployed on WildFly, this application requires access to the JBossWs and CXF APIs provided in
modules org.jboss.ws.cxf.jbossws-cxf-client and org.apache.cxf. The Apache CXF internals,
org.apache.cxf.impl, are needed to build the STS configuration in the SampleSTS constructor. The
dependency statement directs the server to provide them at deployment.
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.2
Created-By: 1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client,org.apache.cxf.impl
WildFly 9
Web service requester Implementation
The ws-requester, the client, uses standard procedures for creating a reference to the web service. To
address the endpoint security requirements, the web service's "Request Context" is configured with the
information needed in message generation. In addition, the STSClient that communicates with the STS is
configured with similar values. Note the key strings ending with a ".it" suffix. This suffix flags these settings
as belonging to the STSClient. The internal CXF code assigns this information to the STSClient that is
auto-generated for this service call.
There is an alternate method of setting up the STSCLient. The user may provide their own instance of the
STSClient. The CXF code will use this object and not auto-generate one. When providing the STSClient in
this way, the user must provide a org.apache.cxf.Bus for it and the configuration keys must not have the ".it"
suffix. This is used in the ActAs and OnBehalfOf examples.
WildFly 9
ClientCallbackHandler
https://docs.jboss.org/author/display/JBWS/WS-Trust+and+STS#WS-TrustandSTS-ClientCallbackHandler
ClientCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the password for
the private key in the keystore. This class enables CXF to retrieve the password of the user name to use for
the message signature. Note that "alice" and her password have been provided here. This information is
not in the (JKS) keystore but provided in the WildFly security domain. It was declared in file
jbossws-users.properties.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class ClientCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
if ("myclientkey".equals(pc.getIdentifier())) {
pc.setPassword("ckpass");
break;
} else if ("alice".equals(pc.getIdentifier())) {
pc.setPassword("clarinet");
break;
} else if ("bob".equals(pc.getIdentifier())) {
pc.setPassword("trombone");
break;
} else if ("myservicekey".equals(pc.getIdentifier())) {
// rls test
added for
bearer test
pc.setPassword("skpass");
break;
}
}
}
}
}
WildFly 9
Crypto properties and keystore files
https://docs.jboss.org/author/display/JBWS/WS-Trust+and+STS#WS-TrustandSTS-RequesterCryptopropertiesandkeystor
WSS4J's Crypto implementation is loaded and configured via a Java properties file that contains Crypto
configuration data. The file contains implementation-specific properties such as a keystore location,
password, default alias and the like. This application is using the Merlin implementation. File
clientKeystore.properties contains this information.
File clientstore.jks, is a Java KeyStore (JKS) repository. It contains self signed certificates for myservicekey
and mystskey. Self signed certificates are not appropriate for production use.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=cspass
org.apache.ws.security.crypto.merlin.keystore.alias=myclientkey
org.apache.ws.security.crypto.merlin.keystore.file=META-INF/clientstore.jks
WildFly 9
Implementation of this scenario has the following requirements.
SAML tokens with a Holder-Of-Key subject confirmation method must be protected so the token can
not be snooped. In most cases, a Holder-Of-Key token combined with HTTPS is sufficient to prevent
"a man in the middle" getting possession of the token. This means a security policy that uses a
sp:TransportBinding and sp:HttpsToken.
A Holder-Of-Key token has no encryption or signing keys associated with it, therefore a
sp:IssuedToken of SymmetricKey or PublicKey keyType should be used with a
sp:SignedEndorsingSupportingTokens.
Web service Provider
This section examines the web service elements for the SAML Holder-Of-Key scenario. The components
are
Web service provider's WSDL
SSL configuration
Web service provider's Interface and Implementation classes.
Crypto properties and keystore files
MANIFEST.MF
Web service provider WSDL
The web service provider is a contract-first endpoint. All the WS-trust and security policies for it are declared
in the WSDL, HolderOfKeyService.wsdl. For this scenario a ws-requester is required to present a SAML 2.0
token of SymmetricKey keyType, issued from a designed STS. The address of the STS is provided in the
WSDL. A transport binding policy is used. The token is declared to be signed and endorsed,
sp:SignedEndorsingSupportingTokens. A detailed explanation of the security settings are provided in the
comments in the listing below.
WildFly 9
</types>
<message name="sayHello">
<part name="parameters" element="tns:sayHello"/>
</message>
<message name="sayHelloResponse">
<part name="parameters" element="tns:sayHelloResponse"/>
</message>
<portType name="HolderOfKeyIface">
<operation name="sayHello">
<input message="tns:sayHello"/>
<output message="tns:sayHelloResponse"/>
</operation>
</portType>
<!-The wsp:PolicyReference binds the security requirments on all the endpoints.
The wsp:Policy wsu:Id="#TransportSAML2HolderOfKeyPolicy" element is defined later in
this file.
-->
<binding name="HolderOfKeyServicePortBinding" type="tns:HolderOfKeyIface">
<wsp:PolicyReference URI="#TransportSAML2HolderOfKeyPolicy" />
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="sayHello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<!-The soap:address has been defined to use JBoss's https port, 8443.
This is
<wsp:Policy wsu:Id="TransportSAML2HolderOfKeyPolicy">
<wsp:ExactlyOne>
<wsp:All>
<!-The wsam:Addressing element, indicates that the endpoints of this
web service MUST conform to the WS-Addressing specification.
The
defines the sp:HttpsToken for use in exchanging messages transmitted over HTTPS.
WildFly 9
-->
<sp:TransportBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken>
<wsp:Policy/>
</sp:HttpsToken>
</wsp:Policy>
</sp:TransportToken>
<!-The sp:AlgorithmSuite element, requires the TripleDes algorithm suite
be used in performing cryptographic operations.
-->
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:TripleDes />
</wsp:Policy>
</sp:AlgorithmSuite>
<!-The sp:Layout element,
WildFly 9
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<sp:RequestSecurityTokenTemplate>
<t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0</t:TokenType>
<!-KeyType of "SymmetricKey", the client must prove to the WS service that it
possesses a particular symmetric session key.
-->
<t:KeyType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey</t:KeyType>
</sp:RequestSecurityTokenTemplate>
<wsp:Policy>
<sp:RequireInternalReference />
</wsp:Policy>
<!-The sp:Issuer element defines the STS's address and endpoint information
This information is used by the STSClient.
-->
<sp:Issuer>
<wsaws:Address>http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-holderofkey/SecurityTokenS
<wsaws:Metadata
xmlns:wsdli="http://www.w3.org/2006/01/wsdl-instance"
wsdli:wsdlLocation="http://@jboss.bind.address@:8080/jaxws-samples-wsse-policy-trust-sts-holderofkey/SecurityT
<wsaw:ServiceName
xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:stsns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/"
EndpointName="UT_Port">stsns:SecurityTokenService</wsaw:ServiceName>
</wsaws:Metadata>
</sp:Issuer>
</sp:IssuedToken>
</wsp:Policy>
</sp:SignedEndorsingSupportingTokens>
<!-The sp:Wss11 element declares WSS: SOAP Message Security 1.1 options
to be supported by the STS. These particular elements generally refer
to how keys are referenced within the SOAP envelope. These are normally
handled by CXF.
-->
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefIssuerSerial />
<sp:MustSupportRefThumbprint />
<sp:MustSupportRefEncryptedKey />
</wsp:Policy>
</sp:Wss11>
<!-The sp:Trust13 element declares controls for WS-Trust 1.3 options.
They are policy assertions related to exchanges specifically with
client and server challenges and entropy behaviors. Again these are
normally handled by CXF.
-->
<sp:Trust13>
<wsp:Policy>
<sp:MustSupportIssuedTokens />
<sp:RequireClientEntropy />
WildFly 9
<sp:RequireServerEntropy />
</wsp:Policy>
</sp:Trust13>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</definitions>
SSL configuration
https://docs.jboss.org/author/display/JBWS/WS-Trust+and+STS#WS-TrustandSTS-SSLconfiguration
This web service is using https, therefore the JBoss server must be configured to provide SSL support in the
Web subsystem. There are 2 components to SSL configuration.
create a certificate keystore
declare an SSL connector in the Web subsystem of the JBoss server configuration file.
Follow the directions in the, "Using the pure Java implementation supplied by JSSE" section in the [SSL
Setup Guide|../../../../../../../../../../display/WFLY8/SSL+setup+guide|||\||].
Here is an example of an SSL connector declaration.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy"
)
public interface HolderOfKeyIface {
@WebMethod
String sayHello();
}
WildFly 9
Web service Implementation
The web service provider implementation class, HolderOfKeyImpl, is a simple POJO. It uses the standard
WebService annotation to define the service endpoint. In addition there are two Apache CXF annotations,
EndpointProperties and EndpointProperty used for configuring the endpoint for the CXF runtime. These
annotations come from the Apache WSS4J project, which provides a Java implementation of the primary
WS-Security standards for Web Services. These annotations are programmatically adding properties to the
endpoint. With plain Apache CXF, these properties are often set via the <jaxws:properties> element on the
<jaxws:endpoint> element in the Spring config; these annotations allow the properties to be configured in the
code.
WSS4J uses the Crypto interface to get keys and certificates for signature creation/verification, as is
asserted by the WSDL for this service. The WSS4J configuration information being provided by
HolderOfKeyImpl is for Crypto's Merlin implementation. More information will be provided about this in the
keystore section.
The first EndpointProperty statement in the listing disables ensurance of compliance with the Basic Security
Profile 1.1. The next EndpointProperty statements declares the Java properties file that contains the (Merlin)
crypto configuration information. The last EndpointProperty statement declares the
STSHolderOfKeyCallbackHandler implementation class. It is used to obtain the user's password for the
certificates in the keystore file.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import javax.jws.WebService;
@WebService
(
portName = "HolderOfKeyServicePort",
serviceName = "HolderOfKeyService",
wsdlLocation = "WEB-INF/wsdl/HolderOfKeyService.wsdl",
targetNamespace =
"http://www.jboss.org/jbossws/ws-extensions/holderofkeywssecuritypolicy",
endpointInterface =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey.HolderOfKeyIface"
)
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.is-bsp-compliant", value = "false"),
@EndpointProperty(key = "ws-security.signature.properties", value =
"serviceKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.holderofkey.HolderOfKeyCallbackHandler")
})
public class HolderOfKeyImpl implements HolderOfKeyIface
{
public String sayHello()
{
return "Holder-Of-Key WS-Trust Hello World!";
}
}
WildFly 9
Crypto properties and keystore files
WSS4J's Crypto implementation is loaded and configured via a Java properties file that contains Crypto
configuration data. The file contains implementation-specific properties such as a keystore location,
password, default alias and the like. This application is using the Merlin implementation. File
serviceKeystore.properties contains this information.
File servicestore.jks, is a Java KeyStore (JKS) repository. It contains self signed certificates for
myservicekey and mystskey. Self signed certificates are not appropriate for production use.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=sspass
org.apache.ws.security.crypto.merlin.keystore.alias=myservicekey
org.apache.ws.security.crypto.merlin.keystore.file=servicestore.jks
MANIFEST.MF
https://docs.jboss.org/author/display/JBWS/WS-Trust+and+STS#WS-TrustandSTS-MANIFEST.MF
When deployed on WildFly this application requires access to the JBossWs and CXF APIs provided in
module org.jboss.ws.cxf.jbossws-cxf-client. The dependency statement directs the server to provide them at
deployment.
Manifest-Version:1.0
Ant-Version: Apache Ant1.8.2
Created-By:1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client
WildFly 9
Security Domain
The STS requires a JBoss security domain be configured. The jboss-web.xml descriptor declares a named
security domain,"JBossWS-trust-sts" to be used by this service for authentication. This security domain
requires two properties files and the addition of a security-domain declaration in the JBoss server
configuration file.
For this scenario the domain needs to contain user alice, password clarinet, and role friend. See the listings
below for jbossws-users.properties and jbossws-roles.properties. In addition the following XML must be
added to the JBoss security subsystem in the server configuration file. Replace " SOME_PATH" with
appropriate information.
<security-domain name="JBossWS-trust-sts">
<authentication>
<login-module code="UsersRoles" flag="required">
<module-option name="usersProperties" value="/SOME_PATH/jbossws-users.properties"/>
<module-option name="unauthenticatedIdentity" value="anonymous"/>
<module-option name="rolesProperties" value="/SOME_PATH/jbossws-roles.properties"/>
</login-module>
</authentication>
</security-domain>
jboss-web.xml
jbossws-users.properties
jbossws-roles.properties
STS's WSDL
WildFly 9
xmlns:tns="http://docs.oasis-open.org/ws-sx/ws-trust/200512/"
xmlns:wstrust="http://docs.oasis-open.org/ws-sx/ws-trust/200512/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsap10="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wst="http://docs.oasis-open.org/ws-sx/ws-trust/200512"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
<wsdl:types>
<xs:schema elementFormDefault="qualified"
targetNamespace='http://docs.oasis-open.org/ws-sx/ws-trust/200512'>
<xs:element name='RequestSecurityToken'
type='wst:AbstractRequestSecurityTokenType'/>
<xs:element name='RequestSecurityTokenResponse'
type='wst:AbstractRequestSecurityTokenType'/>
<xs:complexType name='AbstractRequestSecurityTokenType'>
<xs:sequence>
<xs:any namespace='##any' processContents='lax' minOccurs='0'
maxOccurs='unbounded'/>
</xs:sequence>
<xs:attribute name='Context' type='xs:anyURI' use='optional'/>
<xs:anyAttribute namespace='##other' processContents='lax'/>
</xs:complexType>
<xs:element name='RequestSecurityTokenCollection'
type='wst:RequestSecurityTokenCollectionType'/>
<xs:complexType name='RequestSecurityTokenCollectionType'>
<xs:sequence>
<xs:element name='RequestSecurityToken'
type='wst:AbstractRequestSecurityTokenType' minOccurs='2'
maxOccurs='unbounded'/>
</xs:sequence>
</xs:complexType>
<xs:element name='RequestSecurityTokenResponseCollection'
type='wst:RequestSecurityTokenResponseCollectionType'/>
<xs:complexType name='RequestSecurityTokenResponseCollectionType'>
<xs:sequence>
<xs:element ref='wst:RequestSecurityTokenResponse' minOccurs='1'
maxOccurs='unbounded'/>
</xs:sequence>
<xs:anyAttribute namespace='##other' processContents='lax'/>
</xs:complexType>
</xs:schema>
</wsdl:types>
<!-- WS-Trust defines the following GEDs -->
<wsdl:message name="RequestSecurityTokenMsg">
<wsdl:part name="request" element="wst:RequestSecurityToken"/>
</wsdl:message>
<wsdl:message name="RequestSecurityTokenResponseMsg">
<wsdl:part name="response"
element="wst:RequestSecurityTokenResponse"/>
WildFly 9
</wsdl:message>
<wsdl:message name="RequestSecurityTokenCollectionMsg">
<wsdl:part name="requestCollection"
element="wst:RequestSecurityTokenCollection"/>
</wsdl:message>
<wsdl:message name="RequestSecurityTokenResponseCollectionMsg">
<wsdl:part name="responseCollection"
element="wst:RequestSecurityTokenResponseCollection"/>
</wsdl:message>
<!-- This portType an example of a Requestor (or other) endpoint that
Accepts SOAP-based challenges from a Security Token Service -->
<wsdl:portType name="WSSecurityRequestor">
<wsdl:operation name="Challenge">
<wsdl:input message="tns:RequestSecurityTokenResponseMsg"/>
<wsdl:output message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
</wsdl:portType>
<!-- This portType is an example of an STS supporting full protocol -->
<wsdl:portType name="STS">
<wsdl:operation name="Cancel">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Cancel"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/CancelFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="Issue">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTRC/IssueFinal"
message="tns:RequestSecurityTokenResponseCollectionMsg"/>
</wsdl:operation>
<wsdl:operation name="Renew">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Renew"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/RenewFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="Validate">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Validate"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/ValidateFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="KeyExchangeToken">
<wsdl:input
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/KET"
message="tns:RequestSecurityTokenMsg"/>
<wsdl:output
WildFly 9
wsam:Action="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RSTR/KETFinal"
message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
<wsdl:operation name="RequestCollection">
<wsdl:input message="tns:RequestSecurityTokenCollectionMsg"/>
<wsdl:output message="tns:RequestSecurityTokenResponseCollectionMsg"/>
</wsdl:operation>
</wsdl:portType>
<!-- This portType is an example of an endpoint that accepts
Unsolicited RequestSecurityTokenResponse messages -->
<wsdl:portType name="SecurityTokenResponseService">
<wsdl:operation name="RequestSecurityTokenResponse">
<wsdl:input message="tns:RequestSecurityTokenResponseMsg"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="UT_Binding" type="wstrust:STS">
<wsp:PolicyReference URI="#UT_policy"/>
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Issue">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"/>
<wsdl:input>
<wsp:PolicyReference
URI="#Input_policy"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference
URI="#Output_policy"/>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Validate">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Validate"/>
<wsdl:input>
<wsp:PolicyReference
URI="#Input_policy"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference
URI="#Output_policy"/>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="Cancel">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Cancel"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
WildFly 9
</wsdl:operation>
<wsdl:operation name="Renew">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Renew"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="KeyExchangeToken">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/KeyExchangeToken"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="RequestCollection">
<soap:operation
soapAction="http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/RequestCollection"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SecurityTokenService">
<wsdl:port name="UT_Port" binding="tns:UT_Binding">
<soap:address location="http://localhost:8080/SecurityTokenService/UT"/>
</wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="UT_policy">
<wsp:ExactlyOne>
<wsp:All>
<wsap10:UsingAddressing/>
<sp:SymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
<wsp:Policy>
<sp:RequireDerivedKeys/>
<sp:RequireThumbprintReference/>
<sp:WssX509V3Token10/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
WildFly 9
</sp:ProtectionToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:EncryptSignature/>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:SignedSupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SignedSupportingTokens>
<sp:Wss11
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier/>
<sp:MustSupportRefIssuerSerial/>
<sp:MustSupportRefThumbprint/>
<sp:MustSupportRefEncryptedKey/>
</wsp:Policy>
</sp:Wss11>
<sp:Trust13
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust13>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Input_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="From"
WildFly 9
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="Action"
Namespace="http://www.w3.org/2005/08/addressing"/>
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="Output_policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SignedParts
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<sp:Body/>
<sp:Header Name="To"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="From"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="FaultTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="ReplyTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="MessageID"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="RelatesTo"
Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="Action"
Namespace="http://www.w3.org/2005/08/addressing"/>
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</wsdl:definitions>
WildFly 9
This STS implementation class, SampleSTSHolderOfKey, is a POJO that extends from
SecurityTokenServiceProvider. Note that the class is defined with a WebServiceProvider annotation and not
a WebService annotation. This annotation defines the service as a Provider-based endpoint, meaning it
supports a more messaging-oriented approach to Web services. In particular, it signals that the exchanged
messages will be XML documents of some type. SecurityTokenServiceProvider is an implementation of the
javax.xml.ws.Provider interface. In comparison the WebService annotation defines a (service endpoint
interface) SEI-based endpoint which supports message exchange via SOAP envelopes.
As was done in the HolderOfKeyImpl class, the WSS4J annotations EndpointProperties and
EndpointProperty are providing endpoint configuration for the CXF runtime. The first EndpointProperty
statements declares the Java properties file that contains the (Merlin) crypto configuration information.
WSS4J reads this file and extra required information for message handling. The last EndpointProperty
statement declares the STSHolderOfKeyCallbackHandler implementation class. It is used to obtain the
user's password for the certificates in the keystore file.
In this implementation we are customizing the operations of token issuance and their static properties.
StaticSTSProperties is used to set select properties for configuring resources in the STS. You may think this
is a duplication of the settings made with the WSS4J annotations. The values are the same but the
underlaying structures being set are different, thus this information must be declared in both places.
The setIssuer setting is important because it uniquely identifies the issuing STS. The issuer string is
embedded in issued tokens and, when validating tokens, the STS checks the issuer string value.
Consequently, it is important to use the issuer string in a consistent way, so that the STS can recognize the
tokens that it has issued.
The setEndpoints call allows the declaration of a set of allowed token recipients by address. The addresses
are specified as reg-ex patterns.
TokenIssueOperation has a modular structure. This allows custom behaviors to be injected into the
processing of messages. In this case we are overriding the SecurityTokenServiceProvider's default behavior
and performing SAML token processing. CXF provides an implementation of a SAMLTokenProvider which
we are using rather than writing our own.
Learn more about the SAMLTokenProvider here.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.sts.StaticSTSProperties;
import org.apache.cxf.sts.operation.TokenIssueOperation;
import org.apache.cxf.sts.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider;
import javax.xml.ws.WebServiceProvider;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
WildFly 9
/**
* User: rsearls
* Date: 3/14/14
*/
@WebServiceProvider(serviceName = "SecurityTokenService",
portName = "UT_Port",
targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/",
wsdlLocation = "WEB-INF/wsdl/holderofkey-ws-trust-1.4-service.wsdl")
//be sure to have dependency on org.apache.cxf module when on AS7, otherwise Apache CXF
annotations are ignored
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.properties", value =
"stsKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value =
"org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey.STSHolderOfKeyCallbackHandler")})public
class SampleSTSHolderOfKey extends SecurityTokenServiceProvider
{
public SampleSTSHolderOfKey() throws Exception
{
super();
StaticSTSProperties props = new StaticSTSProperties();
props.setSignatureCryptoProperties("stsKeystore.properties");
props.setSignatureUsername("mystskey");
props.setCallbackHandlerClass(STSHolderOfKeyCallbackHandler.class.getName());
props.setEncryptionCryptoProperties("stsKeystore.properties");
props.setEncryptionUsername("myservicekey");
props.setIssuer("DoubleItSTSIssuer");
List<ServiceMBean> services = new LinkedList<ServiceMBean>();
StaticService service = new StaticService();
service.setEndpoints(Arrays.asList(
"https://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService",
"https://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService",
"https://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService"
));
services.add(service);
TokenIssueOperation issueOperation = new TokenIssueOperation();
issueOperation.getTokenProviders().add(new SAMLTokenProvider());
issueOperation.setServices(services);
issueOperation.setStsProperties(props);
this.setIssueOperation(issueOperation);
}
}
WildFly 9
HolderOfKeyCallbackHandler
STSHolderOfKeyCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the
password for the private key in the keystore. This class enables CXF to retrieve the password of the user
name to use for the message signature.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey;
import org.jboss.wsf.stack.cxf.extensions.security.PasswordCallbackHandler;
import java.util.HashMap;
import java.util.Map;
/**
* User: rsearls
* Date: 3/19/14
*/
public class STSHolderOfKeyCallbackHandler extends PasswordCallbackHandler
{
public STSHolderOfKeyCallbackHandler()
{
super(getInitMap());
}
private static Map<String, String> getInitMap()
{
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("mystskey", "stskpass");
passwords.put("alice", "clarinet");
return passwords;
}
}
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=stsspass
org.apache.ws.security.crypto.merlin.keystore.file=stsstore.jks
WildFly 9
MANIFEST.MF
When deployed on WildFly, this application requires access to the JBossWs and CXF APIs provided in
modules org.jboss.ws.cxf.jbossws-cxf-client and org.apache.cxf. The Apache CXF internals,
org.apache.cxf.impl, are needed to build the STS configuration in the SampleSTSHolderOfKey constructor.
The dependency statement directs the server to provide them at deployment.
Manifest-Version:1.0
Ant-Version: Apache Ant1.8.2
Created-By:1.7.0_25-b15 (Oracle Corporation)
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client,org.apache.cxf.impl
WildFly 9
Web service requester Implementation
The ws-requester, the client, uses standard procedures for creating a reference to the web service. To
address the endpoint security requirements, the web service's "Request Context" is configured with the
information needed in message generation. In addition, the STSClient that communicates with the STS is
configured with similar values. Note the key strings ending with a ".it" suffix. This suffix flags these settings
as belonging to the STSClient. The internal CXF code assigns this information to the STSClient that is
auto-generated for this service call.
There is an alternate method of setting up the STSCLient. The user may provide their own instance of the
STSClient. The CXF code will use this object and not auto-generate one. When providing the STSClient in
this way, the user must provide a org.apache.cxf.Bus for it and the configuration keys must not have the ".it"
suffix. This is used in the ActAs and OnBehalfOf examples.
WildFly 9
ClientCallbackHandler
ClientCallbackHandler is a callback handler for the WSS4J Crypto API. It is used to obtain the password for
the private key in the keystore. This class enables CXF to retrieve the password of the user name to use for
the message signature. Note that "alice" and her password have been provided here. This information is
not in the (JKS) keystore but provided in the WildFly security domain. It was declared in file
jbossws-users.properties.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.shared;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class ClientCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
if ("myclientkey".equals(pc.getIdentifier())) {
pc.setPassword("ckpass");
break;
} else if ("alice".equals(pc.getIdentifier())) {
pc.setPassword("clarinet");
break;
} else if ("bob".equals(pc.getIdentifier())) {
pc.setPassword("trombone");
break;
} else if ("myservicekey".equals(pc.getIdentifier())) {
// rls test
added for
bearer test
pc.setPassword("skpass");
break;
}
}
}
}
}
WildFly 9
Crypto properties and keystore files
WSS4J's Crypto implementation is loaded and configured via a Java properties file that contains Crypto
configuration data. The file contains implementation-specific properties such as a keystore location,
password, default alias and the like. This application is using the Merlin implementation. File
clientKeystore.properties contains this information.
File clientstore.jks, is a Java KeyStore (JKS) repository. It contains self signed certificates for myservicekey
and mystskey. Self signed certificates are not appropriate for production use.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=cspass
org.apache.ws.security.crypto.merlin.keystore.alias=myclientkey
org.apache.ws.security.crypto.merlin.keystore.file=META-INF/clientstore.jks
Reliable Messaging
JBoss Web Services inherits full WS-Reliable Messaging capabilities from the underlying Apache CXF
implementation. At the time of writing, Apache CXF provides support for the WS-Reliable Messaging 1.0
(February 2005) version of the specification.
Example
In this example we configure WS-Reliable Messaging endpoint and client through the WS-Policy support.
Endpoint
We go with a contract-first approach, so we start by creating a proper WSDL contract, containing the
WS-Reliable Messaging and WS-Addressing policies (the latter is a requirement of the former):
WildFly 9
<wsdl:definitions name="SimpleService"
targetNamespace="http://www.jboss.org/jbossws/ws-extensions/wsrm"
xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/wsrm"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsp="http://www.w3.org/2006/07/ws-policy">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/wsrm"
attributeFormDefault="unqualified" elementFormDefault="unqualified"
targetNamespace="http://www.jboss.org/jbossws/ws-extensions/wsrm">
<xsd:element name="ping" type="tns:ping"/>
<xsd:complexType name="ping">
<xsd:sequence/>
</xsd:complexType>
<xsd:element name="echo" type="tns:echo"/>
<xsd:complexType name="echo">
<xsd:sequence>
<xsd:element minOccurs="0" name="arg0" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="echoResponse" type="tns:echoResponse"/>
<xsd:complexType name="echoResponse">
<xsd:sequence>
<xsd:element minOccurs="0" name="return" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="echoResponse">
<wsdl:part name="parameters" element="tns:echoResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="echo">
<wsdl:part name="parameters" element="tns:echo">
</wsdl:part>
</wsdl:message>
<wsdl:message name="ping">
<wsdl:part name="parameters" element="tns:ping">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="SimpleService">
<wsdl:operation name="ping">
<wsdl:input name="ping" message="tns:ping">
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="echo">
<wsdl:input name="echo" message="tns:echo">
</wsdl:input>
<wsdl:output name="echoResponse" message="tns:echoResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SimpleServiceSoapBinding" type="tns:SimpleService">
<wsp:Policy>
<!-- WS-Addressing and basic WS-Reliable Messaging policy assertions -->
WildFly 9
<wswa:UsingAddressing xmlns:wswa="http://www.w3.org/2006/05/addressing/wsdl"/>
<wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"/>
<!-- --------------------------------------------------------------- -->
</wsp:Policy>
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="ping">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="ping">
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="echo">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="echo">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="echoResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SimpleService">
<wsdl:port name="SimpleServicePort" binding="tns:SimpleServiceSoapBinding">
<soap:address location="http://localhost:8080/jaxws-samples-wsrm-api"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Then we use the wsconsume tool to generate both standard JAX-WS client and endpoint.
We provide a basic JAX-WS implementation for the endpoint, nothing special in it:
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsrm.service;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
name = "SimpleService",
serviceName = "SimpleService",
wsdlLocation = "WEB-INF/wsdl/SimpleService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsrm"
)
public class SimpleServiceImpl
{
@Oneway
@WebMethod
public void ping()
{
System.out.println("ping()");
}
@WebMethod
public String echo(String s)
{
System.out.println("echo(" + s + ")");
return s;
}
}
Finally we package the generated POJO endpoint together with a basic web.xml the usual way and deploy
to the application server. The webservices stack automatically detects the policies and enables WS-Reliable
Messaging.
Client
The endpoint advertises his RM capabilities (and requirements) through the published WSDL and the client
is required to also enable WS-RM for successfully exchanging messages with the server.
So a regular JAX WS client is enough if the user does not need to tune any specific detail of the RM
subsystem.
Additional configuration
Fine-grained tuning of WS-Reliable Messaging engine requires setting up proper RM features and attach
them for instance to the client proxy. Here is an example:
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsrm.client;
//...
import javax.xml.ws.Service;
import org.apache.cxf.ws.rm.feature.RMFeature;
import org.apache.cxf.ws.rm.manager.AcksPolicyType;
import org.apache.cxf.ws.rm.manager.DestinationPolicyType;
import org.jboss.test.ws.jaxws.samples.wsrm.generated.SimpleService;
// ...
Service service = Service.create(wsdlURL, serviceName);
RMFeature feature = new RMFeature();
RMAssertion rma = new RMAssertion();
RMAssertion.BaseRetransmissionInterval bri = new RMAssertion.BaseRetransmissionInterval();
bri.setMilliseconds(4000L);
rma.setBaseRetransmissionInterval(bri);
AcknowledgementInterval ai = new AcknowledgementInterval();
ai.setMilliseconds(2000L);
rma.setAcknowledgementInterval(ai);
feature.setRMAssertion(rma);
DestinationPolicyType dp = new DestinationPolicyType();
AcksPolicyType ap = new AcksPolicyType();
ap.setIntraMessageThreshold(0);
dp.setAcksPolicy(ap);
feature.setDestinationPolicy(dp);
SimpleService proxy = (SimpleService)service.getPort(SimpleService.class, feature);
proxy.echo("Hello World");
The same can of course be achieved by factoring the feature into a custom pojo extending
org.apache.cxf.ws.rm.feature.RMFeature and setting the obtained property in a client
configuration:
WildFly 9
package org.jboss.test.ws.jaxws.samples.wsrm.client;
import org.apache.cxf.ws.rm.feature.RMFeature;
import org.apache.cxf.ws.rm.manager.AcksPolicyType;
import org.apache.cxf.ws.rm.manager.DestinationPolicyType;
import org.apache.cxf.ws.rmp.v200502.RMAssertion;
import org.apache.cxf.ws.rmp.v200502.RMAssertion.AcknowledgementInterval;
public class CustomRMFeature extends RMFeature
{
public CustomRMFeature() {
super();
RMAssertion rma = new RMAssertion();
RMAssertion.BaseRetransmissionInterval bri = new RMAssertion.BaseRetransmissionInterval();
bri.setMilliseconds(4000L);
rma.setBaseRetransmissionInterval(bri);
AcknowledgementInterval ai = new AcknowledgementInterval();
ai.setMilliseconds(2000L);
rma.setAcknowledgementInterval(ai);
super.setRMAssertion(rma);
DestinationPolicyType dp = new DestinationPolicyType();
AcksPolicyType ap = new AcksPolicyType();
ap.setIntraMessageThreshold(0);
dp.setAcksPolicy(ap);
super.setDestinationPolicy(dp);
}
}
... and this is how the client would set the configuration:
WildFly 9
import org.jboss.ws.api.configuration.ClientConfigUtil;
import org.jboss.ws.api.configuration.ClientConfigurer;
//...
Service service = Service.create(wsdlURL, serviceName);
SimpleService proxy = (SimpleService)service.getPort(SimpleService.class);
ClientConfigurer configurer = ClientConfigUtil.resolveClientConfigurer();
configurer.setConfigProperties(proxy, "META-INF/jaxws-client-config.xml", "Custom Client
Config");
proxy.echo("Hello World!");
WildFly 9
Apache CXF takes care of setting up the JMS transport for endpoint implementations whose @WebService
annotation points to a port declared for JMS transport as explained above.
JBossWS currently supports POJO endpoints only for JMS transport use. The endpoint classes
can be deployed as part of jar or war archives.
The web.xml descriptor in war archives doesn't need any entry for JMS endpoints.
WildFly 9
Examples
JMS endpoint only deployment
In this example we create a simple endpoint relying on SOAP over JMS and deploy it as part of a jar archive.
The endpoint is created using wsconsume tool from a WSDL contract such as:
WildFly 9
</wsdl:input>
<wsdl:output name="echoResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldService">
<soapjms:jndiConnectionFactoryName>java:jms/RemoteConnectionFactory</soapjms:jndiConnectionFactoryName>
<soapjms:jndiInitialContextFactory>org.jboss.naming.remote.client.InitialContextFactory</soapjms:jndiInitialCo
<soapjms:jndiURL>http-remoting://myhost:8080</soapjms:jndiURL>
<wsdl:port binding="tns:HelloWorldServiceSoapBinding" name="HelloWorldImplPort">
<soap:address location="jms:queue:testQueue"/>
</wsdl:port>
</wsdl:service>
<wsdl:service name="HelloWorldServiceLocal">
<soapjms:jndiConnectionFactoryName>java:/ConnectionFactory</soapjms:jndiConnectionFactoryName>
<wsdl:port binding="tns:HelloWorldServiceSoapBinding" name="HelloWorldImplPort">
<soap:address location="jms:queue:testQueue"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
The HelloWorldImplPort here is meant for using the testQueue that has to be created before
deploying the endpoint.
At the time of writing, java:/ConnectionFactory is the default connection factory JNDI location on WildFly
For allowing remote JNDI lookup of the connection factory, a specific service ( HelloWorldService) for
remote clients is added to the WSDL. The java:jms/RemoteConnectionFactory is the JNDI location of the
same connection factory mentioned above, except it's exposed for remote lookup. The
soapjms:jndiInitialContextFactory and soap:jmsjndiURL complete the remote connection
configuration, specifying the initial context factory class to use and the JNDI registry address.
Have a look at the application server domain for finding out the configured connection factory JNDI
locations.
The endpoint implementation is a basic JAX-WS POJO using @WebService annotation to refer to the
consumed contract:
WildFly 9
package org.jboss.test.ws.jaxws.cxf.jms;
import javax.jws.WebService;
@WebService
(
portName = "HelloWorldImplPort",
serviceName = "HelloWorldServiceLocal",
wsdlLocation = "META-INF/wsdl/HelloWorldService.wsdl",
endpointInterface = "org.jboss.test.ws.jaxws.cxf.jms.HelloWorld",
targetNamespace = "http://org.jboss.ws/jaxws/cxf/jms"
)
public class HelloWorldImpl implements HelloWorld
{
public String echo(String input)
{
return input;
}
}
That's pretty much all. We just need to package the generated service endpoint interface, the endpoint
implementation and the WSDL file in a jar archive and deploy it:
WildFly 9
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 17.0-b16 (Sun Microsystems Inc.)
Dependencies: org.hornetq
A JAX-WS client can interact with the JMS endpoint the usual way:
The WSDL location URL needs to be retrieved in a custom way, depending on the client
application. Given the endpoint is JMS only, there's no automatically published WSDL contract.
in order for performing the remote invocation (which internally goes through remote JNDI lookup of the
connection factory), the calling user credentials need to be set into the Apache CXF JMSConduit:
WildFly 9
Have a look at the WildFly domain and messaging configuration for finding out the actual security
requirements. At the time of writing, a user with guest role is required and that's internally checked
using the other security domain.
Of course once the endpoint is exposed over JMS transport, any plain JMS client can also be used to send
messages to the webservice endpoint. You can have a look at the SOAP over JMS spec details and code
the client similarly to
WildFly 9
In this example we create a deployment containing an endpoint that serves over both HTTP and JMS
transports.
We from a WSDL contract such as below (please note we've two binding / portType for the same
service):
WildFly 9
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:binding name="HttpHelloWorldServiceSoapBinding" type="tns:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="echo">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="echo">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="echoResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldService">
<soapjms:jndiConnectionFactoryName>java:jms/RemoteConnectionFactory</soapjms:jndiConnectionFactoryName>
<soapjms:jndiInitialContextFactory>org.jboss.naming.remote.client.InitialContextFactory</soapjms:jndiInitialCo
<soapjms:jndiURL>http-remoting://localhost:8080</soapjms:jndiURL>
<wsdl:port binding="tns:HelloWorldServiceSoapBinding" name="HelloWorldImplPort">
<soap:address location="jms:queue:testQueue"/>
</wsdl:port>
<wsdl:port binding="tns:HttpHelloWorldServiceSoapBinding" name="HttpHelloWorldImplPort">
<soap:address location="http://localhost:8080/jaxws-cxf-jms-http-deployment"/>
</wsdl:port>
</wsdl:service>
<wsdl:service name="HelloWorldServiceLocal">
<soapjms:jndiConnectionFactoryName>java:/ConnectionFactory</soapjms:jndiConnectionFactoryName>
<wsdl:port binding="tns:HelloWorldServiceSoapBinding" name="HelloWorldImplPort">
<soap:address location="jms:queue:testQueue"/>
</wsdl:port>
</wsdl:definitions>
The same considerations of the previous example regarding the JMS queue and JNDI connection factory
still apply.
Here we can implement the endpoint in multiple ways, either with a common implementation class that's
extended by the JMS and HTTP ones, or keep the two implementation classes independent and just have
them implement the same service endpoint interface:
WildFly 9
package org.jboss.test.ws.jaxws.cxf.jms_http;
import javax.jws.WebService;
@WebService
(
portName = "HelloWorldImplPort",
serviceName = "HelloWorldServiceLocal",
wsdlLocation = "WEB-INF/wsdl/HelloWorldService.wsdl",
endpointInterface = "org.jboss.test.ws.jaxws.cxf.jms_http.HelloWorld",
targetNamespace = "http://org.jboss.ws/jaxws/cxf/jms"
)
public class HelloWorldImpl implements HelloWorld
{
public String echo(String input)
{
System.out.println("input: " + input);
return input;
}
}
package org.jboss.test.ws.jaxws.cxf.jms_http;
import javax.jws.WebService;
@WebService
(
portName = "HttpHelloWorldImplPort",
serviceName = "HelloWorldService",
wsdlLocation = "WEB-INF/wsdl/HelloWorldService.wsdl",
endpointInterface = "org.jboss.test.ws.jaxws.cxf.jms_http.HelloWorld",
targetNamespace = "http://org.jboss.ws/jaxws/cxf/jms"
)
public class HttpHelloWorldImpl implements HelloWorld
{
public String echo(String input)
{
System.out.println("input (http): " + input);
return "(http) " + input;
}
}
Both classes are packaged together the service endpoint interface and the WSDL file in a war archive:
WildFly 9
A trivial web.xml descriptor is also included to trigger the HTTP endpoint publish:
Here too the MANIFEST.MF needs to declare a dependency on org.hornetq module when
deploying to WildFly.
Finally, the JAX-WS client can ineract with both JMS and HTTP endpoints as usual:
WildFly 9
//start another bus to avoid affecting the one that could already be assigned to current thread
- optional but highly suggested
Bus bus = BusFactory.newInstance().createBus();
BusFactory.setThreadDefaultBus(bus);
try
{
QName serviceName = new QName("http://org.jboss.ws/jaxws/cxf/jms", "HelloWorldService");
Service service = Service.create(wsdlUrl, serviceName);
//JMS test
HelloWorld proxy = (HelloWorld) service.getPort(new
QName("http://org.jboss.ws/jaxws/cxf/jms", "HelloWorldImplPort"), HelloWorld.class);
setupProxy(proxy);
proxy.echo("Hi");
//HTTP test
HelloWorld httpProxy = (HelloWorld) service.getPort(new
QName("http://org.jboss.ws/jaxws/cxf/jms", "HttpHelloWorldImplPort"), HelloWorld.class);
httpProxy.echo("Hi");
}
finally
{
bus.shutdown(true);
}
where HelloWorldImpl is a POJO endpoint implementation referencing a JMS port in a given WSDL
contract, as explained in the previous examples.
The main difference among the deployment approach is in the direct control and responsibility over the
endpoint lifecycle (start/publish and stop).
WildFly 9
HTTP Proxy
The HTTP Proxy related functionalities of JBoss Web Services are provided by the Apache CXF http
transport layer.
The suggested configuration mechanism when running JBoss Web Services is explained below; for further
information please refer to the Apache CXF documentation.
Configuration
The HTTP proxy configuration for a given JAX-WS client can be set in the following ways:
through the http.proxyHost and http.proxyPort system properties, or
leveraging the org.apache.cxf.transport.http.HTTPConduit options
The former is a JVM level configuration; for instance, assuming the http proxy is currently running at
http://localhost:9934, here is the setup:
System.getProperties().setProperty("http.proxyHost", "localhost");
System.getProperties().setProperty("http.proxyPort", 9934);
The latter is a client stub/port level configuration: the setup is performed on the HTTPConduit object that's
part of the Apache CXF Client abstraction.
import org.apache.cxf.configuration.security.ProxyAuthorizationPolicy;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.apache.cxf.transports.http.configuration.ProxyServerType;
...
Service service = Service.create(wsdlURL, new QName("http://org.jboss.ws/jaxws/cxf/httpproxy",
"HelloWorldService"));
HelloWorld port = (HelloWorld) service.getPort(new
QName("http://org.jboss.ws/jaxws/cxf/httpproxy", "HelloWorldImplPort"), HelloWorld.class);
Client client = ClientProxy.getClient(port);
HTTPConduit conduit = (HTTPConduit)client.getConduit();
ProxyAuthorizationPolicy policy = new ProxyAuthorizationPolicy();
policy.setAuthorizationType("Basic");
policy.setUserName(PROXY_USER);
policy.setPassword(PROXY_PWD);
conduit.setProxyAuthorization(policy);
port.echo("Foo");
The ProxyAuthorizationPolicy also allows for setting the authotization type as well as the username /
password to be used.
WildFly 9
Speaking of authorization and authentication, please note that the JDK already features the
java.net.Authenticator facility, which is used whenever opening a connection to a given URL
requiring a http proxy. Users might want to set a custom Authenticator for instance when needing to read
WSDL contracts before actually calling into the JBoss Web Services / Apache CXF code; here is an
example:
import java.net.Authenticator;
import java.net.PasswordAuthentication;
...
public class ProxyAuthenticator extends Authenticator
{
private String user, password;
public ProxyAuthenticator(String user, String password)
{
this.user = user;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user, password.toCharArray());
}
}
...
Authenticator.setDefault(new ProxyAuthenticator(PROXY_USER, PROXY_PWD));
WildFly 9
Discovery
Apache CXF includes support for Web Services Dynamic Discovery (WS-Discovery), which is a protocol to
enable dynamic discovery of services available on the local network. The protocol implies using a UDP based
multicast transport to announce new services and probe for existing services. A managed mode where a
discovery proxy is used to reduce the amount of required multicast traffic is also covered by the protocol.
JBossWS integrates the WS-Discovery functionalities provided by Apache CXF into the application server.
Enabling WS-Discovery
Apache CXF enables WS-Discovery depending on the availability of its runtime component; given that's
always shipped in the application server, JBossWS integration requires using the
cxf.ws-discovery.enabled property usage for enabling WS-Discovery for a given deployment. By
default WS-Discovery is disabled on the application server. Below is an example of jboss-webservices.xml
descriptor to be used for enabling WS-Discovery:
<webservices xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.2" xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee">
<property>
<name>cxf.ws-discovery.enabled</name>
<value>true</value>
</property>
</webservices>
By default, a WS-Discovery service endpoint (SOAP-over-UDP bound) will be started the first time a
WS-Discovery enabled deployment is processed on the application server. Every ws endpoint belonging to
WS-Discovery enabled deployments will be automatically registered into such a WS-Discovery service
endpoint (Hello messages). The service will reply to Probe and Resolve messages received on UDP port
3702 (including multicast messages sent to IPv4 address 239.255.255.250, as per specification).
Endpoints will eventually be automatically unregistered using Bye messages upon undeployment.
Probing services
Apache CXF comes with a WS-Discovery API that can be used to probe / resolve services. When running
in-container, a JBoss module dependency to the org.apache.cxf.impl module is to be set to have
access to WS-Discovery client functionalities.
The org.apache.cxf.ws.discovery.WSDiscoveryClient class provides the probe and resolve methods which
also accepts filters on scopes. Users can rely on them for locating available endpoints on the network.
Please have a look at the JBossWS testsuite which includes a sample on CXF WS-Discovery usage.
WildFly 9
Policy
Apache CXF WS-Policy support
Contract-first approach
Code-first approach
JBossWS additions
Policy sets
Contract-first approach
WS-Policies can be attached and referenced in wsdl elements (the specifications describe all possible
alternatives). Apache CXF automatically recognizes, reads and uses policies defined in the wsdl.
Users should hence develop endpoints using the contract-first approach, that is explicitly providing the
contract for their services. Here is a excerpt taken from a wsdl including a WS-Addressing policy:
Of course, CXF also acts upon policies specified in wsdl documents consumed on client side.
WildFly 9
Code-first approach
For those preferring code-first (java-first) endpoint development, Apache CXF comes with
org.apache.cxf.annotations.Policy and org.apache.cxf.annotations.Policies
annotations to be used for attaching policy fragments to the wsdl generated at deploy time.
Here is an example of a code-first endpoint including @Policy annotation:
import javax.jws.WebService;
import org.apache.cxf.annotations.Policy;
@WebService(portName = "MyServicePort",
serviceName = "MyService",
name = "MyServiceIface",
targetNamespace = "http://www.jboss.org/jbossws/foo")
@Policy(placement = Policy.Placement.BINDING, uri = "JavaFirstPolicy.xml")
public class MyServiceImpl {
public String sayHello() {
return "Hello World!";
}
}
The referenced descriptor is to be added to the deployment and will include the policy to be attached; the
attachment position in the contracts is defined through the placement attribute. Here is a descriptor
example:
JBossWS additions
Policy sets
WildFly 9
Both approaches above require users to actually write their policies' assertions; while this offer great
flexibility and control of the actual contract, providing the assertions might end up being quite a challenging
task for complex policies. For this reason, the JBossWS integration provides policy sets, which are basically
pre-defined groups of policy assertions corresponding to well known / common needs. Each set has a label
allowing users to specify it in the @org.jboss.ws.api.annotation.PolicySets annotation to have
the policy assertions for that set attached to the annotated endpoint. Multiple labels can also be specified.
Here is an example of the @PolicySets annotation on a service endpoint interface:
import javax.jws.WebService;
import org.jboss.ws.api.annotation.PolicySets;
@WebService(name = "EndpointTwo", targetNamespace = "http://org.jboss.ws.jaxws.cxf/jbws3648")
@PolicySets({"WS-RM_Policy_spec_example", "WS-SP-EX223_WSS11_Anonymous_X509_Sign_Encrypt",
"WS-Addressing"})
public interface EndpointTwo
{
String echo(String input);
}
The three sets specified in @PolicySets will cause the wsdl generated for the endpoint having this interface
to be enriched with some policy assertions for WS-RM, WS-Security and WS-Addressing.
The labels' list of known sets is stored in the
META-INF/policies/org.jboss.wsf.stack.cxf.extensions.policy.PolicyAttachmentStore
file within the jbossws-cxf-client.jar (org.jboss.ws.cxf:jbossws-cxf-client maven artifact).
Actual policy fragments for each set are also stored in the same artifact at
META-INF/policies/<set-label>-<attachment-position>.xml.
Here is a list of the available policy sets:
Label
Description
WS-Addressing
Basic
WS-Addressing
policy
WS-RM_Policy_spec_example
WS-SP-EX2121_SSL_UT_Supporting_Token
WildFly 9
WS-SP-EX213_WSS10_UT_Mutual_Auth_X509_Sign_Encrypt
WS-SP-EX214_WSS11_User_Name_Cert_Sign_Encrypt
WS-SP-EX221_WSS10_Mutual_Auth_X509_Sign_Encrypt
WS-SP-EX222_WSS10_Mutual_Auth_X509_Sign_Encrypt
WS-SP-EX223_WSS11_Anonymous_X509_Sign_Encrypt
WS-SP-EX224_WSS11_Mutual_Auth_X509_Sign_Encrypt
WildFly 9
AsymmetricBinding_X509v1_TripleDesRsa15_EncryptBeforeSigning_ProtectTokens A WS-Security
policy for
asymmetric binding
(encrypt before
signing) using
X.509v1 tokens,
3DES + RSA 1.5
algorithms and with
token protections
enabled
AsymmetricBinding_X509v1_GCM256OAEP_ProtectTokens
The same as
before, but using
custom Apache
CXF algorithm suite
including GCM 256
+ RSA OAEP
algorithms
Always verify the contents of the generated wsdl contract, as policy sets are potentially subject to
updates between JBossWS releases. This is especially important when dealing with security
related policies; the provided sets are to be considered as convenient configuration options only;
users remain responsible for the policies in their contracts.
If you feel a new set should be added, just propose it by writing the user forum!
WildFly 9
WildFly 9
Name
Type
Description
modify-wsdl-address
boolean This boolean enables and disables the address rewrite functionality.
When modify-wsdl-address is set to true and the content of
<soap:address> is a valid URL, JBossWS will rewrite the URL using the
values of wsdl-host and wsdl-port or wsdl-secure-port.
When modify-wsdl-address is set to false and the content of
<soap:address> is a valid URL, JBossWS will not rewrite the URL. The
<soap:address> URL will be used.
When the content of <soap:address> is not a valid URL, JBossWS will
rewrite it no matter what the setting of modify-wsdl-address.
If modify-wsdl-address is set to true and wsdl-host is not defined or
explicitly set to 'jbossws.undefined.host' the content of
<soap:address> URL is use. JBossWS uses the requester's host when
rewriting the <soap:address>
When modify-wsdl-address is not defined JBossWS uses a default value
of true.
wsdl-host
string
wsdl-port
int
Set this property to explicitly define the HTTP port that will be used for
rewriting the SOAP address.
Otherwise the HTTP port will be identified by querying the list of installed
HTTP connectors.
wsdl-secure-port
int
Set this property to explicitly define the HTTPS port that will be used for
rewriting the SOAP address.
Otherwise the HTTPS port will be identified by querying the list of
installed HTTPS connectors.
wsdl-uri-scheme
string
This property explicitly sets the URI scheme to use for rewriting
<soap:address> . Valid values are http and https. This
configuration overrides scheme computed by processing the endpoint
(even if a transport guarantee
is specified). The provided values for wsdl-port and
wsdl-secure-port (or their default values) are used depending on
specified scheme.
wsdl-path-rewrite-rule string
WildFly 9
Additionally, users can override the server level configuration by requesting a specific rewrite behavior for a
given endpoint deployment. That is achieved by setting one of the following properties within a
jboss-webservices.xml descriptor:
Property
wsdl.soapAddress.rewrite.modify-wsdl-address
modify-wsdl-address
wsdl.soapAddress.rewrite.wsdl-host
wsdl-host
wsdl.soapAddress.rewrite.wsdl-port
wsdl-port
wsdl.soapAddress.rewrite.wsdl-secure-port
wsdl-secure-port
wsdl.soapAddress.rewrite.wsdl-path-rewrite-rule wsdl-path-rewrite-rule
wsdl.soapAddress.rewrite.wsdl-uri-scheme
wsdl-uri-scheme
Here is an example of partial overriding of the default configuration for a specific deployment:
WildFly 9
<wsdl:definitions ...>
...
<wsdl:binding name="ServiceOneSoapBinding" type="tns:EndpointOne">
...
<wsp:PolicyReference URI="#@org.jboss.wsf.test.JBWS3628TestCase.policy@"/>
<wsdl:operation name="echo">
...
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ServiceOne">
<wsdl:port binding="tns:ServiceOneSoapBinding" name="EndpointOnePort">
<soap:address location="http://localhost:8080/jaxws-cxf-jbws3628/ServiceOne"/>
</wsdl:port>
</wsdl:service>
<wsp:Policy
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://www.w3.org/ns/ws-policy" wsu:Id="WS-RM_Policy">
<wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy">
...
</wsrmp:RMAssertion>
</wsp:Policy>
<wsp:Policy
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://www.w3.org/ns/ws-policy"
xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" wsu:Id="WS-Addressing_policy">
<wsam:Addressing>
<wsp:Policy/>
</wsam:Addressing>
</wsp:Policy>
</wsdl:definitions>
WildFly 9
The JBoss Web Services functionalities are provided by a given set of modules / libraries installed on
WildFly, which are organized into JBoss Modules modules. In particular the org.jboss.as.webservices.* and
org.jboss.ws.* modules belong to the JBossWS - WildFly integration. Users should not need to change
anything in them.
While users are of course allowed to provide their own modules for their custom needs, below is a brief
collection of suggestions and hints around modules and webservices development on WildFly.
The JBoss Web Services APIs are always available by default whenever the webservices
subsystem is available on AS7. So users just use them, no need for explicit dependencies
declaration for those modules.
Using MANIFEST.MF
The convenient method for configuring deployment dependencies is adding them into the MANIFEST.MF
file:
Manifest-Version: 1.0
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client services export,foo.bar
Here above org.jboss.ws.cxf.jbossws-cxf-client and foo.bar are the modules you want to set dependencies
to; services tells the modules framework that you want to also import META-INF/services/.. declarations from
the dependency, while export exports the classes from the module to any other module that might be
depending on the module implicitly created for your deployment.
When using annotations on your endpoints / handlers such as the Apache CXF ones
(@InInterceptor, @GZIP, ...) remember to add the proper module dependency in your manifest.
Otherwise your annotations are not picked up and added to the annotation index by WildFly,
resulting in them being completely and silently ignored.
Using JAXB
In order for successfully directly using JAXB contexts, etc. in your client or endpoint running in-container, you
need to properly setup a JAXB implementation; that is performed setting the following dependency:
WildFly 9
However, please note that would not come with any JBossWS-CXF customizations nor additional
extensions. For this reason, and generally speaking for simplifying user configuration, a client side
aggregation module is available with all the WS dependencies users might need.
Please note the services option above: that's strictly required in order for you to get the JBossWS-CXF
version of classes that are retrieved using the Service API, the org.apache.cxf.Bus for instance.
Be careful as issues because of misconfiguration here can be quite hard to track down, because
the Apache CXF behaviour would be sensibly different.
Annotation scanning
The application server uses an annotation index for detecting JAX-WS endpoints in user deployments. When
declaring WS endpoints whose class belongs to a different module (for instance referring that in the
web.xml descriptor), be sure to have an annotations type dependency in place. Without that, your
endpoints would simply be ignored as they won't appear as annotated classes to the webservices
subsystem.
WildFly 9
Using jboss-deployment-descriptor.xml
In some circumstances, the convenient approach of setting module dependencies in MANIFEST.MF might
not work. An example is the need for importing/exporting specific resources from a given module
dependency. Users should hence add a jboss-deployment-structure.xml descriptor to their deployment and
set module dependencies in it.
WildFly 9
WildFly 9
EJB Timer
Marking an EJB as clustered
Deploying clustered EJBs
Failover for clustered EJBs
Remote standalone clients
Cluster topology communication
Remote clients on another instance of WildFly 8
Testcases for failover of stateful beans
Hibernate
Related Issues
Modularity And Class Loading
Monitoring
Changes From Previous Versions
Key changes
Migration to Wildfly
WildFly 8 Cluster Howto
References
All WildFly 8 documentation
WildFly 9
These two independent high availability services can very effectively inter-operate when making
use of mod_cluster for load balancing!
Taking advantage of WildFly's high availability services is easy, and simply involves deploying WildFly on a
cluster of nodes, making a small number of application configuration changes, and then deploying the
application in the cluster.
We now take a brief look at what these services can guarantee.
WildFly 9
WildFly 9
JGroups Subsystem
Purpose
The JGroups subsystem provides group communication support for HA services in the form of JGroups
channels.
Named channel instances permit application peers in a cluster to communicate as a group and in such a
way that the communication satisfies defined properties (e.g. reliable, ordered, failure-sensitive).
Communication properties are configurable for each channel and are defined by the protocol stack used to
create the channel. Protocol stacks consist of a base transport layer (used to transport messages around the
cluster) together with a user-defined, ordered stack of protocol layers, where each protocol layer supports a
given communication property.
The JGroups subsystem provides the following features:
allows definition of named protocol stacks
view run-time metrics associated with channels
specify a default stack for general use
In the following sections, we describe the JGroups subsystem.
JGroups channels are created transparently as part of the clustering functionality (e.g. on clustered
application deployment, channels will be created behind the scenes to support clustered features
such as session replication or transmission of SSO contexts around the cluster).
WildFly 9
Configuration example
What follows is a sample JGroups subsystem configuration showing all of the possible elements and
attributes which may be configured. We shall use this example to explain the meaning of the various
elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:jgroups:2.0" default-stack="udp">
<stack name="udp">
<transport type="UDP" socket-binding="jgroups-udp"
diagnostics-socket-binding="jgroups-diagnostics"
default-executor="jgroups" oob-executor="jgroups-oob" timer-executor="jgroups-timer"
shared="false" thread-factory="jgroups-thread-factory"
machine="machine1" rack="rack1" site="site1"/>
<protocol type="PING">
<property name="timeout">100</property>
</protocol>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<protocol type="MPING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="udp-xsite">
<transport type="UDP" socket-binding="jgroups-udp"/>
<protocol type="PING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
<relay site="LONDON">
<remote-site name="SFO" stack="tcp" cluster="global"/>
<remote-site name="NYC" stack="tcp" cluster="global"/>
</relay>
</stack>
</subsystem>
WildFly 9
<subsystem>
This element is used to configure the subsystem within a Wildfly system profile.
xmlns This attribute specifies the XML namespace of the JGroups subsystem and, in particular, its
version.
default-stack This attribute is used to specify a default stack for the JGroups subsystem. This
default stack will be used whenever a stack is required but no stack is specified.
<stack>
This element is used to configure a JGroups protocol stack.
name This attribute is used to specify the name of the stack.
WildFly 9
<transport>
This element is used to configure the transport layer (required) of the protocol stack.
type This attribute specifies the transport type (e.g. UDP, TCP, TCPGOSSIP)
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally.
diagnostics-socket-binding This attribute references a defined socket binding in the server
profile. It is used when JGroups needs to create sockets for use with the diagnostics program. For
more about the use of diagnostics, see the JGroups documentation for probe.sh.
default-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle incoming JGroups
messages.
oob-executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle incoming JGroups OOB
(out-of-bound) messages.
timer-executor This attribute references a defined thread pool executor in the threads subsystem.
It governs the allocation and execution of runnable timer-related tasks.
shared This attribute indicates whether or not this transport is shared amongst several JGroups
stacks or not.
thread-factory This attribute references a defined thread factory in the threads subsystem. It
governs the allocation of threads for running tasks which are not handled by the executors above.
site This attribute defines a site (data centre) id for this node.
rack This attribute defines a rack (server rack) id for this node.
machine This attribute defines a machine (host) is for this node.
site, rack and machine ids are used by the Infinispan topology-aware consistent hash function,
which when using dist mode, prevents dist mode replicas from being stored on the same host, rack
or site
<property>
This element is used to configure a transport property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
WildFly 9
<protocol>
This element is used to configure a (non-transport) protocol layer in the JGroups stack. Protocol layers are
ordered within the stack.
type This attribute specifies the name of the JGroups protocol implementation (e.g. MPING,
pbcast.GMS), with the package prefix org.jgroups.protocols removed.
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally for this protocol instance.
<property>
This element is used to configure a protocol property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
<relay>
This element is used to configure the RELAY protocol for a JGroups stack. RELAY is a protocol which
provides cross-site replication between defined sites (data centres). In the RELAY protocol, defined sites
specify the names of remote sites (backup sites) to which their data should be backed up. Channels are
defined between sites to permit the RELAY protocol to transport the data from the current site to a backup
site.
site This attribute specifies the name of the current site. Site names can be referenced elsewhere
(e.g. in the JGroups remote-site configuration elements, as well as backup configuration elements in
the Infinispan subsystem)
<remote-site>
This element is used to configure a remote site for the RELAY protocol.
name This attribute specifies the name of the remote site to which this configuration applies.
stack This attribute specifies a JGroups protocol stack to use for communication between this site
and the remote site.
cluster This attribute specifies the name of the JGroups channel to use for communication between
this site and the remote site.
WildFly 9
Use Cases
In many cases, channels will be configured via XML as in the example above, so that the channels will be
available upon server startup. However, channels may also be added, removed or have their configurations
changed in a running server by making use of the Wildfly management API command-line interface (CLI). In
this section, we present some key use cases for the JGroups management API.
The key use cases covered are:
adding a stack
adding a protocol to an existing stack
adding a property to a protocol
The Wildfly management API command-line interface (CLI) itself can be used to provide extensive
information on the attributes and commands available in the JGroups subsystem interface used in
these examples.
Add a stack
/subsystem=jgroups/stack=mystack:add(transport={}, protocols={})
/subsystem=jgroups/stack=mystack:add-protocol(type=<type>, socket-binding=<socketbinding>)
Infinispan Subsystem
WildFly 9
Purpose
The Infinispan subsystem provides caching support for HA services in the form of Infinispan caches:
high-performance, transactional caches which can operate in both non-distributed and distributed
scenarios. Distributed caching support is used in the provision of many key HA services. For example, the
failover of a session-oriented client HTTP request from a failing node to a new (failover) node depends on
session data for the client being available on the new node. In other words, the client session data needs to
be replicated across nodes in the cluster. This is effectively achieved via a distributed Infinispan cache. This
approach to providing fail-over also applies to EJB SFSB sessions. Over and above providing support for
fail-over, an underlying cache is also required when providing second-level caching for entity beans using
Hibernate, and this case is also handled through the use of an Infinispan cache.
The Infinispan subsystem provides the following features:
allows definition and configuration of named cache containers and caches
view run-time metrics associated with cache container and cache instances
In the following sections, we describe the Infinispan subsystem.
Infiispan cache containers and caches are created transparently as part of the clustering
functionality (e.g. on clustered application deployment, cache containers and their associated
caches will be created behind the scenes to support clustered features such as session replication
or caching of entities around the cluster).
Configuration Example
In this section, we provide an example XML configuration of the infinispan subsystem and review the
configuration elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:infinispan:2.0">
<cache-container name="server" aliases="singleton cluster" default-cache="default"
module="org.wildfly.clustering.server">
<transport lock-timeout="60000"/>
<replicated-cache name="default" mode="SYNC" batching="true">
<locking isolation="REPEATABLE_READ"/>
</replicated-cache>
</cache-container>
<cache-container name="web" aliases="standard-session-cache" default-cache="repl"
module="org.wildfly.clustering.web.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<file-store/>
</replicated-cache>
<replicated-cache name="sso" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="ejb" aliases="sfsb sfsb-cache" default-cache="repl"
module="org.jboss.as.clustering.ejb3.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</replicated-cache>
<!-~ Clustered cache used internally by EJB subsytem for managing the client-mapping(s) of
~
the socketbinding referenced by the EJB remoting connector
-->
<replicated-cache name="remote-connector-client-mappings" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="hibernate" default-cache="local-query" module="org.hibernate">
<transport lock-timeout="60000"/>
<local-cache name="local-query">
<transaction mode="NONE"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<invalidation-cache name="entity" mode="SYNC">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</invalidation-cache>
<replicated-cache name="timestamps" mode="ASYNC">
<transaction mode="NONE"/>
<eviction strategy="NONE"/>
</replicated-cache>
</cache-container>
</subsystem>
WildFly 9
<cache-container>
This element is used to configure a cache container.
name This attribute is used to specify the name of the cache container.
default-cache This attribute configures the default cache to be used, when no cache is otherwise
specified.
listener-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks in the replication queue.
eviction-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle evictions.
replication-queue-executor This attribute references a defined thread pool executor in the
threads subsystem. It governs the allocation and execution of runnable tasks to handle asynchronous
cache operations.
jndi-name This attribute is used to assign a name for the cache container in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
aliases This attribute is used to define aliases for the cache container name.
This element has the following child elements: <transport>, <local-cache>, <invalidation-cache>,
<replicated-cache>, and <distributed-cache>.
WildFly 9
<transport>
This element is used to configure the JGroups transport used by the cache container, when required.
stack This attribute configures the JGroups stack to be used for the transport. If none is specified,
the default-stack for the JGroups subsystem is used.
cluster This attribute configures the name of the group communication cluster. This is the name
which will be seen in debugging logs.
executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle ? <fill me in >?.
lock-timeout This attribute configures the time-out to be used when obtaining locks for the
transport.
site This attribute configures the site id of the cache container.
rack This attribute configures the rack id of the cache container.
machine This attribute configures the machine id of the cache container.
The presence of the transport element is required when operating in clustered mode
These cache-related elements are actually part of an xsd hierarchy with abstract complexTypes
cache, clustered-cache, and shared-cache. In order to simplify the presentation, we notate these
as pseudo-elements <abstract cache>, <abstract clustered-cache> and <abstract
shared-cache>. In what follows, we first describe the extension hierarchy of base elements, and
then show how the cache type elements relate to them.
<abstract cache>
This abstract base element defines the attributes and child elements common to all non-clustered caches.
name This attribute configures the name of the cache. This name may be referenced by other
subsystems.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
batching This attribute configures batching. If enabled, the invocation batching API will be made
available for this cache.
indexing This attribute configures indexing. If enabled, entries will be indexed when they are added
to the cache. Indexes will be updated as entries change or are removed.
jndi-name This attribute is used to assign a name for the cache in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
WildFly 9
The <abstract cache> abstract base element has the following child elements: <indexing-properties>,
<locking>, <transaction>, <eviction>, <expiration>, <store>, <file-store>, <string-keyed-jdbc-store>,
<binary-keyed-jdbc-store>, <mixed-keyed-jdbc-store>, <remote-store>.
<indexing-properties>
This child element defines properties to control indexing behaviour.
<locking>
This child element configures the locking behaviour of the cache.
isolation This attribute the cache locking isolation level. Allowable values are NONE,
SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED.
striping If true, a pool of shared locks is maintained for all entries that need to be locked.
Otherwise, a lock is created per entry in the cache. Lock striping helps control memory footprint but
may reduce concurrency in the system.
acquire-timeout This attribute configures the maximum time to attempt a particular lock
acquisition.
concurrency-level This attribute is used to configure the concurrency level. Adjust this value
according to the number of concurrent threads interacting with Infinispan.
<transaction>
This child element configures the transactional behaviour of the cache.
mode This attribute configures the transaction mode, setting the cache transaction mode to one of
NONE, NON_XA, NON_DURABLE_XA, FULL_XA.
stop-timeout If there are any ongoing transactions when a cache is stopped, Infinispan waits for
ongoing remote and local transactions to finish. The amount of time to wait for is defined by the cache
stop timeout.
locking This attribute configures the locking mode for this cache, one of OPTIMISTIC or
PESSIMISTIC.
<eviction>
This child element configures the eviction behaviour of the cache.
strategy This attribute configures the cache eviction strategy. Available options are 'UNORDERED',
'FIFO', 'LRU', 'LIRS' and 'NONE' (to disable eviction).
max-entries This attribute configures the maximum number of entries in a cache instance. If
selected value is not a power of two the actual value will default to the least power of two larger than
selected value. -1 means no limit.
WildFly 9
<expiration>
This child element configures the expiration behaviour of the cache.
max-idle This attribute configures the maximum idle time a cache entry will be maintained in the
cache, in milliseconds. If the idle time is exceeded, the entry will be expired cluster-wide. -1 means
the entries never expire.
lifespan This attribute configures the maximum lifespan of a cache entry, after which the entry is
expired cluster-wide, in milliseconds. -1 means the entries never expire.
interval This attribute specifies the interval (in ms) between subsequent runs to purge expired
entries from memory and any cache stores. If you wish to disable the periodic eviction process
altogether, set wakeupInterval to -1.
The remaining child elements of the abstract base element <cache>, namely <store>, <file-store>,
<remote-store>, <string-keyed-jdbc-store>, <binary-keyed-jdbc-store> and <mixed-keyed-jdbc-store>,
each configures one of six key cache store types.
These cache store-related elements are actually part of an xsd extension hierarchy with abstract
complexTypes base-store and base-jdbc-store. As before, in order to simplify the presentation,
we notate these as pseudo-elements <abstract base-store> and <abstract base-jdbc-store>. In
what follows, we first describe the extension hierarchy of base elements, and then show how the
cache store elements relate to them.
WildFly 9
<abstract base-store>
This abstract base element defines the attributes and child elements common to all cache stores.
shared This attribute should be set to true when multiple cache instances share the same cache
store (e.g. multiple nodes in a cluster using a JDBC-based CacheStore pointing to the same, shared
database) Setting this to true avoids multiple cache instances writing the same modification multiple
times. If enabled, only the node where the modification originated will write to the cache store. If
disabled, each individual cache reacts to a potential remote update by storing the data to the cache
store.
preload This attribute configures whether or not, when the cache starts, data stored in the cache
loader will be pre-loaded into memory. This is particularly useful when data in the cache loader is
needed immediately after start-up and you want to avoid cache operations being delayed as a result
of loading this data lazily. Can be used to provide a 'warm-cache' on start-up, however there is a
performance penalty as start-up time is affected by this process. Note that pre-loading is done in a
local fashion, so any data loaded is only stored locally in the node. No replication or distribution of the
preloaded data happens. Also, Infinispan only pre-loads up to the maximum configured number of
entries in eviction.
passivation If true, data is only written to the cache store when it is evicted from memory, a
phenomenon known as passivation. Next time the data is requested, it will be 'activated' which means
that data will be brought back to memory and removed from the persistent store. If false, the cache
store contains a copy of the cache contents in memory, so writes to cache result in cache store
writes. This essentially gives you a 'write-through' configuration.
fetch-state This attribute, if true, causes persistent state to be fetched when joining a cluster. If
multiple cache stores are chained, only one of them can have this property enabled.
purge This attribute configures whether the cache store is purged upon start-up.
singleton This attribute configures whether or not the singleton store cache store is enabled.
SingletonStore is a delegating cache store used for situations when only one instance in a cluster
should interact with the underlying store.
class This attribute configures a custom store implementation class to use for this cache store.
properties This attribute is used to configure a list of cache store properties.
The abstract base element has one child element: <write-behind>
<write-behind>
This element is used to configure a cache store as write-behind instead of write-through. In write-through
mode, writes to the cache are also synchronously written to the cache store, whereas in write-behind mode,
writes to the cache are followed by asynchronous writes to the cache store.
flush-lock-timeout This attribute configures the time-out for acquiring the lock which guards the
state to be flushed to the cache store periodically.
modification-queue-size This attribute configures the maximum number of entries in the
asynchronous queue. When the queue is full, the store becomes write-through until it can accept new
entries.
shutdown-timeout This attribute configures the time-out (in ms) to stop the cache store.
thread-pool This attribute is used to configure the size of the thread pool whose threads are
responsible for applying the modifications to the cache store.
WildFly 9
<abstract base-jdbc-store> extends <abstract base-store>
This abstract base element defines the attributes and child elements common to all JDBC-based cache
stores.
datasource This attribute configures the datasource for the JDBC-based cache store.
entry-table This attribute configures the database table used to store cache entries.
bucket-table This attribute configures the database table used to store binary cache entries.
<file-store> extends <abstract base-store>
This child element is used to configure a file-based cache store. This requires specifying the name of the file
to be used as backing storage for the cache store.
relative-to This attribute optionally configures a relative path prefix for the file store path. Can be
null.
path This attribute configures an absolute path to a file if relative-to is null; configures a relative path
to the file, in relation to the value for relative-to, otherwise.
<remote-store> extends <abstract base-store>
This child element of cache is used to configure a remote cache store. It has a child <remote-servers>.
cache This attribute configures the name of the remote cache to use for this remote store.
tcp-nodelay This attribute configures a TCP_NODELAY value for communication with the remote
cache.
socket-timeout This attribute configures a socket time-out for communication with the remote
cache.
<remote-servers>
This child element of cache configures a list of remote servers for this cache store.
<remote-server>
This element configures a remote server. A remote server is defined completely by a locally defined
outbound socket binding, through which communication is made with the server.
outbound-socket-binding This attribute configures an outbound socket binding for a remote
server.
WildFly 9
WildFly 9
WildFly 9
Use Cases
In many cases, cache containers and caches will be configured via XML as in the example above, so that
they will be available upon server start-up. However, cache containers and caches may also be added,
removed or have their configurations changed in a running server by making use of the Wildfly management
API command-line interface (CLI). In this section, we present some key use cases for the Infinispan
management API.
The key use cases covered are:
adding a cache container
adding a cache to an existing cache container
configuring the transaction subsystem of a cache
The Wildfly management API command-line interface (CLI) can be used to provide
extensive information on the attributes and commands available in the Infinispan subsystem
interface used in these examples.
Add a cache
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache:add()
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache/transaction=TRANSACTION:add(mode=<t
WildFly 9
mod_cluster Subsystem
The mod_cluster integration is done via the modcluster subsystem it requires mod_cluster-1.1.x.or
mod_cluster-1.2.x (since 7.1.0)
The modcluster subsystem supports several operations:
WildFly 9
The operations specific to the modcluster subsystem are divided in 3 categories the ones that affects the
configuration and require a restart of the subsystem, the one that just modify the behaviour temporarily and
the ones that display information from the httpd part.
WildFly 9
read-proxies-configuration
Send a DUMP message to all Apache httpd the node is connected to and display the message received
from Apache httpd.
WildFly 9
read-proxies-info
Send a INFO message to all Apache httpd the node is connected to and display the message received from
Apache httpd.
WildFly 9
list-proxies:
Displays the httpd that are connected to the node. The httpd could be discovered via the Advertise protocol
or via the proxy-list attribute.
remove-proxy
Remove a proxy from the discovered proxies or temporarily from the proxy-list attribute.
proxy
Add a proxy to the discovered proxies or temporarily to the proxy-list attribute.
WildFly 9
enable-context
Tell Apache httpd that the context is ready receive requests.
disable-context
Tell Apache httpd that it shouldn't send new session requests to the context of the virtualhost.
stop-context
Tell Apache httpd that it shouldn't send requests to the context of the virtualhost.
refresh
Refresh the node by sending a new CONFIG message to Apache httpd.
reset
reset the connection between Apache httpd and the node
Configuration
Metric configuration
There are 4 metric operations corresponding to add and remove load metrics to the dynamic-load-provider.
Note that when nothing is defined a simple-load-provider is use with a fixed load factor of one.
WildFly 9
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<simple-load-provider factor="1"/>
</mod-cluster-config>
</subsystem>
metric
Add a metric to the dynamic-load-provider, the dynamic-load-provider in configuration is created if needed.
remove-metric
Remove a metric from the dynamic-load-provider.
WildFly 9
custom-metric / remove-custom-metric
like the add-metric and remove-metric except they require a class parameter instead the type. Usually they
needed additional properties which can be specified
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<dynamic-load-provider history="9" decay="2">
<custom-load-metric class="myclass">
<property name="pro1" value="value1"/>
<property name="pro2" value="value2"/>
</custom-load-metric>
</dynamic-load-provider>
</mod-cluster-config>
</subsystem>
JVMRoute configuration
If you want to use your own JVM route instead of automatically generated one you can insert the following
property:
...
</extensions>
<system-properties>
<property name="jboss.mod_cluster.jvmRoute" value="myJvmRoute"/>
</system-properties>
<management>
...
WildFly 9
jboss-ejb3.xml
<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns:c="urn:clustering:1.0">
<jee:assembly-descriptor>
<c:clustering>
<jee:ejb-name>DDBasedClusteredBean</jee:ejb-name>
<c:clustered>true</c:clustered>
</c:clustering>
</jee:assembly-descriptor>
</jboss>
WildFly 9
./standalone.sh -server-config=standalone-ha.xml
This will start a single instance of the server with HA capabilities. Deploying the EJBs to this instance doesn't
involve anything special and is the same as explained in the application deployment chapter.
Obviously, to be able to see the benefits of clustering, you'll need more than one instance of the server. So
let's start another server with HA capabilities. That another instance of the server can either be on the same
machine or on some other machine. If it's on the same machine, the two things you have to make sure is
that you pass the port offset for the second instance and also make sure that each of the server instances
have a unique jboss.node.name system property. You can do that by passing the following two system
properties to the startup command:
Follow whichever approach you feel comfortable with for deploying the EJB deployment to this instance too.
Deploying the application on just one node of a standalone instance of a clustered server does not
mean that it will be automatically deployed to the other clustered instance. You will have to do
deploy it explicitly on the other standalone clustered instance too. Or you can start the servers in
domain mode so that the deployment can be deployed to all the server within a server group. See
the admin guide for more details on domain setup.
Now that you have deployed an application with clustered EJBs on both the instances, the EJBs are now
capable of making use of the clustering features.
WildFly 9
remote.clusters=ejb
remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED=false
WildFly 9
WildFly 9
7.5 Hibernate
WildFly 9
7.6.2 Monitoring
Describe resources available for monitoring clustered applications.
7.9 References
Couldn't find a page to include called: References
WildFly 9
These two independent high availability services can very effectively inter-operate when making
use of mod_cluster for load balancing!
Taking advantage of WildFly's high availability services is easy, and simply involves deploying WildFly on a
cluster of nodes, making a small number of application configuration changes, and then deploying the
application in the cluster.
We now take a brief look at what these services can guarantee.
WildFly 9
WildFly 9
JGroups Subsystem
Purpose
The JGroups subsystem provides group communication support for HA services in the form of JGroups
channels.
Named channel instances permit application peers in a cluster to communicate as a group and in such a
way that the communication satisfies defined properties (e.g. reliable, ordered, failure-sensitive).
Communication properties are configurable for each channel and are defined by the protocol stack used to
create the channel. Protocol stacks consist of a base transport layer (used to transport messages around the
cluster) together with a user-defined, ordered stack of protocol layers, where each protocol layer supports a
given communication property.
The JGroups subsystem provides the following features:
allows definition of named protocol stacks
view run-time metrics associated with channels
specify a default stack for general use
In the following sections, we describe the JGroups subsystem.
JGroups channels are created transparently as part of the clustering functionality (e.g. on clustered
application deployment, channels will be created behind the scenes to support clustered features
such as session replication or transmission of SSO contexts around the cluster).
WildFly 9
Configuration example
What follows is a sample JGroups subsystem configuration showing all of the possible elements and
attributes which may be configured. We shall use this example to explain the meaning of the various
elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:jgroups:2.0" default-stack="udp">
<stack name="udp">
<transport type="UDP" socket-binding="jgroups-udp"
diagnostics-socket-binding="jgroups-diagnostics"
default-executor="jgroups" oob-executor="jgroups-oob" timer-executor="jgroups-timer"
shared="false" thread-factory="jgroups-thread-factory"
machine="machine1" rack="rack1" site="site1"/>
<protocol type="PING">
<property name="timeout">100</property>
</protocol>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<protocol type="MPING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="udp-xsite">
<transport type="UDP" socket-binding="jgroups-udp"/>
<protocol type="PING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
<relay site="LONDON">
<remote-site name="SFO" stack="tcp" cluster="global"/>
<remote-site name="NYC" stack="tcp" cluster="global"/>
</relay>
</stack>
</subsystem>
WildFly 9
<subsystem>
This element is used to configure the subsystem within a Wildfly system profile.
xmlns This attribute specifies the XML namespace of the JGroups subsystem and, in particular, its
version.
default-stack This attribute is used to specify a default stack for the JGroups subsystem. This
default stack will be used whenever a stack is required but no stack is specified.
<stack>
This element is used to configure a JGroups protocol stack.
name This attribute is used to specify the name of the stack.
WildFly 9
<transport>
This element is used to configure the transport layer (required) of the protocol stack.
type This attribute specifies the transport type (e.g. UDP, TCP, TCPGOSSIP)
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally.
diagnostics-socket-binding This attribute references a defined socket binding in the server
profile. It is used when JGroups needs to create sockets for use with the diagnostics program. For
more about the use of diagnostics, see the JGroups documentation for probe.sh.
default-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle incoming JGroups
messages.
oob-executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle incoming JGroups OOB
(out-of-bound) messages.
timer-executor This attribute references a defined thread pool executor in the threads subsystem.
It governs the allocation and execution of runnable timer-related tasks.
shared This attribute indicates whether or not this transport is shared amongst several JGroups
stacks or not.
thread-factory This attribute references a defined thread factory in the threads subsystem. It
governs the allocation of threads for running tasks which are not handled by the executors above.
site This attribute defines a site (data centre) id for this node.
rack This attribute defines a rack (server rack) id for this node.
machine This attribute defines a machine (host) is for this node.
site, rack and machine ids are used by the Infinispan topology-aware consistent hash function,
which when using dist mode, prevents dist mode replicas from being stored on the same host, rack
or site
<property>
This element is used to configure a transport property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
WildFly 9
<protocol>
This element is used to configure a (non-transport) protocol layer in the JGroups stack. Protocol layers are
ordered within the stack.
type This attribute specifies the name of the JGroups protocol implementation (e.g. MPING,
pbcast.GMS), with the package prefix org.jgroups.protocols removed.
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally for this protocol instance.
<property>
This element is used to configure a protocol property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
<relay>
This element is used to configure the RELAY protocol for a JGroups stack. RELAY is a protocol which
provides cross-site replication between defined sites (data centres). In the RELAY protocol, defined sites
specify the names of remote sites (backup sites) to which their data should be backed up. Channels are
defined between sites to permit the RELAY protocol to transport the data from the current site to a backup
site.
site This attribute specifies the name of the current site. Site names can be referenced elsewhere
(e.g. in the JGroups remote-site configuration elements, as well as backup configuration elements in
the Infinispan subsystem)
<remote-site>
This element is used to configure a remote site for the RELAY protocol.
name This attribute specifies the name of the remote site to which this configuration applies.
stack This attribute specifies a JGroups protocol stack to use for communication between this site
and the remote site.
cluster This attribute specifies the name of the JGroups channel to use for communication between
this site and the remote site.
WildFly 9
Use Cases
In many cases, channels will be configured via XML as in the example above, so that the channels will be
available upon server startup. However, channels may also be added, removed or have their configurations
changed in a running server by making use of the Wildfly management API command-line interface (CLI). In
this section, we present some key use cases for the JGroups management API.
The key use cases covered are:
adding a stack
adding a protocol to an existing stack
adding a property to a protocol
The Wildfly management API command-line interface (CLI) itself can be used to provide extensive
information on the attributes and commands available in the JGroups subsystem interface used in
these examples.
Add a stack
/subsystem=jgroups/stack=mystack:add(transport={}, protocols={})
/subsystem=jgroups/stack=mystack:add-protocol(type=<type>, socket-binding=<socketbinding>)
Infinispan Subsystem
WildFly 9
Purpose
The Infinispan subsystem provides caching support for HA services in the form of Infinispan caches:
high-performance, transactional caches which can operate in both non-distributed and distributed
scenarios. Distributed caching support is used in the provision of many key HA services. For example, the
failover of a session-oriented client HTTP request from a failing node to a new (failover) node depends on
session data for the client being available on the new node. In other words, the client session data needs to
be replicated across nodes in the cluster. This is effectively achieved via a distributed Infinispan cache. This
approach to providing fail-over also applies to EJB SFSB sessions. Over and above providing support for
fail-over, an underlying cache is also required when providing second-level caching for entity beans using
Hibernate, and this case is also handled through the use of an Infinispan cache.
The Infinispan subsystem provides the following features:
allows definition and configuration of named cache containers and caches
view run-time metrics associated with cache container and cache instances
In the following sections, we describe the Infinispan subsystem.
Infiispan cache containers and caches are created transparently as part of the clustering
functionality (e.g. on clustered application deployment, cache containers and their associated
caches will be created behind the scenes to support clustered features such as session replication
or caching of entities around the cluster).
Configuration Example
In this section, we provide an example XML configuration of the infinispan subsystem and review the
configuration elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:infinispan:2.0">
<cache-container name="server" aliases="singleton cluster" default-cache="default"
module="org.wildfly.clustering.server">
<transport lock-timeout="60000"/>
<replicated-cache name="default" mode="SYNC" batching="true">
<locking isolation="REPEATABLE_READ"/>
</replicated-cache>
</cache-container>
<cache-container name="web" aliases="standard-session-cache" default-cache="repl"
module="org.wildfly.clustering.web.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<file-store/>
</replicated-cache>
<replicated-cache name="sso" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="ejb" aliases="sfsb sfsb-cache" default-cache="repl"
module="org.jboss.as.clustering.ejb3.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</replicated-cache>
<!-~ Clustered cache used internally by EJB subsytem for managing the client-mapping(s) of
~
the socketbinding referenced by the EJB remoting connector
-->
<replicated-cache name="remote-connector-client-mappings" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="hibernate" default-cache="local-query" module="org.hibernate">
<transport lock-timeout="60000"/>
<local-cache name="local-query">
<transaction mode="NONE"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<invalidation-cache name="entity" mode="SYNC">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</invalidation-cache>
<replicated-cache name="timestamps" mode="ASYNC">
<transaction mode="NONE"/>
<eviction strategy="NONE"/>
</replicated-cache>
</cache-container>
</subsystem>
WildFly 9
<cache-container>
This element is used to configure a cache container.
name This attribute is used to specify the name of the cache container.
default-cache This attribute configures the default cache to be used, when no cache is otherwise
specified.
listener-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks in the replication queue.
eviction-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle evictions.
replication-queue-executor This attribute references a defined thread pool executor in the
threads subsystem. It governs the allocation and execution of runnable tasks to handle asynchronous
cache operations.
jndi-name This attribute is used to assign a name for the cache container in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
aliases This attribute is used to define aliases for the cache container name.
This element has the following child elements: <transport>, <local-cache>, <invalidation-cache>,
<replicated-cache>, and <distributed-cache>.
WildFly 9
<transport>
This element is used to configure the JGroups transport used by the cache container, when required.
stack This attribute configures the JGroups stack to be used for the transport. If none is specified,
the default-stack for the JGroups subsystem is used.
cluster This attribute configures the name of the group communication cluster. This is the name
which will be seen in debugging logs.
executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle ? <fill me in >?.
lock-timeout This attribute configures the time-out to be used when obtaining locks for the
transport.
site This attribute configures the site id of the cache container.
rack This attribute configures the rack id of the cache container.
machine This attribute configures the machine id of the cache container.
The presence of the transport element is required when operating in clustered mode
These cache-related elements are actually part of an xsd hierarchy with abstract complexTypes
cache, clustered-cache, and shared-cache. In order to simplify the presentation, we notate these
as pseudo-elements <abstract cache>, <abstract clustered-cache> and <abstract
shared-cache>. In what follows, we first describe the extension hierarchy of base elements, and
then show how the cache type elements relate to them.
<abstract cache>
This abstract base element defines the attributes and child elements common to all non-clustered caches.
name This attribute configures the name of the cache. This name may be referenced by other
subsystems.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
batching This attribute configures batching. If enabled, the invocation batching API will be made
available for this cache.
indexing This attribute configures indexing. If enabled, entries will be indexed when they are added
to the cache. Indexes will be updated as entries change or are removed.
jndi-name This attribute is used to assign a name for the cache in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
WildFly 9
The <abstract cache> abstract base element has the following child elements: <indexing-properties>,
<locking>, <transaction>, <eviction>, <expiration>, <store>, <file-store>, <string-keyed-jdbc-store>,
<binary-keyed-jdbc-store>, <mixed-keyed-jdbc-store>, <remote-store>.
<indexing-properties>
This child element defines properties to control indexing behaviour.
<locking>
This child element configures the locking behaviour of the cache.
isolation This attribute the cache locking isolation level. Allowable values are NONE,
SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED.
striping If true, a pool of shared locks is maintained for all entries that need to be locked.
Otherwise, a lock is created per entry in the cache. Lock striping helps control memory footprint but
may reduce concurrency in the system.
acquire-timeout This attribute configures the maximum time to attempt a particular lock
acquisition.
concurrency-level This attribute is used to configure the concurrency level. Adjust this value
according to the number of concurrent threads interacting with Infinispan.
<transaction>
This child element configures the transactional behaviour of the cache.
mode This attribute configures the transaction mode, setting the cache transaction mode to one of
NONE, NON_XA, NON_DURABLE_XA, FULL_XA.
stop-timeout If there are any ongoing transactions when a cache is stopped, Infinispan waits for
ongoing remote and local transactions to finish. The amount of time to wait for is defined by the cache
stop timeout.
locking This attribute configures the locking mode for this cache, one of OPTIMISTIC or
PESSIMISTIC.
<eviction>
This child element configures the eviction behaviour of the cache.
strategy This attribute configures the cache eviction strategy. Available options are 'UNORDERED',
'FIFO', 'LRU', 'LIRS' and 'NONE' (to disable eviction).
max-entries This attribute configures the maximum number of entries in a cache instance. If
selected value is not a power of two the actual value will default to the least power of two larger than
selected value. -1 means no limit.
WildFly 9
<expiration>
This child element configures the expiration behaviour of the cache.
max-idle This attribute configures the maximum idle time a cache entry will be maintained in the
cache, in milliseconds. If the idle time is exceeded, the entry will be expired cluster-wide. -1 means
the entries never expire.
lifespan This attribute configures the maximum lifespan of a cache entry, after which the entry is
expired cluster-wide, in milliseconds. -1 means the entries never expire.
interval This attribute specifies the interval (in ms) between subsequent runs to purge expired
entries from memory and any cache stores. If you wish to disable the periodic eviction process
altogether, set wakeupInterval to -1.
The remaining child elements of the abstract base element <cache>, namely <store>, <file-store>,
<remote-store>, <string-keyed-jdbc-store>, <binary-keyed-jdbc-store> and <mixed-keyed-jdbc-store>,
each configures one of six key cache store types.
These cache store-related elements are actually part of an xsd extension hierarchy with abstract
complexTypes base-store and base-jdbc-store. As before, in order to simplify the presentation,
we notate these as pseudo-elements <abstract base-store> and <abstract base-jdbc-store>. In
what follows, we first describe the extension hierarchy of base elements, and then show how the
cache store elements relate to them.
WildFly 9
<abstract base-store>
This abstract base element defines the attributes and child elements common to all cache stores.
shared This attribute should be set to true when multiple cache instances share the same cache
store (e.g. multiple nodes in a cluster using a JDBC-based CacheStore pointing to the same, shared
database) Setting this to true avoids multiple cache instances writing the same modification multiple
times. If enabled, only the node where the modification originated will write to the cache store. If
disabled, each individual cache reacts to a potential remote update by storing the data to the cache
store.
preload This attribute configures whether or not, when the cache starts, data stored in the cache
loader will be pre-loaded into memory. This is particularly useful when data in the cache loader is
needed immediately after start-up and you want to avoid cache operations being delayed as a result
of loading this data lazily. Can be used to provide a 'warm-cache' on start-up, however there is a
performance penalty as start-up time is affected by this process. Note that pre-loading is done in a
local fashion, so any data loaded is only stored locally in the node. No replication or distribution of the
preloaded data happens. Also, Infinispan only pre-loads up to the maximum configured number of
entries in eviction.
passivation If true, data is only written to the cache store when it is evicted from memory, a
phenomenon known as passivation. Next time the data is requested, it will be 'activated' which means
that data will be brought back to memory and removed from the persistent store. If false, the cache
store contains a copy of the cache contents in memory, so writes to cache result in cache store
writes. This essentially gives you a 'write-through' configuration.
fetch-state This attribute, if true, causes persistent state to be fetched when joining a cluster. If
multiple cache stores are chained, only one of them can have this property enabled.
purge This attribute configures whether the cache store is purged upon start-up.
singleton This attribute configures whether or not the singleton store cache store is enabled.
SingletonStore is a delegating cache store used for situations when only one instance in a cluster
should interact with the underlying store.
class This attribute configures a custom store implementation class to use for this cache store.
properties This attribute is used to configure a list of cache store properties.
The abstract base element has one child element: <write-behind>
<write-behind>
This element is used to configure a cache store as write-behind instead of write-through. In write-through
mode, writes to the cache are also synchronously written to the cache store, whereas in write-behind mode,
writes to the cache are followed by asynchronous writes to the cache store.
flush-lock-timeout This attribute configures the time-out for acquiring the lock which guards the
state to be flushed to the cache store periodically.
modification-queue-size This attribute configures the maximum number of entries in the
asynchronous queue. When the queue is full, the store becomes write-through until it can accept new
entries.
shutdown-timeout This attribute configures the time-out (in ms) to stop the cache store.
thread-pool This attribute is used to configure the size of the thread pool whose threads are
responsible for applying the modifications to the cache store.
WildFly 9
<abstract base-jdbc-store> extends <abstract base-store>
This abstract base element defines the attributes and child elements common to all JDBC-based cache
stores.
datasource This attribute configures the datasource for the JDBC-based cache store.
entry-table This attribute configures the database table used to store cache entries.
bucket-table This attribute configures the database table used to store binary cache entries.
<file-store> extends <abstract base-store>
This child element is used to configure a file-based cache store. This requires specifying the name of the file
to be used as backing storage for the cache store.
relative-to This attribute optionally configures a relative path prefix for the file store path. Can be
null.
path This attribute configures an absolute path to a file if relative-to is null; configures a relative path
to the file, in relation to the value for relative-to, otherwise.
<remote-store> extends <abstract base-store>
This child element of cache is used to configure a remote cache store. It has a child <remote-servers>.
cache This attribute configures the name of the remote cache to use for this remote store.
tcp-nodelay This attribute configures a TCP_NODELAY value for communication with the remote
cache.
socket-timeout This attribute configures a socket time-out for communication with the remote
cache.
<remote-servers>
This child element of cache configures a list of remote servers for this cache store.
<remote-server>
This element configures a remote server. A remote server is defined completely by a locally defined
outbound socket binding, through which communication is made with the server.
outbound-socket-binding This attribute configures an outbound socket binding for a remote
server.
WildFly 9
WildFly 9
WildFly 9
Use Cases
In many cases, cache containers and caches will be configured via XML as in the example above, so that
they will be available upon server start-up. However, cache containers and caches may also be added,
removed or have their configurations changed in a running server by making use of the Wildfly management
API command-line interface (CLI). In this section, we present some key use cases for the Infinispan
management API.
The key use cases covered are:
adding a cache container
adding a cache to an existing cache container
configuring the transaction subsystem of a cache
The Wildfly management API command-line interface (CLI) can be used to provide
extensive information on the attributes and commands available in the Infinispan subsystem
interface used in these examples.
Add a cache
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache:add()
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache/transaction=TRANSACTION:add(mode=<t
WildFly 9
mod_cluster Subsystem
The mod_cluster integration is done via the modcluster subsystem it requires mod_cluster-1.1.x.or
mod_cluster-1.2.x (since 7.1.0)
The modcluster subsystem supports several operations:
WildFly 9
The operations specific to the modcluster subsystem are divided in 3 categories the ones that affects the
configuration and require a restart of the subsystem, the one that just modify the behaviour temporarily and
the ones that display information from the httpd part.
WildFly 9
read-proxies-configuration
Send a DUMP message to all Apache httpd the node is connected to and display the message received
from Apache httpd.
WildFly 9
read-proxies-info
Send a INFO message to all Apache httpd the node is connected to and display the message received from
Apache httpd.
WildFly 9
list-proxies:
Displays the httpd that are connected to the node. The httpd could be discovered via the Advertise protocol
or via the proxy-list attribute.
remove-proxy
Remove a proxy from the discovered proxies or temporarily from the proxy-list attribute.
proxy
Add a proxy to the discovered proxies or temporarily to the proxy-list attribute.
WildFly 9
enable-context
Tell Apache httpd that the context is ready receive requests.
disable-context
Tell Apache httpd that it shouldn't send new session requests to the context of the virtualhost.
stop-context
Tell Apache httpd that it shouldn't send requests to the context of the virtualhost.
refresh
Refresh the node by sending a new CONFIG message to Apache httpd.
reset
reset the connection between Apache httpd and the node
Configuration
Metric configuration
There are 4 metric operations corresponding to add and remove load metrics to the dynamic-load-provider.
Note that when nothing is defined a simple-load-provider is use with a fixed load factor of one.
WildFly 9
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<simple-load-provider factor="1"/>
</mod-cluster-config>
</subsystem>
metric
Add a metric to the dynamic-load-provider, the dynamic-load-provider in configuration is created if needed.
remove-metric
Remove a metric from the dynamic-load-provider.
WildFly 9
custom-metric / remove-custom-metric
like the add-metric and remove-metric except they require a class parameter instead the type. Usually they
needed additional properties which can be specified
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<dynamic-load-provider history="9" decay="2">
<custom-load-metric class="myclass">
<property name="pro1" value="value1"/>
<property name="pro2" value="value2"/>
</custom-load-metric>
</dynamic-load-provider>
</mod-cluster-config>
</subsystem>
JVMRoute configuration
If you want to use your own JVM route instead of automatically generated one you can insert the following
property:
...
</extensions>
<system-properties>
<property name="jboss.mod_cluster.jvmRoute" value="myJvmRoute"/>
</system-properties>
<management>
...
JGroups Subsystem
WildFly 9
Purpose
The JGroups subsystem provides group communication support for HA services in the form of JGroups
channels.
Named channel instances permit application peers in a cluster to communicate as a group and in such a
way that the communication satisfies defined properties (e.g. reliable, ordered, failure-sensitive).
Communication properties are configurable for each channel and are defined by the protocol stack used to
create the channel. Protocol stacks consist of a base transport layer (used to transport messages around the
cluster) together with a user-defined, ordered stack of protocol layers, where each protocol layer supports a
given communication property.
The JGroups subsystem provides the following features:
allows definition of named protocol stacks
view run-time metrics associated with channels
specify a default stack for general use
In the following sections, we describe the JGroups subsystem.
JGroups channels are created transparently as part of the clustering functionality (e.g. on clustered
application deployment, channels will be created behind the scenes to support clustered features
such as session replication or transmission of SSO contexts around the cluster).
Configuration example
What follows is a sample JGroups subsystem configuration showing all of the possible elements and
attributes which may be configured. We shall use this example to explain the meaning of the various
elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:jgroups:2.0" default-stack="udp">
<stack name="udp">
<transport type="UDP" socket-binding="jgroups-udp"
diagnostics-socket-binding="jgroups-diagnostics"
default-executor="jgroups" oob-executor="jgroups-oob" timer-executor="jgroups-timer"
shared="false" thread-factory="jgroups-thread-factory"
machine="machine1" rack="rack1" site="site1"/>
<protocol type="PING">
<property name="timeout">100</property>
</protocol>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<protocol type="MPING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="udp-xsite">
<transport type="UDP" socket-binding="jgroups-udp"/>
<protocol type="PING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
<relay site="LONDON">
<remote-site name="SFO" stack="tcp" cluster="global"/>
<remote-site name="NYC" stack="tcp" cluster="global"/>
</relay>
</stack>
</subsystem>
WildFly 9
<subsystem>
This element is used to configure the subsystem within a Wildfly system profile.
xmlns This attribute specifies the XML namespace of the JGroups subsystem and, in particular, its
version.
default-stack This attribute is used to specify a default stack for the JGroups subsystem. This
default stack will be used whenever a stack is required but no stack is specified.
<stack>
This element is used to configure a JGroups protocol stack.
name This attribute is used to specify the name of the stack.
WildFly 9
<transport>
This element is used to configure the transport layer (required) of the protocol stack.
type This attribute specifies the transport type (e.g. UDP, TCP, TCPGOSSIP)
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally.
diagnostics-socket-binding This attribute references a defined socket binding in the server
profile. It is used when JGroups needs to create sockets for use with the diagnostics program. For
more about the use of diagnostics, see the JGroups documentation for probe.sh.
default-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle incoming JGroups
messages.
oob-executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle incoming JGroups OOB
(out-of-bound) messages.
timer-executor This attribute references a defined thread pool executor in the threads subsystem.
It governs the allocation and execution of runnable timer-related tasks.
shared This attribute indicates whether or not this transport is shared amongst several JGroups
stacks or not.
thread-factory This attribute references a defined thread factory in the threads subsystem. It
governs the allocation of threads for running tasks which are not handled by the executors above.
site This attribute defines a site (data centre) id for this node.
rack This attribute defines a rack (server rack) id for this node.
machine This attribute defines a machine (host) is for this node.
site, rack and machine ids are used by the Infinispan topology-aware consistent hash function,
which when using dist mode, prevents dist mode replicas from being stored on the same host, rack
or site
<property>
This element is used to configure a transport property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
WildFly 9
<protocol>
This element is used to configure a (non-transport) protocol layer in the JGroups stack. Protocol layers are
ordered within the stack.
type This attribute specifies the name of the JGroups protocol implementation (e.g. MPING,
pbcast.GMS), with the package prefix org.jgroups.protocols removed.
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally for this protocol instance.
<property>
This element is used to configure a protocol property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
<relay>
This element is used to configure the RELAY protocol for a JGroups stack. RELAY is a protocol which
provides cross-site replication between defined sites (data centres). In the RELAY protocol, defined sites
specify the names of remote sites (backup sites) to which their data should be backed up. Channels are
defined between sites to permit the RELAY protocol to transport the data from the current site to a backup
site.
site This attribute specifies the name of the current site. Site names can be referenced elsewhere
(e.g. in the JGroups remote-site configuration elements, as well as backup configuration elements in
the Infinispan subsystem)
<remote-site>
This element is used to configure a remote site for the RELAY protocol.
name This attribute specifies the name of the remote site to which this configuration applies.
stack This attribute specifies a JGroups protocol stack to use for communication between this site
and the remote site.
cluster This attribute specifies the name of the JGroups channel to use for communication between
this site and the remote site.
WildFly 9
Use Cases
In many cases, channels will be configured via XML as in the example above, so that the channels will be
available upon server startup. However, channels may also be added, removed or have their configurations
changed in a running server by making use of the Wildfly management API command-line interface (CLI). In
this section, we present some key use cases for the JGroups management API.
The key use cases covered are:
adding a stack
adding a protocol to an existing stack
adding a property to a protocol
The Wildfly management API command-line interface (CLI) itself can be used to provide extensive
information on the attributes and commands available in the JGroups subsystem interface used in
these examples.
Add a stack
/subsystem=jgroups/stack=mystack:add(transport={}, protocols={})
/subsystem=jgroups/stack=mystack:add-protocol(type=<type>, socket-binding=<socketbinding>)
Infinispan Subsystem
WildFly 9
Purpose
The Infinispan subsystem provides caching support for HA services in the form of Infinispan caches:
high-performance, transactional caches which can operate in both non-distributed and distributed
scenarios. Distributed caching support is used in the provision of many key HA services. For example, the
failover of a session-oriented client HTTP request from a failing node to a new (failover) node depends on
session data for the client being available on the new node. In other words, the client session data needs to
be replicated across nodes in the cluster. This is effectively achieved via a distributed Infinispan cache. This
approach to providing fail-over also applies to EJB SFSB sessions. Over and above providing support for
fail-over, an underlying cache is also required when providing second-level caching for entity beans using
Hibernate, and this case is also handled through the use of an Infinispan cache.
The Infinispan subsystem provides the following features:
allows definition and configuration of named cache containers and caches
view run-time metrics associated with cache container and cache instances
In the following sections, we describe the Infinispan subsystem.
Infiispan cache containers and caches are created transparently as part of the clustering
functionality (e.g. on clustered application deployment, cache containers and their associated
caches will be created behind the scenes to support clustered features such as session replication
or caching of entities around the cluster).
Configuration Example
In this section, we provide an example XML configuration of the infinispan subsystem and review the
configuration elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:infinispan:2.0">
<cache-container name="server" aliases="singleton cluster" default-cache="default"
module="org.wildfly.clustering.server">
<transport lock-timeout="60000"/>
<replicated-cache name="default" mode="SYNC" batching="true">
<locking isolation="REPEATABLE_READ"/>
</replicated-cache>
</cache-container>
<cache-container name="web" aliases="standard-session-cache" default-cache="repl"
module="org.wildfly.clustering.web.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<file-store/>
</replicated-cache>
<replicated-cache name="sso" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="ejb" aliases="sfsb sfsb-cache" default-cache="repl"
module="org.jboss.as.clustering.ejb3.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</replicated-cache>
<!-~
Clustered cache used internally by EJB subsytem for managing the client-mapping(s) of
~
the socketbinding referenced by the EJB remoting connector
-->
<replicated-cache name="remote-connector-client-mappings" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="hibernate" default-cache="local-query" module="org.hibernate">
<transport lock-timeout="60000"/>
<local-cache name="local-query">
<transaction mode="NONE"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<invalidation-cache name="entity" mode="SYNC">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</invalidation-cache>
<replicated-cache name="timestamps" mode="ASYNC">
<transaction mode="NONE"/>
<eviction strategy="NONE"/>
</replicated-cache>
</cache-container>
</subsystem>
WildFly 9
<cache-container>
This element is used to configure a cache container.
name This attribute is used to specify the name of the cache container.
default-cache This attribute configures the default cache to be used, when no cache is otherwise
specified.
listener-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks in the replication queue.
eviction-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle evictions.
replication-queue-executor This attribute references a defined thread pool executor in the
threads subsystem. It governs the allocation and execution of runnable tasks to handle asynchronous
cache operations.
jndi-name This attribute is used to assign a name for the cache container in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
aliases This attribute is used to define aliases for the cache container name.
This element has the following child elements: <transport>, <local-cache>, <invalidation-cache>,
<replicated-cache>, and <distributed-cache>.
WildFly 9
<transport>
This element is used to configure the JGroups transport used by the cache container, when required.
stack This attribute configures the JGroups stack to be used for the transport. If none is specified,
the default-stack for the JGroups subsystem is used.
cluster This attribute configures the name of the group communication cluster. This is the name
which will be seen in debugging logs.
executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle ? <fill me in >?.
lock-timeout This attribute configures the time-out to be used when obtaining locks for the
transport.
site This attribute configures the site id of the cache container.
rack This attribute configures the rack id of the cache container.
machine This attribute configures the machine id of the cache container.
The presence of the transport element is required when operating in clustered mode
These cache-related elements are actually part of an xsd hierarchy with abstract complexTypes
cache, clustered-cache, and shared-cache. In order to simplify the presentation, we notate these
as pseudo-elements <abstract cache>, <abstract clustered-cache> and <abstract
shared-cache>. In what follows, we first describe the extension hierarchy of base elements, and
then show how the cache type elements relate to them.
<abstract cache>
This abstract base element defines the attributes and child elements common to all non-clustered caches.
name This attribute configures the name of the cache. This name may be referenced by other
subsystems.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
batching This attribute configures batching. If enabled, the invocation batching API will be made
available for this cache.
indexing This attribute configures indexing. If enabled, entries will be indexed when they are added
to the cache. Indexes will be updated as entries change or are removed.
jndi-name This attribute is used to assign a name for the cache in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
WildFly 9
The <abstract cache> abstract base element has the following child elements: <indexing-properties>,
<locking>, <transaction>, <eviction>, <expiration>, <store>, <file-store>, <string-keyed-jdbc-store>,
<binary-keyed-jdbc-store>, <mixed-keyed-jdbc-store>, <remote-store>.
<indexing-properties>
This child element defines properties to control indexing behaviour.
<locking>
This child element configures the locking behaviour of the cache.
isolation This attribute the cache locking isolation level. Allowable values are NONE,
SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED.
striping If true, a pool of shared locks is maintained for all entries that need to be locked.
Otherwise, a lock is created per entry in the cache. Lock striping helps control memory footprint but
may reduce concurrency in the system.
acquire-timeout This attribute configures the maximum time to attempt a particular lock
acquisition.
concurrency-level This attribute is used to configure the concurrency level. Adjust this value
according to the number of concurrent threads interacting with Infinispan.
<transaction>
This child element configures the transactional behaviour of the cache.
mode This attribute configures the transaction mode, setting the cache transaction mode to one of
NONE, NON_XA, NON_DURABLE_XA, FULL_XA.
stop-timeout If there are any ongoing transactions when a cache is stopped, Infinispan waits for
ongoing remote and local transactions to finish. The amount of time to wait for is defined by the cache
stop timeout.
locking This attribute configures the locking mode for this cache, one of OPTIMISTIC or
PESSIMISTIC.
<eviction>
This child element configures the eviction behaviour of the cache.
strategy This attribute configures the cache eviction strategy. Available options are 'UNORDERED',
'FIFO', 'LRU', 'LIRS' and 'NONE' (to disable eviction).
max-entries This attribute configures the maximum number of entries in a cache instance. If
selected value is not a power of two the actual value will default to the least power of two larger than
selected value. -1 means no limit.
WildFly 9
<expiration>
This child element configures the expiration behaviour of the cache.
max-idle This attribute configures the maximum idle time a cache entry will be maintained in the
cache, in milliseconds. If the idle time is exceeded, the entry will be expired cluster-wide. -1 means
the entries never expire.
lifespan This attribute configures the maximum lifespan of a cache entry, after which the entry is
expired cluster-wide, in milliseconds. -1 means the entries never expire.
interval This attribute specifies the interval (in ms) between subsequent runs to purge expired
entries from memory and any cache stores. If you wish to disable the periodic eviction process
altogether, set wakeupInterval to -1.
The remaining child elements of the abstract base element <cache>, namely <store>, <file-store>,
<remote-store>, <string-keyed-jdbc-store>, <binary-keyed-jdbc-store> and <mixed-keyed-jdbc-store>,
each configures one of six key cache store types.
These cache store-related elements are actually part of an xsd extension hierarchy with abstract
complexTypes base-store and base-jdbc-store. As before, in order to simplify the presentation,
we notate these as pseudo-elements <abstract base-store> and <abstract base-jdbc-store>. In
what follows, we first describe the extension hierarchy of base elements, and then show how the
cache store elements relate to them.
WildFly 9
<abstract base-store>
This abstract base element defines the attributes and child elements common to all cache stores.
shared This attribute should be set to true when multiple cache instances share the same cache
store (e.g. multiple nodes in a cluster using a JDBC-based CacheStore pointing to the same, shared
database) Setting this to true avoids multiple cache instances writing the same modification multiple
times. If enabled, only the node where the modification originated will write to the cache store. If
disabled, each individual cache reacts to a potential remote update by storing the data to the cache
store.
preload This attribute configures whether or not, when the cache starts, data stored in the cache
loader will be pre-loaded into memory. This is particularly useful when data in the cache loader is
needed immediately after start-up and you want to avoid cache operations being delayed as a result
of loading this data lazily. Can be used to provide a 'warm-cache' on start-up, however there is a
performance penalty as start-up time is affected by this process. Note that pre-loading is done in a
local fashion, so any data loaded is only stored locally in the node. No replication or distribution of the
preloaded data happens. Also, Infinispan only pre-loads up to the maximum configured number of
entries in eviction.
passivation If true, data is only written to the cache store when it is evicted from memory, a
phenomenon known as passivation. Next time the data is requested, it will be 'activated' which means
that data will be brought back to memory and removed from the persistent store. If false, the cache
store contains a copy of the cache contents in memory, so writes to cache result in cache store
writes. This essentially gives you a 'write-through' configuration.
fetch-state This attribute, if true, causes persistent state to be fetched when joining a cluster. If
multiple cache stores are chained, only one of them can have this property enabled.
purge This attribute configures whether the cache store is purged upon start-up.
singleton This attribute configures whether or not the singleton store cache store is enabled.
SingletonStore is a delegating cache store used for situations when only one instance in a cluster
should interact with the underlying store.
class This attribute configures a custom store implementation class to use for this cache store.
properties This attribute is used to configure a list of cache store properties.
The abstract base element has one child element: <write-behind>
<write-behind>
This element is used to configure a cache store as write-behind instead of write-through. In write-through
mode, writes to the cache are also synchronously written to the cache store, whereas in write-behind mode,
writes to the cache are followed by asynchronous writes to the cache store.
flush-lock-timeout This attribute configures the time-out for acquiring the lock which guards the
state to be flushed to the cache store periodically.
modification-queue-size This attribute configures the maximum number of entries in the
asynchronous queue. When the queue is full, the store becomes write-through until it can accept new
entries.
shutdown-timeout This attribute configures the time-out (in ms) to stop the cache store.
thread-pool This attribute is used to configure the size of the thread pool whose threads are
responsible for applying the modifications to the cache store.
WildFly 9
<abstract base-jdbc-store> extends <abstract base-store>
This abstract base element defines the attributes and child elements common to all JDBC-based cache
stores.
datasource This attribute configures the datasource for the JDBC-based cache store.
entry-table This attribute configures the database table used to store cache entries.
bucket-table This attribute configures the database table used to store binary cache entries.
<file-store> extends <abstract base-store>
This child element is used to configure a file-based cache store. This requires specifying the name of the file
to be used as backing storage for the cache store.
relative-to This attribute optionally configures a relative path prefix for the file store path. Can be
null.
path This attribute configures an absolute path to a file if relative-to is null; configures a relative path
to the file, in relation to the value for relative-to, otherwise.
<remote-store> extends <abstract base-store>
This child element of cache is used to configure a remote cache store. It has a child <remote-servers>.
cache This attribute configures the name of the remote cache to use for this remote store.
tcp-nodelay This attribute configures a TCP_NODELAY value for communication with the remote
cache.
socket-timeout This attribute configures a socket time-out for communication with the remote
cache.
<remote-servers>
This child element of cache configures a list of remote servers for this cache store.
<remote-server>
This element configures a remote server. A remote server is defined completely by a locally defined
outbound socket binding, through which communication is made with the server.
outbound-socket-binding This attribute configures an outbound socket binding for a remote
server.
WildFly 9
WildFly 9
WildFly 9
Use Cases
In many cases, cache containers and caches will be configured via XML as in the example above, so that
they will be available upon server start-up. However, cache containers and caches may also be added,
removed or have their configurations changed in a running server by making use of the Wildfly management
API command-line interface (CLI). In this section, we present some key use cases for the Infinispan
management API.
The key use cases covered are:
adding a cache container
adding a cache to an existing cache container
configuring the transaction subsystem of a cache
The Wildfly management API command-line interface (CLI) can be used to provide
extensive information on the attributes and commands available in the Infinispan subsystem
interface used in these examples.
Add a cache
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache:add()
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache/transaction=TRANSACTION:add(mode=<t
WildFly 9
JGroups Subsystem
Purpose
The JGroups subsystem provides group communication support for HA services in the form of JGroups
channels.
Named channel instances permit application peers in a cluster to communicate as a group and in such a
way that the communication satisfies defined properties (e.g. reliable, ordered, failure-sensitive).
Communication properties are configurable for each channel and are defined by the protocol stack used to
create the channel. Protocol stacks consist of a base transport layer (used to transport messages around the
cluster) together with a user-defined, ordered stack of protocol layers, where each protocol layer supports a
given communication property.
The JGroups subsystem provides the following features:
allows definition of named protocol stacks
view run-time metrics associated with channels
specify a default stack for general use
In the following sections, we describe the JGroups subsystem.
JGroups channels are created transparently as part of the clustering functionality (e.g. on clustered
application deployment, channels will be created behind the scenes to support clustered features
such as session replication or transmission of SSO contexts around the cluster).
Configuration example
What follows is a sample JGroups subsystem configuration showing all of the possible elements and
attributes which may be configured. We shall use this example to explain the meaning of the various
elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:jgroups:2.0" default-stack="udp">
<stack name="udp">
<transport type="UDP" socket-binding="jgroups-udp"
diagnostics-socket-binding="jgroups-diagnostics"
default-executor="jgroups" oob-executor="jgroups-oob" timer-executor="jgroups-timer"
shared="false" thread-factory="jgroups-thread-factory"
machine="machine1" rack="rack1" site="site1"/>
<protocol type="PING">
<property name="timeout">100</property>
</protocol>
<protocol type="MERGE3"/>
<protocol type="FD_SOCK" socket-binding="jgroups-udp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="UFC"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="tcp">
<transport type="TCP" socket-binding="jgroups-tcp"/>
<protocol type="MPING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
</stack>
<stack name="udp-xsite">
<transport type="UDP" socket-binding="jgroups-udp"/>
<protocol type="PING" socket-binding="jgroups-mping"/>
<protocol type="MERGE2"/>
<protocol type="FD_SOCK" socket-binding="jgroups-tcp-fd"/>
<protocol type="FD"/>
<protocol type="VERIFY_SUSPECT"/>
<protocol type="pbcast.NAKACK2"/>
<protocol type="UNICAST2"/>
<protocol type="pbcast.STABLE"/>
<protocol type="pbcast.GMS"/>
<protocol type="MFC"/>
<protocol type="FRAG2"/>
<protocol type="RSVP"/>
<relay site="LONDON">
<remote-site name="SFO" stack="tcp" cluster="global"/>
<remote-site name="NYC" stack="tcp" cluster="global"/>
</relay>
</stack>
</subsystem>
WildFly 9
<subsystem>
This element is used to configure the subsystem within a Wildfly system profile.
xmlns This attribute specifies the XML namespace of the JGroups subsystem and, in particular, its
version.
default-stack This attribute is used to specify a default stack for the JGroups subsystem. This
default stack will be used whenever a stack is required but no stack is specified.
<stack>
This element is used to configure a JGroups protocol stack.
name This attribute is used to specify the name of the stack.
WildFly 9
<transport>
This element is used to configure the transport layer (required) of the protocol stack.
type This attribute specifies the transport type (e.g. UDP, TCP, TCPGOSSIP)
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally.
diagnostics-socket-binding This attribute references a defined socket binding in the server
profile. It is used when JGroups needs to create sockets for use with the diagnostics program. For
more about the use of diagnostics, see the JGroups documentation for probe.sh.
default-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle incoming JGroups
messages.
oob-executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle incoming JGroups OOB
(out-of-bound) messages.
timer-executor This attribute references a defined thread pool executor in the threads subsystem.
It governs the allocation and execution of runnable timer-related tasks.
shared This attribute indicates whether or not this transport is shared amongst several JGroups
stacks or not.
thread-factory This attribute references a defined thread factory in the threads subsystem. It
governs the allocation of threads for running tasks which are not handled by the executors above.
site This attribute defines a site (data centre) id for this node.
rack This attribute defines a rack (server rack) id for this node.
machine This attribute defines a machine (host) is for this node.
site, rack and machine ids are used by the Infinispan topology-aware consistent hash function,
which when using dist mode, prevents dist mode replicas from being stored on the same host, rack
or site
.
<property>
This element is used to configure a transport property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
WildFly 9
<protocol>
This element is used to configure a (non-transport) protocol layer in the JGroups stack. Protocol layers are
ordered within the stack.
type This attribute specifies the name of the JGroups protocol implementation (e.g. MPING,
pbcast.GMS), with the package prefix org.jgroups.protocols removed.
socket-binding This attribute references a defined socket binding in the server profile. It is used
when JGroups needs to create general sockets internally for this protocol instance.
<property>
This element is used to configure a protocol property.
name This attribute specifies the name of the protocol property. The value is provided as text for the
property element.
<relay>
This element is used to configure the RELAY protocol for a JGroups stack. RELAY is a protocol which
provides cross-site replication between defined sites (data centres). In the RELAY protocol, defined sites
specify the names of remote sites (backup sites) to which their data should be backed up. Channels are
defined between sites to permit the RELAY protocol to transport the data from the current site to a backup
site.
site This attribute specifies the name of the current site. Site names can be referenced elsewhere
(e.g. in the JGroups remote-site configuration elements, as well as backup configuration elements in
the Infinispan subsystem)
<remote-site>
This element is used to configure a remote site for the RELAY protocol.
name This attribute specifies the name of the remote site to which this configuration applies.
stack This attribute specifies a JGroups protocol stack to use for communication between this site
and the remote site.
cluster This attribute specifies the name of the JGroups channel to use for communication between
this site and the remote site.
WildFly 9
Use Cases
In many cases, channels will be configured via XML as in the example above, so that the channels will be
available upon server startup. However, channels may also be added, removed or have their configurations
changed in a running server by making use of the Wildfly management API command-line interface (CLI). In
this section, we present some key use cases for the JGroups management API.
The key use cases covered are:
adding a stack
adding a protocol to an existing stack
adding a property to a protocol
The Wildfly management API command-line interface (CLI) itself can be used to provide extensive
information on the attributes and commands available in the JGroups subsystem interface used in
these examples.
Add a stack
/subsystem=jgroups/stack=mystack:add(transport={}, protocols={})
/subsystem=jgroups/stack=mystack:add-protocol(type=<type>, socket-binding=<socketbinding>)
WildFly 9
Infinispan Subsystem
Purpose
The Infinispan subsystem provides caching support for HA services in the form of Infinispan caches:
high-performance, transactional caches which can operate in both non-distributed and distributed
scenarios. Distributed caching support is used in the provision of many key HA services. For example, the
failover of a session-oriented client HTTP request from a failing node to a new (failover) node depends on
session data for the client being available on the new node. In other words, the client session data needs to
be replicated across nodes in the cluster. This is effectively achieved via a distributed Infinispan cache. This
approach to providing fail-over also applies to EJB SFSB sessions. Over and above providing support for
fail-over, an underlying cache is also required when providing second-level caching for entity beans using
Hibernate, and this case is also handled through the use of an Infinispan cache.
The Infinispan subsystem provides the following features:
allows definition and configuration of named cache containers and caches
view run-time metrics associated with cache container and cache instances
In the following sections, we describe the Infinispan subsystem.
Infiispan cache containers and caches are created transparently as part of the clustering
functionality (e.g. on clustered application deployment, cache containers and their associated
caches will be created behind the scenes to support clustered features such as session replication
or caching of entities around the cluster).
Configuration Example
In this section, we provide an example XML configuration of the infinispan subsystem and review the
configuration elements and attributes.
The schema for the subsystem, describing all valid elements and attributes, can be found in the
Wildfly distribution, in the docs/schema directory.
WildFly 9
<subsystem xmlns="urn:jboss:domain:infinispan:2.0">
<cache-container name="server" aliases="singleton cluster" default-cache="default"
module="org.wildfly.clustering.server">
<transport lock-timeout="60000"/>
<replicated-cache name="default" mode="SYNC" batching="true">
<locking isolation="REPEATABLE_READ"/>
</replicated-cache>
</cache-container>
<cache-container name="web" aliases="standard-session-cache" default-cache="repl"
module="org.wildfly.clustering.web.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<file-store/>
</replicated-cache>
<replicated-cache name="sso" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="ejb" aliases="sfsb sfsb-cache" default-cache="repl"
module="org.jboss.as.clustering.ejb3.infinispan">
<transport lock-timeout="60000"/>
<replicated-cache name="repl" mode="ASYNC" batching="true">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</replicated-cache>
<!-~ Clustered cache used internally by EJB subsytem for managing the client-mapping(s) of
~
the socketbinding referenced by the EJB remoting connector
-->
<replicated-cache name="remote-connector-client-mappings" mode="SYNC" batching="true"/>
<distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
<eviction strategy="LRU" max-entries="10000"/>
<file-store/>
</distributed-cache>
</cache-container>
<cache-container name="hibernate" default-cache="local-query" module="org.hibernate">
<transport lock-timeout="60000"/>
<local-cache name="local-query">
<transaction mode="NONE"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</local-cache>
<invalidation-cache name="entity" mode="SYNC">
<transaction mode="NON_XA"/>
<eviction strategy="LRU" max-entries="10000"/>
<expiration max-idle="100000"/>
</invalidation-cache>
<replicated-cache name="timestamps" mode="ASYNC">
<transaction mode="NONE"/>
<eviction strategy="NONE"/>
</replicated-cache>
</cache-container>
</subsystem>
WildFly 9
<cache-container>
This element is used to configure a cache container.
name This attribute is used to specify the name of the cache container.
default-cache This attribute configures the default cache to be used, when no cache is otherwise
specified.
listener-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks in the replication queue.
eviction-executor This attribute references a defined thread pool executor in the threads
subsystem. It governs the allocation and execution of runnable tasks to handle evictions.
replication-queue-executor This attribute references a defined thread pool executor in the
threads subsystem. It governs the allocation and execution of runnable tasks to handle asynchronous
cache operations.
jndi-name This attribute is used to assign a name for the cache container in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
aliases This attribute is used to define aliases for the cache container name.
This element has the following child elements: <transport>, <local-cache>, <invalidation-cache>,
<replicated-cache>, and <distributed-cache>.
WildFly 9
<transport>
This element is used to configure the JGroups transport used by the cache container, when required.
stack This attribute configures the JGroups stack to be used for the transport. If none is specified,
the default-stack for the JGroups subsystem is used.
cluster This attribute configures the name of the group communication cluster. This is the name
which will be seen in debugging logs.
executor This attribute references a defined thread pool executor in the threads subsystem. It
governs the allocation and execution of runnable tasks to handle ? <fill me in >?.
lock-timeout This attribute configures the time-out to be used when obtaining locks for the
transport.
site This attribute configures the site id of the cache container.
rack This attribute configures the rack id of the cache container.
machine This attribute configures the machine id of the cache container.
The presence of the transport element is required when operating in clustered mode
These cache-related elements are actually part of an xsd hierarchy with abstract complexTypes
cache, clustered-cache, and shared-cache. In order to simplify the presentation, we notate these
as pseudo-elements <abstract cache>, <abstract clustered-cache> and <abstract
shared-cache>. In what follows, we first describe the extension hierarchy of base elements, and
then show how the cache type elements relate to them.
<abstract cache>
This abstract base element defines the attributes and child elements common to all non-clustered caches.
name This attribute configures the name of the cache. This name may be referenced by other
subsystems.
start This attribute configured the cache container start mode and has since been deprecated, the
only supported and the default value is LAZY (on-demand start).
batching This attribute configures batching. If enabled, the invocation batching API will be made
available for this cache.
indexing This attribute configures indexing. If enabled, entries will be indexed when they are added
to the cache. Indexes will be updated as entries change or are removed.
jndi-name This attribute is used to assign a name for the cache in the JNDI name service.
module This attribute configures the module whose class loader should be used when building this
cache container's configuration.
WildFly 9
The <abstract cache> abstract base element has the following child elements: <indexing-properties>,
<locking>, <transaction>, <eviction>, <expiration>, <store>, <file-store>, <string-keyed-jdbc-store>,
<binary-keyed-jdbc-store>, <mixed-keyed-jdbc-store>, <remote-store>.
<indexing-properties>
This child element defines properties to control indexing behaviour.
<locking>
This child element configures the locking behaviour of the cache.
isolation This attribute the cache locking isolation level. Allowable values are NONE,
SERIALIZABLE, REPEATABLE_READ, READ_COMMITTED, READ_UNCOMMITTED.
striping If true, a pool of shared locks is maintained for all entries that need to be locked.
Otherwise, a lock is created per entry in the cache. Lock striping helps control memory footprint but
may reduce concurrency in the system.
acquire-timeout This attribute configures the maximum time to attempt a particular lock
acquisition.
concurrency-level This attribute is used to configure the concurrency level. Adjust this value
according to the number of concurrent threads interacting with Infinispan.
<transaction>
This child element configures the transactional behaviour of the cache.
mode This attribute configures the transaction mode, setting the cache transaction mode to one of
NONE, NON_XA, NON_DURABLE_XA, FULL_XA.
stop-timeout If there are any ongoing transactions when a cache is stopped, Infinispan waits for
ongoing remote and local transactions to finish. The amount of time to wait for is defined by the cache
stop timeout.
locking This attribute configures the locking mode for this cache, one of OPTIMISTIC or
PESSIMISTIC.
<eviction>
This child element configures the eviction behaviour of the cache.
strategy This attribute configures the cache eviction strategy. Available options are 'UNORDERED',
'FIFO', 'LRU', 'LIRS' and 'NONE' (to disable eviction).
max-entries This attribute configures the maximum number of entries in a cache instance. If
selected value is not a power of two the actual value will default to the least power of two larger than
selected value. -1 means no limit.
WildFly 9
<expiration>
This child element configures the expiration behaviour of the cache.
max-idle This attribute configures the maximum idle time a cache entry will be maintained in the
cache, in milliseconds. If the idle time is exceeded, the entry will be expired cluster-wide. -1 means
the entries never expire.
lifespan This attribute configures the maximum lifespan of a cache entry, after which the entry is
expired cluster-wide, in milliseconds. -1 means the entries never expire.
interval This attribute specifies the interval (in ms) between subsequent runs to purge expired
entries from memory and any cache stores. If you wish to disable the periodic eviction process
altogether, set wakeupInterval to -1.
The remaining child elements of the abstract base element <cache>, namely <store>, <file-store>,
<remote-store>, <string-keyed-jdbc-store>, <binary-keyed-jdbc-store> and <mixed-keyed-jdbc-store>,
each configures one of six key cache store types.
These cache store-related elements are actually part of an xsd extension hierarchy with abstract
complexTypes base-store and base-jdbc-store. As before, in order to simplify the presentation,
we notate these as pseudo-elements <abstract base-store> and <abstract base-jdbc-store>. In
what follows, we first describe the extension hierarchy of base elements, and then show how the
cache store elements relate to them.
WildFly 9
<abstract base-store>
This abstract base element defines the attributes and child elements common to all cache stores.
shared This attribute should be set to true when multiple cache instances share the same cache
store (e.g. multiple nodes in a cluster using a JDBC-based CacheStore pointing to the same, shared
database) Setting this to true avoids multiple cache instances writing the same modification multiple
times. If enabled, only the node where the modification originated will write to the cache store. If
disabled, each individual cache reacts to a potential remote update by storing the data to the cache
store.
preload This attribute configures whether or not, when the cache starts, data stored in the cache
loader will be pre-loaded into memory. This is particularly useful when data in the cache loader is
needed immediately after start-up and you want to avoid cache operations being delayed as a result
of loading this data lazily. Can be used to provide a 'warm-cache' on start-up, however there is a
performance penalty as start-up time is affected by this process. Note that pre-loading is done in a
local fashion, so any data loaded is only stored locally in the node. No replication or distribution of the
preloaded data happens. Also, Infinispan only pre-loads up to the maximum configured number of
entries in eviction.
passivation If true, data is only written to the cache store when it is evicted from memory, a
phenomenon known as passivation. Next time the data is requested, it will be 'activated' which means
that data will be brought back to memory and removed from the persistent store. If false, the cache
store contains a copy of the cache contents in memory, so writes to cache result in cache store
writes. This essentially gives you a 'write-through' configuration.
fetch-state This attribute, if true, causes persistent state to be fetched when joining a cluster. If
multiple cache stores are chained, only one of them can have this property enabled.
purge This attribute configures whether the cache store is purged upon start-up.
singleton This attribute configures whether or not the singleton store cache store is enabled.
SingletonStore is a delegating cache store used for situations when only one instance in a cluster
should interact with the underlying store.
class This attribute configures a custom store implementation class to use for this cache store.
properties This attribute is used to configure a list of cache store properties.
The abstract base element has one child element: <write-behind>
<write-behind>
This element is used to configure a cache store as write-behind instead of write-through. In write-through
mode, writes to the cache are also synchronously written to the cache store, whereas in write-behind mode,
writes to the cache are followed by asynchronous writes to the cache store.
flush-lock-timeout This attribute configures the time-out for acquiring the lock which guards the
state to be flushed to the cache store periodically.
modification-queue-size This attribute configures the maximum number of entries in the
asynchronous queue. When the queue is full, the store becomes write-through until it can accept new
entries.
shutdown-timeout This attribute configures the time-out (in ms) to stop the cache store.
thread-pool This attribute is used to configure the size of the thread pool whose threads are
responsible for applying the modifications to the cache store.
WildFly 9
<abstract base-jdbc-store> extends <abstract base-store>
This abstract base element defines the attributes and child elements common to all JDBC-based cache
stores.
datasource This attribute configures the datasource for the JDBC-based cache store.
entry-table This attribute configures the database table used to store cache entries.
bucket-table This attribute configures the database table used to store binary cache entries.
<file-store> extends <abstract base-store>
This child element is used to configure a file-based cache store. This requires specifying the name of the file
to be used as backing storage for the cache store.
relative-to This attribute optionally configures a relative path prefix for the file store path. Can be
null.
path This attribute configures an absolute path to a file if relative-to is null; configures a relative path
to the file, in relation to the value for relative-to, otherwise.
<remote-store> extends <abstract base-store>
This child element of cache is used to configure a remote cache store. It has a child <remote-servers>.
cache This attribute configures the name of the remote cache to use for this remote store.
tcp-nodelay This attribute configures a TCP_NODELAY value for communication with the remote
cache.
socket-timeout This attribute configures a socket time-out for communication with the remote
cache.
<remote-servers>
This child element of cache configures a list of remote servers for this cache store.
<remote-server>
This element configures a remote server. A remote server is defined completely by a locally defined
outbound socket binding, through which communication is made with the server.
outbound-socket-binding This attribute configures an outbound socket binding for a remote
server.
<local-cache> extends <abstract cache>
This element configures a local cache.
WildFly 9
<abstract clustered-cache> extends <abstract cache>
This abstract base element defines the attributes and child elements common to all clustered caches. A
clustered cache is a cache which spans multiple nodes in a cluster. It inherits from <cache>, so that all
attributes and elements of <cache> are also defined for <clustered-cache>.
async-marshalling This attribute configures async marshalling. If enabled, this will cause
marshalling of entries to be performed asynchronously.
mode This attribute configures the clustered cache mode, ASYNC for asynchronous operation, or
SYNC for synchronous operation.
queue-size In ASYNC mode, this attribute can be used to trigger flushing of the queue when it
reaches a specific threshold.
queue-flush-interval In ASYNC mode, this attribute controls how often the asynchronous
thread used to flush the replication queue runs. This should be a positive integer which represents
thread wakeup time in milliseconds.
remote-timeout In SYNC mode, this attribute (in ms) used to wait for an acknowledgement when
making a remote call, after which the call is aborted and an exception is thrown.
<invalidation-cache> extends <abstract clustered-cache>
This element configures an invalidation cache.
WildFly 9
<abstract shared-cache> extends <abstract clustered-cache>
This abstract base element defines the attributes and child elements common to all shared caches. A shared
cache is a clustered cache which shares state with its cache peers in the cluster. It inherits from
<clustered-cache>, so that all attributes and elements of <clustered-cache> are also defined for
<shared-cache>.
<state-transfer>
enabled If enabled, this will cause the cache to ask neighbouring caches for state when it starts up,
so the cache starts 'warm', although it will impact start-up time.
timeout This attribute configures the maximum amount of time (ms) to wait for state from
neighbouring caches, before throwing an exception and aborting start-up.
chunk-size This attribute configures the size, in bytes, in which to batch the transfer of cache
entries.
<backups>
<backup>
strategy This attribute configures the backup strategy for this cache. Allowable values are SYNC,
ASYNC.
failure-policy This attribute configures the policy to follow when connectivity to the backup site
fails. Allowable values are IGNORE, WARN, FAIL, CUSTOM.
enabled This attribute configures whether or not this backup is enabled. If enabled, data will be sent
to the backup site; otherwise, the backup site will be effectively ignored.
timeout This attribute configures the time-out for replicating to the backup site.
after-failures This attribute configures the number of failures after which this backup site should
go off-line.
min-wait This attribute configures the minimum time (in milliseconds) to wait after the max number
of failures is reached, after which this backup site should go off-line.
<backup-for>
remote-cache This attribute configures the name of the remote cache for which this cache acts as a
backup.
remote-site This attribute configures the site of the remote cache for which this cache acts as a
backup.
<replicated-cache> extends <abstract shared-cache>
This element configures a replicated cache. With a replicated cache, all contents (key-value pairs) of the
cache are replicated on all nodes in the cluster.
WildFly 9
<distributed-cache> extends <abstract shared-cache>
This element configures a distributed cache. With a distributed cache, contents of the cache are selectively
replicated on nodes in the cluster, according to the number of owners specified.
owners This attribute configures the number of cluster-wide replicas for each cache entry.
segments This attribute configures the number of hash space segments which is the granularity for
key distribution in the cluster. Value must be strictly positive.
l1-lifespan This attribute configures the maximum lifespan of an entry placed in the L1 cache.
Configures the L1 cache behaviour in 'distributed' caches instances. In any other cache modes, this
element is ignored.
Use Cases
In many cases, cache containers and caches will be configured via XML as in the example above, so that
they will be available upon server start-up. However, cache containers and caches may also be added,
removed or have their configurations changed in a running server by making use of the Wildfly management
API command-line interface (CLI). In this section, we present some key use cases for the Infinispan
management API.
The key use cases covered are:
adding a cache container
adding a cache to an existing cache container
configuring the transaction subsystem of a cache
The Wildfly management API command-line interface (CLI) can be used to provide
extensive information on the attributes and commands available in the Infinispan subsystem
interface used in these examples.
Add a cache
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache:add()
/subsystem=infinispan/cache-container=mycontainer/local-cache=mylocalcache/transaction=TRANSACTION:add(mode=<t
WildFly 9
mod_cluster Subsystem
The mod_cluster integration is done via the modcluster subsystem it requires mod_cluster-1.1.x.or
mod_cluster-1.2.x (since 7.1.0)
The modcluster subsystem supports several operations:
WildFly 9
The operations specific to the modcluster subsystem are divided in 3 categories the ones that affects the
configuration and require a restart of the subsystem, the one that just modify the behaviour temporarily and
the ones that display information from the httpd part.
WildFly 9
read-proxies-configuration
Send a DUMP message to all Apache httpd the node is connected to and display the message received
from Apache httpd.
WildFly 9
read-proxies-info
Send a INFO message to all Apache httpd the node is connected to and display the message received from
Apache httpd.
WildFly 9
remove-proxy
Remove a proxy from the discovered proxies or temporarily from the proxy-list attribute.
proxy
Add a proxy to the discovered proxies or temporarily to the proxy-list attribute.
WildFly 9
disable-context
Tell Apache httpd that it shouldn't send new session requests to the context of the virtualhost.
stop-context
Tell Apache httpd that it shouldn't send requests to the context of the virtualhost.
Configuration
Metric configuration
There are 4 metric operations corresponding to add and remove load metrics to the dynamic-load-provider.
Note that when nothing is defined a simple-load-provider is use with a fixed load factor of one.
WildFly 9
that corresponds to the following configuration:
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<simple-load-provider factor="1"/>
</mod-cluster-config>
</subsystem>
metric
Add a metric to the dynamic-load-provider, the dynamic-load-provider in configuration is created if needed.
remove-metric
Remove a metric from the dynamic-load-provider.
WildFly 9
custom-metric / remove-custom-metric
like the add-metric and remove-metric except they require a class parameter instead the type. Usually they
needed additional properties which can be specified
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<dynamic-load-provider history="9" decay="2">
<custom-load-metric class="myclass">
<property name="pro1" value="value1"/>
<property name="pro2" value="value2"/>
</custom-load-metric>
</dynamic-load-provider>
</mod-cluster-config>
</subsystem>
JVMRoute configuration
If you want to use your own JVM route instead of automatically generated one you can insert the following
property:
...
</extensions>
<system-properties>
<property name="jboss.mod_cluster.jvmRoute" value="myJvmRoute"/>
</system-properties>
<management>
...
WildFly 9
Apache httpd
The recommended front-end module is mod_cluster but mod_jk or mod_proxy could be used as in Tomcat
or other AS version.
To use AJP define a ajp connector in the web subsystem like:
<subsystem xmlns="urn:jboss:domain:web:1.0">
<connector name="http" protocol="HTTP/1.1" socket-binding="http"/>
<connector name="ajp" protocol="AJP/1.3" socket-binding="ajp"/>
To the ajp in the in the socket-binding-group like:
<socket-binding-group name="standard-sockets" default-interface="public">
....
<socket-binding name="http" port="8080"/>
<socket-binding name="ajp" port="8009"/>
<socket-binding name="https" port="8443"/>
mod_cluster Subsystem
The mod_cluster integration is done via the modcluster subsystem it requires mod_cluster-1.1.x.or
mod_cluster-1.2.x (since 7.1.0)
The modcluster subsystem supports several operations:
WildFly 9
The operations specific to the modcluster subsystem are divided in 3 categories the ones that affects the
configuration and require a restart of the subsystem, the one that just modify the behaviour temporarily and
the ones that display information from the httpd part.
WildFly 9
read-proxies-configuration
Send a DUMP message to all Apache httpd the node is connected to and display the message received
from Apache httpd.
WildFly 9
read-proxies-info
Send a INFO message to all Apache httpd the node is connected to and display the message received from
Apache httpd.
WildFly 9
list-proxies:
Displays the httpd that are connected to the node. The httpd could be discovered via the Advertise protocol
or via the proxy-list attribute.
remove-proxy
Remove a proxy from the discovered proxies or temporarily from the proxy-list attribute.
proxy
Add a proxy to the discovered proxies or temporarily to the proxy-list attribute.
WildFly 9
enable-context
Tell Apache httpd that the context is ready receive requests.
disable-context
Tell Apache httpd that it shouldn't send new session requests to the context of the virtualhost.
stop-context
Tell Apache httpd that it shouldn't send requests to the context of the virtualhost.
refresh
Refresh the node by sending a new CONFIG message to Apache httpd.
reset
reset the connection between Apache httpd and the node
Configuration
Metric configuration
There are 4 metric operations corresponding to add and remove load metrics to the dynamic-load-provider.
Note that when nothing is defined a simple-load-provider is use with a fixed load factor of one.
WildFly 9
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<simple-load-provider factor="1"/>
</mod-cluster-config>
</subsystem>
metric
Add a metric to the dynamic-load-provider, the dynamic-load-provider in configuration is created if needed.
remove-metric
Remove a metric from the dynamic-load-provider.
WildFly 9
custom-metric / remove-custom-metric
like the add-metric and remove-metric except they require a class parameter instead the type. Usually they
needed additional properties which can be specified
<subsystem xmlns="urn:jboss:domain:modcluster:1.0">
<mod-cluster-config>
<dynamic-load-provider history="9" decay="2">
<custom-load-metric class="myclass">
<property name="pro1" value="value1"/>
<property name="pro2" value="value2"/>
</custom-load-metric>
</dynamic-load-provider>
</mod-cluster-config>
</subsystem>
JVMRoute configuration
If you want to use your own JVM route instead of automatically generated one you can insert the following
property:
...
</extensions>
<system-properties>
<property name="jboss.mod_cluster.jvmRoute" value="myJvmRoute"/>
</system-properties>
<management>
...
WildFly 9
jboss-ejb3.xml
<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
xmlns:jee="http://java.sun.com/xml/ns/javaee"
xmlns:c="urn:clustering:1.0">
<jee:assembly-descriptor>
<c:clustering>
<jee:ejb-name>DDBasedClusteredBean</jee:ejb-name>
<c:clustered>true</c:clustered>
</c:clustering>
</jee:assembly-descriptor>
</jboss>
WildFly 9
./standalone.sh -server-config=standalone-ha.xml
This will start a single instance of the server with HA capabilities. Deploying the EJBs to this instance doesn't
involve anything special and is the same as explained in the application deployment chapter.
Obviously, to be able to see the benefits of clustering, you'll need more than one instance of the server. So
let's start another server with HA capabilities. That another instance of the server can either be on the same
machine or on some other machine. If it's on the same machine, the two things you have to make sure is
that you pass the port offset for the second instance and also make sure that each of the server instances
have a unique jboss.node.name system property. You can do that by passing the following two system
properties to the startup command:
Follow whichever approach you feel comfortable with for deploying the EJB deployment to this instance too.
Deploying the application on just one node of a standalone instance of a clustered server does not
mean that it will be automatically deployed to the other clustered instance. You will have to do
deploy it explicitly on the other standalone clustered instance too. Or you can start the servers in
domain mode so that the deployment can be deployed to all the server within a server group. See
the admin guide for more details on domain setup.
Now that you have deployed an application with clustered EJBs on both the instances, the EJBs are now
capable of making use of the clustering features.
WildFly 9
remote.clusters=ejb
remote.cluster.ejb.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.cluster.ejb.connect.options.org.xnio.Options.SSL_ENABLED=false
WildFly 9
WildFly 9
7.14 Hibernate
WildFly 9
7.15.2 Monitoring
Describe resources available for monitoring clustered applications.
WildFly 9
Scenario
Here are some details on what we are going to do:
Let's call one host as 'master', the other one as 'slave'.
Both master and slave will run WildFly 9, and master will run as domain controller, slave will under the
domain management of master.
Apache httpd will be run on master, and in httpd we will enable the mod_cluster module. The WildFly
9 on master and slave will form a cluster and discovered by httpd.
We will deploy a demo project into domain, and verify that the project is deployed into both master
and slave by domain controller. Thus we could see that domain management provide us a single
point to manage the deployments across multiple hosts in a single domain.
We will access the cluster URL and verify that httpd has distributed the request to one of the WildFly
host. So we could see the cluster is working properly.
We will try to make a request on cluster, and if the request is forwarded to master, we then kill the
WildFly process on master. After that we will go on requesting cluster and we should see the request
is forwarded to slave, but the session is not lost. Our goal is to verify the HA is working and sessions
are replicated.
After previous step finished, we reconnect the master by restarting it. We should see the master is
registered back into cluster, also we should see slave sees master as domain controller again and
connect to it.
WildFly 9
Please don't worry if you cannot digest so many details currently. Let's move on and you will get the points
step by step.
WildFly 9
http://wildfly.org/downloads/
wildfly-9.0.0.Final.zip
Note: The name of your archive will differ slightly due to version naming conventions.
Then I unzipped the package to master and try to make a test run:
unzip wildfly-9.0.0.Final.zip
cd wildfly-9.0.0.Final/bin
./domain.sh
wildfly-9.0.0.Final/bin$ ./domain.sh
=========================================================================
JBoss Bootstrap Environment
JBOSS_HOME: /Users/weli/Downloads/wildfly-9.0.0.Final
JAVA: /Library/Java/Home/bin/java
JAVA_OPTS: -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true
-Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000
-Dsun.rmi.dgc.server.gcInterval=3600000 -Djboss.modules.system.pkgs=org.jboss.byteman
-Djava.awt.headless=true
=========================================================================
...
[Server:server-two] 14:46:12,375 INFO
WildFly 9.0.0.Final "Kenny" started in 8860ms - Started 210 of 258 services (89 services are
lazy, passive or on-demand)
Now exit master and let's repeat the same steps on slave host. Finally we get WildFly 9 run on both master
and slave, then we could move on to next step.
WildFly 9
vi domain/configuration/host.xml
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
<interface name="unsecured">
<inet-address value="127.0.0.1" />
</interface>
</interfaces>
We need to change the address to the management interface so slave could connect to master. The public
interface allows the application to be accessed by non-local HTTP, and the unsecured interface allows
remote RMI access. My master's ip address is 10.211.55.7, so I change the config to:
<interfaces>
<interface name="management"
<inet-address value="${jboss.bind.address.management:10.211.55.7}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:10.211.55.7}"/>
</interface>
<interface name="unsecured">
<inet-address value="10.211.55.7" />
</interface>
</interfaces>
vi domain/configuration/host.xml
WildFly 9
The configuration we'll use on slave is a little bit different, because we need to let slave connect to master.
First we need to set the hostname. We change the name property from:
to:
Then we need to modify domain-controller section so slave can connect to master's management port:
<domain-controller>
<remote protocol="remote" host="10.211.55.7" port="9999" />
</domain-controller>
<domain-controller>
<remote security-realm="ManagementRealm" >
<discovery-options>
<static-discovery name="master-native" protocol="remote"
Finally, we also need to configure interfaces section and expose the management ports to public address:
<interfaces>
<interface name="management">
<inet-address value="${jboss.bind.address.management:10.211.55.2}"/>
</interface>
<interface name="public">
<inet-address value="${jboss.bind.address:10.211.55.2}"/>
</interface>
<interface name="unsecured">
<inet-address value="10.211.55.2" />
</interface>
</interfaces>
10.211.55.2 is the ip address of the slave. Refer to the domain controller configuration above for an
explanation of the management, public, and unsecured interfaces.
WildFly 9
It is easier to turn off all firewalls for testing, but in production, you need to enable the firewall and
allow access to the following ports: 9999.
Security Configuration
If you start WildFly on both master and slave now, you will see the slave cannot be started with following
error:
Because we haven't properly set up the authentication between master and slave. Now let's work on it:
Master
In bin directory there is a script called add-user.sh, we'll use it to add new users to the properties file used for
domain management authentication:
./add-user.sh
Enter the details of the new user to add.
Realm (ManagementRealm) :
Username : admin
Password recommendations are listed below. To modify these restrictions edit the
add-user.properties configuration file.
- The password should not be one of the following restricted values {root, admin,
administrator}
- The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1
non-alphanumeric symbol(s)
- The password should be different from the username
Password : passw0rd!
Re-enter Password : passw0rd!
The username 'admin' is easy to guess
Are you sure you want to add user 'admin' yes/no? yes
About to add user 'admin' for realm 'ManagementRealm'
Is this correct yes/no? yes
Added user 'admin' to file
'/home/weli/projs/wildfly-9.0.0.Final/standalone/configuration/mgmt-users.properties'
Added user 'admin' to file
'/home/weli/projs/wildfly-9.0.0.Final/domain/configuration/mgmt-users.properties'
WildFly 9
As shown above, we have created a user named 'admin' and its password is 'passw0rd!'. Then we add
another user called 'slave':
./add-user.sh
Enter the details of the new user to add.
Realm (ManagementRealm) :
Username : slave
Password recommendations are listed below. To modify these restrictions edit the
add-user.properties configuration file.
- The password should not be one of the following restricted values {root, admin,
administrator}
- The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1
non-alphanumeric symbol(s)
- The password should be different from the username
Password : passw0rd!
Re-enter Password : passw0rd!
What groups do you want this user to belong to? (Please enter a comma separated list, or leave
blank for none)[
]:
We will use this user for slave host to connect to master. The add-user.sh will let you choose the type of the
user. Here we need to choose 'Management User' type for both 'admin' and 'slave' account.
WildFly 9
Slave
In slave we need to configure host.xml for authentication. We should change the security-realms section as
following:
<security-realms>
<security-realm name="ManagementRealm">
<server-identities>
<secret value="cGFzc3cwcmQh" />
<!-- This is required for SSL remoting -->
<ssl>
<keystore path="server.keystore" relative-to="jboss.domain.config.dir"
keystore-password="jbossas" alias="jboss" key-password="jbossas"/>
</ssl>
</server-identities>
<authentication>
<properties path="mgmt-users.properties" relative-to="jboss.domain.config.dir"/>
</authentication>
</security-realm>
</security-realms>
We've added server-identities into security-realm, which is used for authentication host when slave tries to
connect to master. In secret value property we have 'cGFzc3cwcmQh', which is the base64 code for
'passw0rd!'. You can generate this value by using a base64 calculator such as the one at
http://www.webutils.pl/index.php?idx=base64.
Then in domain controller section we also need to add security-realm property:
<domain-controller>
<remote protocol="remote" host="10.211.55.7" port="9999" username="slave"
security-realm="ManagementRealm" />
</domain-controller>
So the slave host could use the authentication information we provided in 'ManagementRealm'.
Dry Run
Now everything is set for the two hosts to run in domain mode. Let's start them by running domain.sh on
both hosts. If everything goes fine, we could see from the log on master:
That means all the configurations are correct and two hosts are run in domain mode now as expected.
Hurrah!
WildFly 9
7.17.4 Deployment
Now we can deploy a demo project into the domain. I have created a simple project located at:
https://github.com/liweinan/cluster-demo
In this demo project we have a very simple web application. In web.xml we've enabled session replication by
adding following entry:
<distributable/>
And it contains a jsp page called put.jsp which will put current time to a session entry called 'current.time':
<%
session.setAttribute("current.time", new java.util.Date());
%>
It's an extremely simple project but it could help us to test the cluster later: We will access put.jsp from
cluster and see the request are distributed to master, then we disconnect master and access get.jsp. We
should see the request is forwarded to slave but the 'current.time' value is held by session replication. We'll
cover more details on this one later.
Let's go back to this demo project. Now we need to create a war from it. In the project directory, run the
following command to get the war:
mvn package
It will generate cluster-demo.war. Then we need to deploy the war into domain. First we should access the
http management console on master(Because master is acting as domain controller):
http://10.211.55.7:9990
WildFly 9
It will popup a windows ask you to input account name and password, we can use the 'admin' account we've
added just now. After logging in we could see the 'Server Instances' window. By default there are three
servers listed, which are:
server-one
server-two
server-three
We could see server-one and server-two are in running status and they belong to main-server-group;
server-three is in idle status, and it belongs to other-server-group.
All these servers and server groups are set in domain.xml on master as7. What we are interested in is the
'other-server-group' in domain.xml:
We could see this server-group is using 'ha' profile, which then uses 'ha-sockets' socket binding group. It
enable all the modules we need to establish cluster later(including infinispan, jgroup and mod_cluster
modules). So we will deploy our demo project into a server that belongs to 'other-server-group', so
'server-three' is our choice.
http://10.211.55.7:9990
Now server-three is not running, so let's click on 'server-three' and then click the 'start' button at bottom right
of the server list. Wait a moment and server-three should start now.
Now we should also enable 'server-three' on slave: From the top of menu list on left side of the page, we
could see now we are managing master currently. Click on the list, and click 'slave', then choose
'server-three', and we are in slave host management page now.
Then repeat the steps we've done on master to start 'server-three' on slave.
WildFly 9
server-three on master and slave are two different hosts, their names can be different.
After server-three on both master and slave are started, we will add our cluster-demo.war for deployment.
Click on the 'Manage Deployments' link at the bottom of left menu list.
(We should ensure the server-three should be started on both master and slave)
After enter 'Manage Deployments' page, click 'Add Content' at top right corner. Then we should choose our
cluster-demo.war, and follow the instruction to add it into our content repository.
Now we can see cluster-demo.war is added. Next we click 'Add to Groups' button and add the war to
'other-server-group' and then click 'save'.
Wait a few seconds, management console will tell you that the project is deployed into 'other-server-group'.
WildFly 9
Please note we have two hosts participate in this server group, so the project should be deployed in both
master and slave now - that's the power of domain management.
Now let's verify this, trying to access cluster-demo from both master and slave, and they should all work
now:
http://10.211.55.7:8330/cluster-demo/
WildFly 9
http://10.211.55.2:8330/cluster-demo/
Now that we have finished the project deployment and see the usages of domain controller, we will then
head up for using these two hosts to establish a cluster
WildFly 9
Why is the port number 8330 instead of 8080? Please check the settings in host.xml on both
master and slave:
Now we quit the WildFly process on both master and slave. We have some work left on host.xml
configurations. Open the host.xml of master, and do some modifications the servers section from:
to:
We've set auto-start to true so we don't need to enable it in management console each time WildFly restart.
Now open slave's host.xml, and modify the server-three section:
Besides setting auto-start to true, we've renamed the 'server-three' to 'server-three-slave'. We need to do
this because mod_cluster will fail to register the hosts with same name in a single server group. It will cause
name conflict.
After finishing the above configuration, let's restart two as7 hosts and go on cluster configuration.
WildFly 9
The WildFly 8 domain controller and httpd are not necessary to be on same host. But in this article
I just install them all on master for convenience.
And then we need to download newer version of mod_cluster from its website:
http://www.jboss.org/mod_cluster/downloads
http://downloads.jboss.org/mod_cluster/1.1.3.Final/mod_cluster-1.1.3.Final-linux2-x86-so.tar.gz
/etc/httpd/modules
sudo vi /etc/httpd/conf/httpd.conf
WildFly 9
This is conflicted with cluster module. And then we need to make httpd to listen to public address so we
could do the testing. Because we installed httpd on master host so we know the ip address of it:
Listen 10.211.55.7:80
# This Listen port is for the mod_cluster-manager, where you can see the status of mod_cluster.
# Port 10001 is not a reserved port, so this prevents problems with SELinux.
Listen 10.211.55.7:10001
# This directive only applies to Red Hat Enterprise Linux. It prevents the temmporary
# files from being written to /etc/httpd/logs/ which is not an appropriate location.
MemManagerFile /var/cache/httpd
<VirtualHost 10.211.55.7:10001>
<Directory />
Order deny,allow
Deny from all
Allow from 10.211.55.
</Directory>
WildFly 9
http://docs.jboss.org/mod_cluster/1.1.0/html/Quick_Start_Guide.html
7.17.6 Testing
If everything goes fine we can start httpd service now:
http://10.211.55.7/cluster-demo/put.jsp
We should see the request is distributed to one of the hosts(master or slave) from the WildFly log. For me
the request is sent to master:
WildFly 9
Now I disconnect master by using the management interface. Select 'runtime' and the server 'master' in the
upper corners.
Select 'server-three' and kick the stop button, the active-icon should change.
Killing the server by using system commands will have the effect that the Host-Controller restart the instance
imediately!
Then wait for a few seconds and access cluster:
http://10.211.55.7/cluster-demo/get.jsp
Now the request should be served by slave and we should see the log from slave:
[stdout] (http-10.211.55.2-10.211.55.2-8330-1)
And from the get.jsp we should see that the time we get is the same we've put by 'put.jsp'. Thus it's proven
that the session is correctly replicated to slave.
Now we restart master and should see the host is registered back to cluster.
WildFly 9
It doesn't matter if you found the request is distributed to slave at first time. Then just disconnect
slave and do the testing, the request should be sent to master instead. The point is we should see
the request is redirect from one host to another and the session is held.
WildFly 9
8.1 Introduction
This page has moved to https://github.com/wildfly/quickstart#introduction
WildFly 9
WildFly 9
You should see JBoss AS start up (unless you already started it in Starting JBoss AS from Eclipse with
JBoss Tools) and the application deploy in the Console log:
WildFly 9
http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/guide/NumberguessQuickstart/#_deploying_the_numberguess_qui
WildFly 9
http://www.jboss.org/jdf/quickstarts/jboss-as-quickstart/guide/KitchensinkQuickstart/#_the_kitchensink_quickstart_in_depth
The Getting Started Guide covers topics such as server layout (what you can configure
where), data source definition, and using the web management interface.
Guide
Torquebox
Torque Box allows you to use all the familiar services from JBoss AS 7, but with Ruby.
WildFly 9
In this article I'd like to introduce the following things:
Create a project using Maven
Add JSF into project
Writing Code
Add JBoss AS 7 deploy plugin into project
Deploy project to JBoss AS 7
Import project into IntelliJ
Add IntelliJ JSF support to project
Add JBoss AS7 to IntelliJ
Debugging project with IntelliJ and AS7
I won't explain many basic concepts about AS7, maven and IntelliJ in this article because there are already
many good introductions on these topics. So before doing the real work, there some preparations should be
done firstly:
Download JBoss AS7
It could be downloaded from here: http://www.jboss.org/jbossas/downloads/
Using the latest release would be fine. When I'm writing this article the latest version is 7.1.1.Final.
Install Maven
Please make sure you have maven installed on your machine. Here is my environment:
Get IntelliJ
In this article I'd like to use IntelliJ Ultimate Edition as the IDE for development, it's a commercial software
and can be downloaded from: http://www.jetbrains.com/idea/
The version I'm using is IntelliJ IDEA Ultimate 11.1
After all of these prepared, we can dive into the real work:
WildFly 9
If everything goes fine maven will generate the project for us:
WildFly 9
<repository>
<id>jvnet-nexus-releases</id>
<name>jvnet-nexus-releases</name>
<url>https://maven.java.net/content/repositories/releases/</url>
</repository>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
Please note the 'scope' is 'provided', because we don't want to bundle the jsf.jar into the war produced by
our project later, as JBoss AS7 already have jsf bundled in.
Then we run 'mvn install' to update the project, and maven will download jsf-api for us automatically.
Writing Code
Writing JSF code in this article is trivial, so I've put written a project called 'jsfdemo' onto github:
https://github.com/liweinan/jsfdemo
Please clone this project into your local machine, and import it into IntelliJ following the steps described as
above.
WildFly 9
<repository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
<layout>default</layout>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
<pluginRepository>
<id>jboss-public-repository-group</id>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
I've put the final version pom.xml here to check whether your modification is correct:
https://github.com/liweinan/jsfdemo/blob/master/pom.xml
Now we have finished the setup work for maven.
WildFly 9
bin/standalone.sh
AS7 should start in a short time. Then let's go back to our project directory and run maven command:
mvn -q jboss-as:deploy
Maven will use some time to download necessary components for a while, so please wait patiently. After a
while, we can see the result:
And if you check the console output of AS7, you can see the project is deployed:
WildFly 9
Now we have learnt how to create a JSF project and deploy it to AS7 without any help from graphical tools.
Next let's see how to use IntelliJ IDEA to go on developing/debugging our project.
WildFly 9
WildFly 9
WildFly 9
Then IntelliJ will ask you the position of the project you want to import. In 'Root directory' input your project's
directory and leave other options as default:
WildFly 9
WildFly 9
WildFly 9
WildFly 9
WildFly 9
Click on 'Facets' section on left; Select 'Web' facet that we already have, and click the '+' on top, choose
'JSF':
WildFly 9
Click 'Ok':
WildFly 9
WildFly 9
WildFly 9
Click 'configure':
WildFly 9
WildFly 9
Now we need to add our project into deployment. Click the 'Deployment' tab:
WildFly 9
WildFly 9
Leave everything as default and click 'Ok', now we've added JBoss AS7 into IntelliJ
WildFly 9
With WildFly you can directly start the server in debug mode:
Please note we should undeploy the existing 'jsfdemo' project in AS7 as we've added by maven jboss deploy
plugin before. Or AS7 will tell us there is already existing project with same name so IntelliJ could not deploy
the project anymore.
If the project start correctly we can see from the IntelliJ console window, and please check the debug option
is enabled:
WildFly 9
Now we will setup the debug configuration, click 'debug' option on menu:
WildFly 9
Set the 'port' to the one you used in AS7 config file 'standalone.conf':
WildFly 9
Leave other configurations as default and click 'Ok'. Now we need to set breakpoints in project, let's choose
TimeBean.java and set a breakpoint on 'getNow()' method by clicking the left side of that line of code:
WildFly 9
Now we go to web browser and see our project's main page, try to click on 'Get current time':
WildFly 9
Then IntelliJ will popup and the code is pausing on break point:
WildFly 9
Conclusion
In this article I've shown to you how to use maven to create a project using JSF and deploy it in JBoss AS7,
and I've also talked about the usage of IntelliJ during project development phase. Hope the contents are
practical and helpful to you
References
JBoss AS7: Using JPDA to debug the AS source code
Importing JBoss 7 Bundled Dependency Versions Through Maven
Maven Getting Started - Developers
JSF 2.1 project using Eclipse and Maven 2:http
Practical RichFaces
Oracle Mojarra JavaServer Faces
JBoss AS7 Maven Plugin
WildFly 9
Introduction
This document is a script for use with the quickstarts associated with the Getting Started Developing
Applications Guide. It can be used as the basis for demoing/explaining the Java EE 6 programming model
with JBoss AS 7.
There is an associated presentation JBoss AS - Getting Started Developing Applications which can be
used to introduce the Java EE 6 ecosystem.
The emphasis here is on the programming model, not on OAM/dev-ops, performance etc.
WildFly 9
WildFly 9
Using Maven
1. Start JBoss AS 7 from the console
$JBOSS_HOME/bin/standalone.sh
The quickstarts use the jboss-as maven plugin to deploy and undeploy applications. This
plugin uses the JBoss AS Native Java Detyped Management API to communicate with the
server. The Detyped API is used by management tools to control an entire domain of
servers, and exposes only a small number of types, allowing for backwards and forwards
compatibility.
mvn jboss-as:undeploy
WildFly 9
$JBOSS_HOME/bin/standalone.sh
$JBOSS_HOME/bin/jboss-admin.sh --connect
The command line also uses the Deptyped Management API to communicate with the
server. It's designed to be as "unixy" as possible, allowing you to "cd" into nodes, with full
tab completion etc. The CLI allows you to deploy and undeploy applications, create JMS
queues, topics etc., create datasources (normal and XA). It also fully supports the domain
node.
deploy target/jboss-as-helloworld.war
undeploy jboss-as-helloworld.war
WildFly 9
$JBOSS_HOME/bin/standalone.sh
The web maangement interface offers the same functionality as the CLI (and again uses the
Detyped Management API), but does so using a pretty GWT interface! You can set up
virtual servers, interrogate sub systems and more.
4. Navigate Manage Deployments -> Add content. Click on choose file and locate
helloworld/target/jboss-as-helloworld.war.
5. Click Next and Finish to upload the war to the server.
6. Now click Enable and Ok to start the application
7. Switch to the console to show it deployed
8. Now click Remove
WildFly 9
$JBOSS_HOME/bin/standalone.sh
Of course, you can still use the good ol' file system to deploy. Just copy the file to
$JBOSS_HOME/standalone/deployments.
cp target/jboss-as-helloworld.war $JBOSS_HOME/standalone/deployments
The filesystem deployment uses marker files to indicate the status of a deployment. As this
deployment succeeded we get a
$JBOSS_HOME/standalone/deployments/jboss-as-helloworld.war.deployed
file. If the deployment failed, you would get a .failed file etc.
rm $JBOSS_HOME/standalone/deployments/jboss-as-helloworld.war.deployed
This gives you much more precise control over deployments than before
WildFly 9
Using Eclipse
1. Add a JBoss AS server
1. Bring up the Server view
2. Right click in it, and choose New -> Server
3. Choose JBoss AS 7.0 and hit Next
4. Locate the server on your disc
5. Hit Finish
2. Start JBoss AS in Eclipse
1. Select the server
2. Click the Run button
3. Deploy the app
1. right click on the app, choose Run As -> Run On Server
2. Select the AS 7 instance you want to use
3. Hit finish
4. Load the app at http://localhost:8080/jboss-as-helloworld
WildFly 9
WildFly 9
Views
1. index.html - same as before, just kicks us into the app
2. home.xhtml
1. Lines 19 - 25 these are messages output depending on state of beans (minimise coupling
between controller and view layer by interrogating state, not pushing)
3. Line 20 output any messages pushed out by the controller
4. Line 39 - 42 the input field is bound to the guess field on the game bean. We validate the input by
calling a method on the game bean.
5. Line 43 - 45 the command button is used to submit the form, and calls a method on the game bean
6. Line 48, 49, The reset button again calls a method on the game bean
WildFly 9
Beans
1. Game.java this is the main controller for the game. App has no persistence etc.
1. @Named As we discussed CDI is typesafe, (beans are injected by type) but sometimes need
to access in a non-typesafe fashion. @Named exposes the Bean in EL - and allows us to
access it from JSF
2. @SessionScoped really simple app, we keep the game data in the session - to play two
concurrent games, need two sessions. This is not a limitation of CDI, but simply keeps this
demo very simple. CDI will create a bean instance the first time the game bean is accessed,
and then always load that for you
3. @Inject maxNumber here we inject the maximum number we can guess. This allows us to
externalize the config of the game
4. @Inject rnadomNumber here we inject the random number we need to guess. Two things
to discuss here
1. Instance - normally we can inject the object itself, but sometimes it's useful to inject a
"provider" of the object (in this case so that we can get a new random number when the
game is reset!). Instance allows us to get() a new instance when needed
2. Qualifiers - now we have two types of Integer (CDI auto-boxes types when doing
injection) so we need to disambiguate. Explain qualifiers and development time
approach to disambiguation. You will want to open up @MaxNumber and @Random here.
5. @PostConstruct here is our reset method - we also call it on startup to set up initial values.
Show use of Instance.get().
2. Generator.java This bean acts as our random number generator.
3. @ApplicationScoped explain about other scopes available in CDI + extensibility.
1. next() Explain about producers being useful for determining bean instance at runtime
2. getMaxNumber() Explain about producers allowing for loose coupling
WildFly 9
Deployment Descriptors
1. Show that we have the same ones we are used in src/main/webapp beans.xml,
faces-config.xml
2. We have a couple of new ones in src/main/resources
1. persistence.xml. Not too exciting. We are using a datasource that AS7 ships with. It's
backed by the H2 database and is purely a sample datasource to use in sample applications.
We also tell Hibernate to auto-create tables - as you always have.
2. import.sql Again, the same old thing you are used to in Hibernate - auto-import data when
the app starts.
3. pom.xml is the same again, but just adds in dependencies for JPA, JTA and EJB
Views
1. template.xhtml One of the updates added to JSF 2.0 was templating ability. We take advantage
of that in this app, as we have multiple views
1. Actually nothing too major here, we define the app "title" and we could easily define a common
footer etc. (we can see this done in the kitchensink app)
2. The ui:insert command inserts the actual content from the templated page.
#home.xhtml
3. Uses the template
4. Has some input fields for the login form, button to login and logout, link to add users.
5. Binds fields to credentials bean}}
6. Buttons link to login bean which is the controller
2. users.xhtml
1. Uses the template
2. Displays all users using a table
3. Has a form with input fields to add users.
4. Binds fields to the newUser bean
5. Methods call on userManager bean
WildFly 9
Beans
1. Credentials.java Backing bean for the login form field, pretty trivial. It's request scoped (natural
for a login field) and named so we can get it from JSF.
2. Login.java
1. Is session scoped (a user is logged in for the length of their session or until they log out}}
2. Is accessible from EL
3. Injects the current credentials
4. Uses the userManager service to load the user, and sends any messages to JSF as needed
5. Uses a producer method to expose the @LoggedIn user (producer methods used as we don't
know which user at development time)
3. User.java Is a pretty straightforward JPA entity. Mapped with @Entity, has an natural id.
4. UserManager.java This is an interface, and by default we use the ManagedBean version, which
requires manual TX control
5. ManagedBeanUserManager.java - accessible from EL, request scoped.
1. Injects a logger (we'll see how that is produced in a minute)
2. Injects the entity manager (again, just a min)
3. Inject the UserTransaction (this is provided by CDI)
4. getUsers() standard JPA-QL that we know and love - but lots of ugly TX handling code.
5. Same for addUser() and findUser() methods - very simple JPA but...
6. Got a couple of producer methods.
1. getUsers() is obvious - loads all the users in the database. No ambiguity - CDI takes
into account generic types when injecting. Also note that CDI names respect JavaBean
naming conventions
2. getNewUser() is used to bind the new user form to from the view layer - very nice as it
decreases coupling - we could completely change the wiring on the server side (different
approach to creating the newUser bean) and no need to change the view layer.
6. EJBUserManager.java
1. It's an alternative explain alternatives, and that they allow selection of beans at deployment
time
2. Much simple now we have declarative TX control.
3. Start to see how we can introduce EJB to get useful enterprise services such as declarative TX
control
7. Resources.java
1. {EntityManager}} - explain resource producer pattern
WildFly 9
Bean Validation
1. Explain the benefits of bean validation - need your data always valid (protect your data) AND good
errors for your user. BV allows you to express once, apply often.
2. index.xhtml
1. Show the input fields no validators attached
2. Show the message output
3. Member.java
1. Hightlight the various validation annotations
4. Java EE automatically applies the validators in both the persistence layer and in your views
RS
1. index.xhtml - Show that URL generation is just manual
2. JaxRsActivator.java - simply activates JAX-RS
3. Member.java - add JAXB annotation to make JAXB process the class properly
4. MemberResourceRESTService.java
1. @Path sets the JAX-RS resource
2. JAX-RS services can use injection
3. @GET methods are auto transformed to XML using JAXB
5. And that is it!
WildFly 9
Arquillian
1. Make sure JBoss AS is running
2. mvn clean test -Parq-jbossas-remote
WildFly 9
Java EE Java EE
WildFly 8
WildFly
Full
Full
Profile
Web
Profile
Profile
Web
Profile
--
--
WildFly 9
X
X
CMP 2.0 (Lite)
X
CMP 2.0
X
(Lite)
Optional
Not
Available
--
--
--
--
--
--
--
--
Optional
--
--
--
--
--
Optional
--
--
--
--
--
--
--
Optional
--
--
--
X
X
WildFly 9
This document provides a quick overview on how to download and get started using WildFly 8 for your
application development. For in-depth content on administrative features, refer to the WildFly 8 Admin
Guide.
9.1.1 Download
Wildfly 8 distributions can be obtained from:
wildfly.org/downloads
WildFly 8 provides a single distribution available in zip or tar file formats.
wildfly-8.0.0.Final.zip
wildfly-8.0.0.Final.tar.gz
9.1.2 Requirements
Java SE 7 or later (we recommend that you use the latest update available)
9.1.3 Installation
Simply extract your chosen download to the directory of your choice. You can install WildFly 8 on any
operating system that supports the zip or tar formats. Refer to the Release Notes for additional information
related to the release.
WildFly 9
DESCRIPTION
appclient
bin
Start up scripts, start up configuration files and various command line utilities like
Vault, add-user and Java diagnostic report
available for Unix and Windows environments
bin/client
docs/schema
Configuration files, deployment content, and writable areas used by the domain
mode processes run from this installation.
modules
standalone
Configuration files, deployment content, and writable areas used by the single
standalone server run from this installation.
welcome-content
WildFly 9
deployments
End user deployment content can be placed in this directory for automatic detection and
deployment of that content into the server's runtime.
NOTE: The server's management API is recommended for installing deployment content.
File system based deployment scanning capabilities remain for developer convenience.
lib/ext
Location for installed library jars referenced by applications using the Extension-List
mechanism
log
tmp
tmp/auth
Special location used to exchange authentication tokens with local clients so they can
confirm that they are local to the running AS process.
WildFly 9
A collection of
multiple servers are referred to as a "domain". Domains can span multiple physical (or virtual) machines
with all WildFly instances on a given host under the control of a Host Controller process. The Host
Controllers interact with the Domain Controller to control the lifecycle of the WildFly instances running on
that host and to assist the Domain Controller in managing them. The configuration files, deployment content
and writeable areas used by domain mode processes run from a WildFly installation are found in the
following subdirectories under the top level "domain" directory:
DIRECTORY DESCRIPTION
configuration Configuration files for the domain and for the Host Controller and any servers running off of
this installation. All configuration information for the servers managed wtihin the domain is
located here and is the single place for configuration information.
content
an internal working area for the Host Controller that controls this installation. This is where it
internally stores deployment content. This directory is not meant to be manipulated by end
users.
Note that "domain" mode does not support deploying content based on scanning a file
system.
lib/ext
Location for installed library jars referenced by applications using the Extension-List
mechanism
log
Location where the Host Controller process writes its logs. The Process Controller, a small
lightweight process that actually spawns the other Host Controller process and any
Application Server processes also writes a log here.
servers
Writable area used by each Application Server instance that runs from this installation.
Each Application Server instance will have its own subdirectory, created when the server is
first started. In each server's subdirectory there will be the following subdirectories:
data -- information written by the server that needs to survive a restart of the server
log -- the server's log files
tmp -- location for temporary files written by the server
tmp
tmp/auth
Special location used to exchange authentication tokens with local clients so they can
confirm that they are local to the running AS process.
WildFly 9
WildFly 8 Configurations
Standalone Server Configurations
standalone.xml (default)
Java Enterprise Edition 7 web profile certified configuration with the required technologies plus
those noted in the table above.
standalone-ha.xml
Java Enterprise Edition 7 web profile certified configuration with high availability
standalone-full.xml
Java Enterprise Edition 7 full profile certified configuration including all the required EE 7
technologies
standalone-full-ha.xml
Java Enterprise Edition 7 full profile certified configuration with high availability
Starting WildFly 8
To start WildFly 8 using the default web profile configuration in "standalone" mode, change directory to
$JBOSS_HOME/bin.
./standalone.sh
To start the default web profile configuration using domain management capabilities,
./domain.sh
./standalone.sh --server-config=standalone-full-ha.xml
WildFly 9
Similarly to start an alternate configuration in domain mode:
./domain.sh --domain-config=my-domain-configuration.xml
Alternatively, you can create your own selecting the additional subsystems you want to add, remove, or
modify.
=========================================================================
JBoss Bootstrap Environment
JBOSS_HOME: /work/wildfly-8.0.0.Final
JAVA: /usr/jdk1.7/bin/java
JAVA_OPTS: -server -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true
-Dorg.jboss.resolver.warning=true -Dsun.rmi.dgc.client.gcInterval=3600000
-Dsun.rmi.dgc.server.gcInterval=3600000
-Djboss.modules.system.pkgs=org.jboss.byteman
=========================================================================
22:58:56,741 INFO
22:58:56,964 INFO
22:58:57,046 INFO
"WildFly" starting
<snip>
23:04:27,150 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: WildFly 8.0.0.Final
"WildFly" started in 1974ms - Started 183 of 232 services (80 services are lazy, passive or
on-demand)
As with previous JBoss releases, you can point your browser to http://localhost:8080 (if using the default
configured http port) which brings you to the Welcome Screen:
WildFly 9
From here you can access links to the WildFly community documentation set, stay up-to-date on the latest
project information, have a discussion in the user forum and access the enhanced web-based Administration
Console. Or, if you uncover a defect while using WildFly, report an issue to inform us (attached patches will
be reviewed). This landing page is recommended for convenient access to information about WildFly 8 but
can easily be replaced with your own if desired.
WildFly 9
Authentication
By default WildFly 8 is now distributed with security enabled for the management interfaces, this means that
before you connect using the administration console or remotely using the CLI you will need to add a new
user, this can be achieved simply by using the add-user.sh script in the bin folder.
After starting the script you will be guided through the process to add a new user: -
./add-user.sh
What type of user do you wish to add?
a) Management User (mgmt-users.properties)
b) Application User (application-users.properties)
(a):
In this case a new user is being added for the purpose of managing the servers so select option a.
You will then be prompted to enter the details of the new user being added: -
It is important to leave the name of the realm as 'ManagementRealm' as this needs to match the name used
in the server's configuration, for the remaining fields enter the new username, password and password
confirmation.
Provided there are no errors in the values entered you will then be asked to confirm that you want to add the
user, the user will be written to the properties files used for authentication and a confirmation message will
be displayed.
The modified time of the properties files are inspected at the time of authentication and the files reloaded if
they have changed, for this reason you do not need to re-start the server after adding a new user.
WildFly 9
Administration Console
To access the web-based Administration Console, simply follow the link from the Welcome Screen. To
directly access the Management Console, point your browser at:
http://localhost:9990/console
NOTE: port 9990 is the default port configured.
<management-interfaces>
<native-interface security-realm="ManagementRealm">
<socket-binding native="management-native"/>
</native-interface>
<http-interface security-realm="ManagementRealm">
<socket-binding http="management-http"/>
</http-interface>
</management-interfaces>
If you modify the management-http socket binding in your running configuration: adjust the above command
accordingly. If such modifications are made, then the link from the Welcome Screen will also be
inaccessible.
If you have not yet added at least one management user an error page will be displayed asking you to add a
new user, after a user has been added you can click on the 'Try Again' link at the bottom of the error page to
try connecting to the administration console again.
WildFly 9
Command-Line Interface
If you prefer to manage your server from the command line (or batching), the jboss-cli.sh script provides the
same capabilities available via the web-based UI. This script is accessed from $JBOSS_HOME/bin
directory; e.g.,
cd $JBOSS_HOME/bin
./jboss-cli.sh --connect
Connected to standalone controller at localhost:9999
WildFly 9
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
<driver>h2</driver>
<pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<xa-datasource jndi-name="java:jboss/datasources/ExampleXADS" pool-name="ExampleXADS">
<driver>h2</driver>
<xa-datasource-property name="URL">jdbc:h2:mem:test</xa-datasource-property>
<xa-pool>
<min-pool-size>10</min-pool-size>
<max-pool-size>20</max-pool-size>
<prefill>true</prefill>
</xa-pool>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</xa-datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
The datasource subsystem is provided by the IronJacamar project. For a detailed description of the available
configuration properties, please consult the project documentation.
IronJacamar homepage: http://www.jboss.org/ironjacamar
Project Documentation: http://www.jboss.org/ironjacamar/docs
Schema description:
http://docs.jboss.org/ironjacamar/userguide/1.0/en-US/html/deployment.html#deployingds_descriptor
WildFly 9
<subsystem xmlns="urn:jboss:domain:logging:1.0">
<console-handler name="CONSOLE" autoflush="true">
<level name="DEBUG"/>
<formatter>
<pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
</formatter>
</console-handler>
[...]
<logger category="org.jboss.as">
<level name="DEBUG"/>
</logger>
[...]
</subsystem>
By default the server.log is configured to include all levels in it's log output. In the above example we
changed the console to also display debug messages.
WildFly 9
WildFly 9
WildFly 9
Tutorial Overview
This chapter describes the Java API for RESTful web services (JAX-RS, defined in JSR331). RESTEasy is
an portable implementation of this specification which can run in any Servlet container. Tight integration with
JBoss Application Server is available for optimal user experience in that environment. While JAX-RS is only
a server-side specification, RESTeasy has innovated to bring JAX-RS to the client through the RESTEasy
JAX-RS Client Framework.
Detailed documentation on RESTEasy is available here.
The source for this tutorial is in github repository git://github.com/tdiesler/javaee-tutorial.git
OpenShift, is a portfolio of portable cloud services for deploying and managing applications in the cloud. This
tutorial shows how to deploy a RESTful web service on the free OpenShift Express JavaEE cartridge that
runs JBossAS 7.
An application running on Android shows how to leverage JBoss technology on mobile devices. Specifically,
we show how use the RESTEasy client API from an Android device to integrate with a RESTful service
running on a JBossAS 7 instance in the cloud.
The following topics are addressed
What are RESTful web services
Creating a RESTful server endpoint
Deploying a RESTful endpoint to a JBossAS instance in the cloud
RESTEasy client running on an Android mobile device
WildFly 9
Coming Soon
This section is still under development.
RESTful web services are designed to expose APIs on the web. REST stands for Representational State T
ransfer. It aims to provide better performance, scalability, and flexibility than traditinoal web services, by
allowing clients to access data and resources using predictable URLs. Many well-known public web services
expose RESTful APIs.
The Java 6 Enterprise Edition specification for RESTful services is JAX-RS. It is covered by JSR-311 (
http://jcp.org/jsr/detail/311.jsp). In the REST model, the server exposes APIs through specific URIs (typically
URLs), and clients access those URIs to query or modify data. REST uses a stateless communication
protocol. Typically, this is HTTP.
The following is a summary of RESTful design principles:
A URL is tied to a resource using the @Path annotation. Clients access the resource using the URL.
Create, Read, Update, and Delete (CRUD) operations are accessed via PUT, GET, POST, and
DELETE requests in the HTTP protocol.
PUT creates a new resource.
DELETE deletes a resource.
GET retrieves the current state of a resource.
POST updates a resources's state.
Resources are decoupled from their representation, so that clients can request the data in a variety of
different formats.
Stateful interactions require explicit state transfer, in the form of URL rewriting, cookies, and hidden
form fields. State can also be embedded in response messages.
WildFly 9
The Library is the RESTful Root Resource. Here we use a set of standard JAX-RS annotations to define
The root path to the library resource
The wire representation of the data (MIME type)
The Http methods and corresponding paths
@Path("/library")
@Consumes({ "application/json" })
@Produces({ "application/json" })
public class Library {
@GET
@Path("/books")
public Collection<Book> getBooks() {
...
}
@GET
@Path("/book/{isbn}")
public Book getBook(@PathParam("isbn") String id) {
...
}
@PUT
@Path("/book/{isbn}")
public Book addBook(@PathParam("isbn") String id, @QueryParam("title") String title) {
...
}
@POST
@Path("/book/{isbn}")
public Book updateBook(@PathParam("isbn") String id, String title) {
...
}
@DELETE
@Path("/book/{isbn}")
public Book removeBook(@PathParam("isbn") String id) {
...
}
}
WildFly 9
Annotation
Description
@Path
Identifies the URI path that a resource class or class method will serve requests for
@Consumes Defines the media types that the methods of a resource class can accept
@Produces
Defines the media type(s) that the methods of a resource class can produce
@GET
@PUT
@POST
@DELETE
For a full description of the available JAX-RS annotations, see the JAX-RS API documentation.
Review
AS7-1674 Remove or explain why web.xml is needed for RESTful endpoints
<jboss-web>
<context-root>jaxrs-sample</context-root>
</jboss-web>
WildFly 9
Arquillian, the test framework we use throughout this tutorial, can manage server startup/shutdown. It is
however also possible to startup the server instance manually before you run the tests. The latter allows you
to look at the console and see what log output the deployment phase and JAX-RS endpoint invocations
produce.
http://tutorial-tdiesler.rhcloud.com/
The remote repository is located here:
ssh://79dcb9db5e134cccb9d1ba33e6089667@tutorial-tdiesler.rhcloud.com/~/git/tutorial.git/
Next, we can clone the remote Git repository to our local workspace
WildFly 9
$ git clone
ssh://79dcb9db5e134cccb9d1ba33e6089667@tutorial-tdiesler.rhcloud.com/~/git/tutorial.git
Cloning into tutorial...
remote: Counting objects: 24, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 24 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (24/24), 21.84 KiB, done.
ls -1 tutorial
deployments
pom.xml
README
src
Because we want to deploy an already existing web application, which we'll build in the next step, we can
safely remove the source artefacts from the repository.
Now we copy the JAX-RS endpoint webapp that we build above to the 'deployments' folder and commit the
changes.
$ cp javaee-tutorial/jaxrs/server/target/javaee-tutorial-jaxrs-server-1.0.0-SNAPSHOT.war
tutorial/deployments
$ cd tutorial; git commit -a -m "Initial jaxrs endpoint deployment"
[master be5b5a3] Initial jaxrs endpoint deployment
7 files changed, 0 insertions(+), 672 deletions(-)
create mode 100644 deployments/javaee-tutorial-jaxrs-server-1.0.0-SNAPSHOT.war
delete mode 100644 pom.xml
delete mode 100644 src/main/java/.gitkeep
delete mode 100644 src/main/resources/.gitkeep
delete mode 100644 src/main/webapp/WEB-INF/web.xml
delete mode 100644 src/main/webapp/health.jsp
delete mode 100644 src/main/webapp/images/jbosscorp_logo.png
delete mode 100644 src/main/webapp/index.html
delete mode 100644 src/main/webapp/snoop.jsp
$ git push origin
Counting objects: 6, done.
...
remote: Starting application...Done
You can now use curl or your browser to see the JAX-RS endpoint in action. The following URL lists the
books that are currently registered in the library.
WildFly 9
$ curl http://tutorial-tdiesler.rhcloud.com/jaxrs-sample/library/books
[
{"title":"The Judgment","isbn":"001"},
{"title":"The Stoker","isbn":"002"},
{"title":"Jackals and Arabs","isbn":"003"},
{"title":"The Refusal","isbn":"004"}
]
WildFly 9
Then go to File|New|Android Project and fill out the first wizard page like this
WildFly 9
Click Finish. Next, go to Project|Properties|Build Path|Libraries and add these external libraries to your
android project.
WildFly 9
To run the application in the emulator, we need an Android Virtual Device (AVD). Go to Window|Android
SDK and AVD Manager and create a new AVD like this
WildFly 9
Now go to Run|Configuration to create a new run configuration for the client app.
WildFly 9
Now you should be able to launch the application in the debugger. Right click on the
javaee-tutorial-jaxrs-android project and select Debug As|Android Application. This should launch the
emulator, which now goes though a series of boot screens until it eventually displays the Android home
screen. This will take a minute or two if you do this for the first time.
WildFly 9
WildFly 9
WildFly 9
When you unlock the home screen by dragging the little green lock to the right. You should see the the
running JAX-RS client application.
WildFly 9
Finally, you need to configure the host that the client app connects to. This would be the same as you used
above to curl the library list. In the emulator click Menu|Host Settings and enter the host address of your
OpenShift application.
WildFly 9
When going back to the application using the little back arrow next to Menu, you should see a list of books.
WildFly 9
You can now add, edit and delete books and switch between your browser and the emulator to verify that the
client app is not cheating and that the books are in fact in the cloud on your JBossAS 7 instance.
In Eclipse you can go to the Debug perspective and click on the little Android robot in the lower right corner.
This will display the LogCat view, which should display log output from that Android system as well as from
this client app
WildFly 9
The JAX-RS client application uses an annotated library client interface
@Consumes({ "application/json" })
@Produces({ "application/json" })
public interface LibraryClient {
@GET
@Path("/books")
public List<Book> getBooks();
@GET
@Path("/book/{isbn}")
public Book getBook(@PathParam("isbn") String id);
@PUT
@Path("/book/{isbn}")
public Book addBook(@PathParam("isbn") String id, @QueryParam("title") String title);
@POST
@Path("/book/{isbn}")
public Book updateBook(@PathParam("isbn") String id, String title);
@DELETE
@Path("/book/{isbn}")
public Book removeBook(@PathParam("isbn") String id);
}
WildFly 9
@Override
public List<Book> getBooks() {
List<Book> result = new ArrayList<Book>();
String content = get("books");
Log.d(LOG_TAG, "Result content:" + content);
if (content != null) {
try {
JSONTokener tokener = new JSONTokener(content);
JSONArray array = (JSONArray) tokener.nextValue();
for (int i = 0; i < array.length(); i++) {
JSONObject obj = array.getJSONObject(i);
String title = obj.getString("title");
String isbn = obj.getString("isbn");
result.add(new Book(isbn, title));
}
} catch (JSONException ex) {
ex.printStackTrace();
}
}
Log.i(LOG_TAG, "getBooks: " + result);
return result;
}
private String get(String path) {
try {
HttpGet request = new HttpGet(getRequestURI(path));
HttpResponse res = httpClient.execute(request);
String content = EntityUtils.toString(res.getEntity());
return content;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
The second implementation uses the fabulous RESTEasy client proxy to interact with the JAX-RS endpoint.
The details of Http connectivity and JSON data binding is transparently handled by RESTEasy. The total
size of the application is considerably bigger in size (i.e. 400k)
@Override
public List<Book> getBooks() {
List<Book> result = new ArrayList<Book>();
try {
result = getLibraryClient().getBooks();
} catch (RuntimeException ex) {
ex.printStackTrace();
}
Log.i(LOG_TAG, "getBooks: " + result);
return result;
}
WildFly 9
Stay tuned for an update on a much more optimized version of the RESTEasy mobile client. Feasible is also
a RESTEasy JavaScript library that would enable the portable PhoneGap approach.
Content
Asynchronous Support
Asynchronous Support
Managed Beans
Contexts and Dependency Injection (CDI)
Bean Validation
Java Message Service API (JMS)
Coming Soon
This guide is still under development, check back soon!
WildFly 9
<extension module="org.jboss.as.messaging"/>
<subsystem xmlns="urn:jboss:domain:messaging:1.0">
<!-- Default journal file size is 10Mb, reduced here to 100k for faster first boot -->
<journal-file-size>102400</journal-file-size>
<journal-min-files>2</journal-min-files>
<journal-type>NIO</journal-type>
<!-- disable messaging persistence -->
<persistence-enabled>false</persistence-enabled>
<connectors>
<netty-connector name="netty" socket-binding="messaging" />
<netty-connector name="netty-throughput" socket-binding="messaging-throughput">
<param key="batch-delay" value="50"/>
</netty-connector>
<in-vm-connector name="in-vm" server-id="0" />
</connectors>
<acceptors>
<netty-acceptor name="netty" socket-binding="messaging" />
<netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">
<param key="batch-delay" value="50"/>
<param key="direct-deliver" value="false"/>
</netty-acceptor>
<acceptor name="stomp-acceptor">
<factory-class>org.hornetq.core.remoting.impl.netty.NettyAcceptorFactory</factory-class>
<param key="protocol" value="stomp" />
<param key="port" value="61613" />
</acceptor>
<in-vm-acceptor name="in-vm" server-id="0" />
</acceptors>
<security-settings>
<security-setting match="#">
<permission type="createNonDurableQueue" roles="guest"/>
<permission type="deleteNonDurableQueue" roles="guest"/>
<permission type="consume" roles="guest"/>
<permission type="send" roles="guest"/>
</security-setting>
</security-settings>
<address-settings>
<!--default for catch all-->
<address-setting match="#">
<dead-letter-address>jms.queue.DLQ</dead-letter-address>
<expiry-address>jms.queue.ExpiryQueue</expiry-address>
<redelivery-delay>0</redelivery-delay>
<max-size-bytes>10485760</max-size-bytes>
<message-counter-history-day-limit>10</message-counter-history-day-limit>
<address-full-policy>BLOCK</address-full-policy>
WildFly 9
</address-setting>
</address-settings>
<!--JMS Stuff-->
<jms-connection-factories>
<connection-factory name="InVmConnectionFactory">
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/ConnectionFactory"/>
</entries>
</connection-factory>
<connection-factory name="RemoteConnectionFactory">
<connectors>
<connector-ref connector-name="netty"/>
</connectors>
<entries>
<entry name="RemoteConnectionFactory"/>
</entries>
</connection-factory>
<pooled-connection-factory name="hornetq-ra">
<transaction mode="xa"/>
<connectors>
<connector-ref connector-name="in-vm"/>
</connectors>
<entries>
<entry name="java:/JmsXA"/>
<!-- Global JNDI entry used to provide a default JMS Connection factory to EE
application -->
<entry name="java:jboss/DefaultJMSConnectionFactory"/>
</entries>
</pooled-connection-factory>
</jms-connection-factories>
<jms-destinations>
<jms-queue name="testQueue">
<entry name="queue/test"/>
</jms-queue>
<jms-topic name="testTopic">
<entry name="topic/test"/>
</jms-topic>
</jms-destinations>
</subsystem>
<socket-binding name="messaging" port="5445" />
<socket-binding name="messaging-throughput" port="5455"/>
$ bin/standalone.sh --server-config=standalone-preview.xml
WildFly 9
$ bin/jboss-admin.sh --connect
Connected to standalone controller at localhost:9999
[standalone@localhost:9999 /] jms-queue add --queue-address=BidQueue --entries=queue/bid
[standalone@localhost:9999 /] jms-topic add --topic-address=AuctionTopic --entries=topic/auction
[standalone@localhost:9999 /] exit
Closed connection to localhost:9999
WildFly 9
Coming Soon
This guide is still under development, check back soon!
Session Beans
Stateful Session Beans
Stateless Session Beans
Singleton Session Beans
Message Driven Beans
How can Enterprise JavaBeans can be accessed?
Remote call invocation
Local call invocation
Web Services
Packaging
Session Beans
Stateful Session Beans
Stateless Session Beans
Singleton Session Beans
Packaging
WildFly 9
Even though detailed knowledge of web service meta data is not required, it will definitely help if
you make yourself familiar with it. For further information see
Web service meta data (JSR-181)
Java API for XML binding (JAXB)
Java API for XML-Based Web Services
WildFly 9
Implementing the service
package org.jboss.test.ws.jaxws.samples.retail.profile;
import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
@Stateless
@WebService(
name="ProfileMgmt",
(1)
(2)
targetNamespace = "http://org.jboss.ws/samples/retail/profile",
serviceName = "ProfileMgmtService")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class ProfileMgmtBean {
(3)
@WebMethod
(4)
public DiscountResponse getCustomerDiscount(DiscountRequest request) {
return new DiscountResponse(request.getCustomer(), 10.00);
}
}
WildFly 9
What about the payload?
The method parameters and return values are going to represent our XML payload and thus require being
compatible with JAXB2. Actually you wouldn't need any JAXB annotations for this particular example,
because JAXB relies on meaningful defaults. For the sake of documentation we put the more important ones
here.
Take a look at the request parameter:
package org.jboss.test.ws.jaxws.samples.retail.profile;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import org.jboss.test.ws.jaxws.samples.retail.Customer;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
name = "discountRequest",
namespace="http://org.jboss.ws/samples/retail/profile",
(1)
propOrder = { "customer" }
)
public class DiscountRequest {
protected Customer customer;
public DiscountRequest() {
}
public DiscountRequest(Customer customer) {
this.customer = customer;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer value) {
this.customer = value;
}
}
1. In this case we use @XmlType to specify an XML complex type name and override the namespace.
If you have more complex mapping problems you need to consult the JAXB documentation.
WildFly 9
If the deployment was successful you should be able to see your endpoint in the application server
management console.
WildFly 9
Using wsconsume
The wsconsume tool is used to consume the abstract contract (WSDL) and produce annotated Java classes
(and optionally sources) that define it. We are going to start with the WSDL from our retail example
(ProfileMgmtService.wsdl). For a detailed tool reference you need to consult the user guide.
-c
--catalog=<file>
-p --package=<name>
-w --wsdlLocation=<loc>
-o, --output=<directory>
-s, --source=<directory>
-q, --quiet
-t, --show-traces
1. As you can see we did use the -p switch to specify the package name of the generated sources.
WildFly 9
The generated artifacts explained
File
Purpose
ProfileMgmt.java
Customer.java
Discount*.java
ObjectFactory.java
package-info.java
import javax.xml.ws.Service;
[...]
Service service = Service.create(
new URL("http://example.org/service?wsdl"),
new QName("MyService")
(1)
);
ProfileMgmt profileMgmt = service.getPort(ProfileMgmt.class);
(2)
(3)
1. Create a service factory using the WSDL location and the service name
2. Use the tool created service endpoint interface to build the service stub
3. Use the stub like any other business interface
Appendix
Sample wsdl contract
<definitions
name='ProfileMgmtService'
targetNamespace='http://org.jboss.ws/samples/retail/profile'
xmlns='http://schemas.xmlsoap.org/wsdl/'
xmlns:ns1='http://org.jboss.ws/samples/retail'
xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:tns='http://org.jboss.ws/samples/retail/profile'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
WildFly 9
<types>
<xs:schema targetNamespace='http://org.jboss.ws/samples/retail'
version='1.0' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
<xs:complexType name='customer'>
<xs:sequence>
<xs:element minOccurs='0' name='creditCardDetails' type='xs:string'/>
<xs:element minOccurs='0' name='firstName' type='xs:string'/>
<xs:element minOccurs='0' name='lastName' type='xs:string'/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema
targetNamespace='http://org.jboss.ws/samples/retail/profile'
version='1.0'
xmlns:ns1='http://org.jboss.ws/samples/retail'
xmlns:tns='http://org.jboss.ws/samples/retail/profile'
xmlns:xs='http://www.w3.org/2001/XMLSchema'>
<xs:import namespace='http://org.jboss.ws/samples/retail'/>
<xs:element name='getCustomerDiscount'
nillable='true' type='tns:discountRequest'/>
<xs:element name='getCustomerDiscountResponse'
nillable='true' type='tns:discountResponse'/>
<xs:complexType name='discountRequest'>
<xs:sequence>
<xs:element minOccurs='0' name='customer' type='ns1:customer'/>
</xs:sequence>
</xs:complexType>
<xs:complexType name='discountResponse'>
<xs:sequence>
<xs:element minOccurs='0' name='customer' type='ns1:customer'/>
<xs:element name='discount' type='xs:double'/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</types>
<message name='ProfileMgmt_getCustomerDiscount'>
<part element='tns:getCustomerDiscount' name='getCustomerDiscount'/>
</message>
<message name='ProfileMgmt_getCustomerDiscountResponse'>
<part element='tns:getCustomerDiscountResponse'
name='getCustomerDiscountResponse'/>
</message>
<portType name='ProfileMgmt'>
<operation name='getCustomerDiscount'
parameterOrder='getCustomerDiscount'>
<input message='tns:ProfileMgmt_getCustomerDiscount'/>
<output message='tns:ProfileMgmt_getCustomerDiscountResponse'/>
</operation>
</portType>
<binding name='ProfileMgmtBinding' type='tns:ProfileMgmt'>
<soap:binding style='document'
WildFly 9
transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getCustomerDiscount'>
<soap:operation soapAction=''/>
<input>
<soap:body use='literal'/>
</input>
<output>
<soap:body use='literal'/>
</output>
</operation>
</binding>
<service name='ProfileMgmtService'>
<port binding='tns:ProfileMgmtBinding' name='ProfileMgmtPort'>
<soap:address
location='http://<HOST>:<PORT>/jaxws-samples-retail/ProfileMgmtBean'/>
</port>
</service>
</definitions>
WildFly 9
1. OSGi Technology
2. Management Interface
Management Interface
Coming Soon
This guide is still under development, check back soon!
WildFly 9
10 Glossary
Module
10.1 Module
A logical grouping of classes used for classloading and dependency management in WildFly 8. Modules can
be dynamic or static.
Static Modules are the predefined modules installed in the modules/ directory of the application server.
Dynamic Modules are created by the application server for each deployment (or sub-deployment in an EAR).
Reference: Class Loading in WildFly
10.2 Module
A logical grouping of classes used for classloading and dependency management in WildFly 8. Modules can
be dynamic or static.
Static Modules are the predefined modules installed in the modules/ directory of the application server.
Dynamic Modules are created by the application server for each deployment (or sub-deployment in an EAR).
Reference: Class Loading in WildFly
WildFly 9
11 Extending WildFly
Target Audience
Prerequisites
Examples in this guide
Overview
Example subsystem
Create the skeleton project
Create the schema
Design and define the model structure
Registering the core subsystem model
Registering the subsystem child
Parsing and marshalling of the subsystem xml
Testing the parsers
Add the deployers
Deployment phases and attachments
STRUCTURE
PARSE
DEPENDENCIES
CONFIGURE_MODULE
POST_MODULE
INSTALL
CLEANUP
Integrate with JBoss AS 7
Expressions
What expression types are supported
How to support expressions in subsystems
Key Interfaces and Classes Relevant to Extension Developers
Extension Interface
WildFly 8 Managed Resources
ManagementResourceRegistration Interface
ResourceDefinition Interface
ResourceDescriptionResolver
AttributeDefinition Interface
OperationDefinition and OperationStepHandler Interfaces
Operation Execution and the OperationContext
Resource Interface
DeploymentUnitProcessor Interface
Useful classes for implementing OperationStepHandler
All WildFly 9 documentation
WildFly 9
11.1.1 Prerequisites
You should know how to download, install and run WildFly 9. If not please consult the Getting Started Guide.
You should also be familiar with the management concepts from the Admin Guide, particularly the Core
management concepts section and you need Java development experience to follow the example in this
guide.
11.2 Overview
In this document we provide an example of how to extend the core functionality of WildFly 9 via an extension
and the subsystem it installs. The WildFly 9 core is very simple and lightweight; most of the capabilities
people associate with an application server are provided via extensions and their subsystems. The WildFly 9
distribution includes many extensions and subsystems; the webserver integration is via a subsystem; the
transaction manager integration is via a subsystem, the EJB container integration is via a subsystem, etc.
This document is divided into two main sections. The first is focused on learning by doing. This section will
walk you through the steps needed to create your own subsystem, and will touch on most of the concepts
discussed elsewhere in this guide. The second focuses on a conceptual overview of the key interfaces and
classes described in the example. Readers should feel free to start with the second section if that better fits
their learning style. Jumping back and forth between the sections is also a good strategy.
WildFly 9
mvn archetype:generate \
-DarchetypeArtifactId=wildfly-subsystem \
-DarchetypeGroupId=org.wildfly.archetypes \
-DarchetypeVersion=8.0.0.Final \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
Maven will download the archetype and it's dependencies, and ask you some questions:
$ mvn archetype:generate \
-DarchetypeArtifactId=wildfly-subsystem \
-DarchetypeGroupId=org.wildfly.archetypes \
-DarchetypeVersion=8.0.0.Final \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------------------------------------------------[INFO] Building Maven Stub Project (No POM) 1
[INFO] -----------------------------------------------------------------------[INFO]
.........
Define value for property 'groupId': : com.acme.corp
Define value for property 'artifactId': : acme-subsystem
Define value for property 'version': 1.0-SNAPSHOT: :
Define value for property 'package':
com.acme.corp: : com.acme.corp.tracker
WildFly 9
Instruction
1 Enter the groupId you wish to use
2 Enter the artifactId you wish to use
3 Enter the version you wish to use, or just hit Enter if you wish to accept the default 1.0-SNAPSHOT
4 Enter the java package you wish to use, or just hit Enter if you wish to accept the default (which is
copied from groupId ).
5 Enter the module name you wish to use for your extension.
6 Finally, if you are happy with your choices, hit Enter and Maven will generate the project for you.
You can also do this in Eclipse, see Creating your own application for more details. We now have a skeleton
project that you can use to implement a subsystem. Import the acme-subsystem project into your favourite
IDE. A nice side-effect of running this in the IDE is that you can see the javadoc of WildFly classes and
interfaces imported by the skeleton code. If you do a mvn install in the project it will work if we plug it into
WildFly 8, but before doing that we will change it to do something more useful.
The rest of this section modifies the skeleton project created by the archetype to do something more useful,
and the full code can be found in acme-subsystem.zip.
If you do a mvn install in the created project, you will see some tests being run
$mvn install
[INFO] Scanning for projects...
[...]
[INFO] Surefire report directory:
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/target/surefire-reports
------------------------------------------------------T E S T S
------------------------------------------------------Running com.acme.corp.tracker.extension.SubsystemBaseParsingTestCase
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.424 sec
Running com.acme.corp.tracker.extension.SubsystemParsingTestCase
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.074 sec
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[...]
We will talk about these later in the Testing the parsers section.
WildFly 9
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:com.acme.corp.tracker:1.0"
xmlns="urn:com.acme.corp.tracker:1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.0">
<!-- The subsystem root element -->
<xs:element name="subsystem" type="subsystemType"/>
<xs:complexType name="subsystemType">
<xs:all>
<xs:element name="deployment-types" type="deployment-typesType"/>
</xs:all>
</xs:complexType>
<xs:complexType name="deployment-typesType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="deployment-type" type="deployment-typeType"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="deployment-typeType">
<xs:attribute name="suffix" use="required"/>
<xs:attribute name="tick" type="xs:long" use="optional" default="10000"/>
</xs:complexType>
</xs:schema>
WildFly 9
<subsystem xmlns="urn:com.acme.corp.tracker:1.0">
<deployment-types>
<deployment-type suffix="sar" tick="10000"/>
<deployment-type suffix="war" tick="10000"/>
</deployment-types>
</subsystem>
Now when designing our model, we can either do a one to one mapping between the schema and the model
or come up with something slightly or very different. To keep things simple, let us stay pretty true to the
schema so that when executing a :read-resource(recursive=true) against our subsystem we'll see
something like:
{
"outcome" => "success",
"result" => {"type" => {
"sar" => {"tick" => "10000"},
"war" => {"tick" => "10000"}
}}
}
Each deployment-type in the xml becomes in the model a child resource of the subsystem's root
resource. The child resource's child-type is type, and it is indexed by its suffix. Each type resource then
contains the tick attribute.
We also need a name for our subsystem, to do that change
com.acme.corp.tracker.extension.SubsystemExtension:
WildFly 9
@Override
public void initialize(ExtensionContext context) {
//register subsystem with its model version
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0);
//register subsystem model with subsystem definition that defines all attributes and
operations
final ManagementResourceRegistration registration =
subsystem.registerSubsystemModel(SubsystemDefinition.INSTANCE);
//register describe operation, note that this can be also registered in
SubsystemDefinition
registration.registerOperationHandler(DESCRIBE,
GenericSubsystemDescribeHandler.INSTANCE, GenericSubsystemDescribeHandler.INSTANCE, false,
OperationEntry.EntryType.PRIVATE);
//we can register additional submodels here
//
subsystem.registerXMLElementWriter(parser);
}
The registerSubsystem() call registers our subsystem with the extension context. At the end of the
method we register our parser with the returned SubsystemRegistration to be able to marshal our
subsystem's model back to the main configuration file when it is modified. We will add more functionality to
this method later.
It's parameter is an implementation of the ResourceDefinition interface, which means that when you call
/subsystem=tracker:read-resource-description the information you see comes from model that
is defined by SubsystemDefinition.INSTANCE.
WildFly 9
WildFly 9
There are two way to define DescriptionProvider, one is by defining it by hand using ModelNode, but as this
has show to be very error prone there are lots of helper methods to help you automatically describe the
model. Flowing example is done by manually defining Description provider for ADD operation handler
/**
* Used to create the description of the subsystem add method
*/
public static DescriptionProvider SUBSYSTEM_ADD = new DescriptionProvider() {
public ModelNode getModelDescription(Locale locale) {
//The locale is passed in so you can internationalize the strings used in the
descriptions
final ModelNode subsystem = new ModelNode();
subsystem.get(OPERATION_NAME).set(ADD);
subsystem.get(DESCRIPTION).set("Adds the tracker subsystem");
return subsystem;
}
};
Or you can use API that helps you do that for you. For Add and Remove methods there are classes
DefaultResourceAddDescriptionProvider and DefaultResourceRemoveDescriptionProvider that do work for
you. In case you use SimpleResourceDefinition even that part is hidden from you.
resourceRegistration.registerOperationHandler(ADD, SubsystemAdd.INSTANCE, new
DefaultResourceAddDescriptionProvider(resourceRegistration,descriptionResolver), false);
resourceRegistration.registerOperationHandler(REMOVE, SubsystemRemove.INSTANCE, new
DefaultResourceRemoveDescriptionProvider(resourceRegistration,descriptionResolver), false);
For other operation handlers that are not add/remove you can use DefaultOperationDescriptionProvider that
takes additional parameter of what is the name of operation and optional array of parameters/attributes
operation takes. This is an example to register operation "add-mime" with two parameters:
container.registerOperationHandler("add-mime",
MimeMappingAdd.INSTANCE,
new DefaultOperationDescriptionProvider("add-mime",
Extension.getResourceDescriptionResolver("container.mime-mapping"), MIME_NAME, MIME_VALUE));
When descriping an operation its description provider's OPERATION_NAME must match the name
used when calling ManagementResourceRegistration.registerOperationHandler()
Next we have the actual operation handler instance, note that we have changed its populateModel()
method to initialize the type child of the model.
WildFly 9
SubsystemAdd also has a performBoottime() method which is used for initializing the deployer chain
associated with this subsystem. We will talk about the deployers later on. However, the basic idea for all
operation handlers is that we do any model updates before changing the actual runtime state.
The rule of thumb is that every thing that can be added, can also be removed so we have a remove handler
for the subsystem registered
in SubsystemDefinition.registerOperations or just provide the operation handler in constructor.
The description provider for the remove operation is simple and quite similar to that of the add handler where
just name of the method changes.
WildFly 9
Then we define subsystem model. Lets call it TypeDefinition and for ease of use let it extend
SimpleResourceDefinition instead just implement ResourceDefinition.
WildFly 9
Which will take care of describing the model for us. As you can see in example above we define
SimpleAttributeDefinition named TICK, this is a mechanism to define Attributes in more type safe way and to
add more common API to manipulate attributes. As you can see here we define default value of 1000 as
also other constraints and capabilities. There could be other properties set such as validators, alternate
names, xml name, flags for marking it attribute allows expressions and more.
Then we do the work of updating the model by implementing the populateModel() method from the
AbstractAddStepHandler, which populates the model's attribute from the operation parameters. First we
get hold of the model relative to the address of this operation (we will see later that we will register it against
/subsystem=tracker/type=*), so we just specify an empty relative address, and we then populate our
model with the parameters from the operation. There is operation validateAndSet on AttributeDefinition that
helps us validate and set the model based on definition of the attribute.
@Override
protected void populateModel(ModelNode operation, ModelNode model) throws
OperationFailedException {
TICK.validateAndSet(operation,model);
}
We then override the performRuntime() method to perform our runtime changes, which in this case
involves installing a service into the controller at the heart of WildFly 8. (
AbstractAddStepHandler.performRuntime() is similar to
AbstractBoottimeAddStepHandler.performBoottime() in that the model is updated before runtime
changes are made.
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode
model,
ServiceVerificationHandler verificationHandler, List<ServiceController<?>>
newControllers)
throws OperationFailedException {
String suffix =
PathAddress.pathAddress(operation.get(ModelDescriptionConstants.ADDRESS)).getLastElement().getValue();
long tick = TICK.resolveModelAttribute(context,model).asLong();
TrackerService service = new TrackerService(suffix, tick);
ServiceName name = TrackerService.createServiceName(suffix);
ServiceController<TrackerService> controller = context.getServiceTarget()
.addService(name, service)
.addListener(verificationHandler)
.setInitialMode(Mode.ACTIVE)
.install();
newControllers.add(controller);
}
}
WildFly 9
The tracker service is quite simple. All services installed into WildFly 8 must implement the
org.jboss.msc.service.Service interface.
We then have some fields to keep the tick count and a thread which when run outputs all the deployments
registered with our service.
Next we have three methods which come from the Service interface. getValue() returns this service,
start() is called when the service is started by the controller, stop is called when the service is stopped
by the controller, and they start and stop the thread outputting the deployments.
WildFly 9
@Override
public TrackerService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}
@Override
public void start(StartContext context) throws StartException {
OUTPUT.start();
}
@Override
public void stop(StopContext context) {
OUTPUT.interrupt();
}
Next we have a utility method to create the ServiceName which is used to register the service in the
controller.
Finally we have some methods to add and remove deployments, and to set and read the tick. The 'cool'
deployments will be explained later.
WildFly 9
Since we are able to add type children, we need a way to be able to remove them, so we create a
com.acme.corp.tracker.extension.TypeRemoveHandler. In this case we extend
AbstractRemoveStepHandler which takes care of removing the resource from the model so we don't
need to override its performRemove() operationa. But we need to implement the
DescriptionProvider method to provide the model description, and since the add handler installs the
TrackerService, we need to remove that in the performRuntime() method.
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode
model) throws OperationFailedException {
String suffix =
PathAddress.pathAddress(operation.get(ModelDescriptionConstants.ADDRESS)).getLastElement().getValue();
ServiceName name = TrackerService.createServiceName(suffix);
context.removeService(name);
}
}
We then need a description provider for the type part of the model itself, so we modify TypeDefinitnion to
registerAttribute
class TypeDefinition{
...
@Override
public void registerAttributes(ManagementResourceRegistration resourceRegistration){
resourceRegistration.registerReadWriteAttribute(TICK, null, TrackerTickHandler.INSTANCE);
}
}
Then finally we need to specify that our new type child and associated handlers go under
/subsystem=tracker/type=* in the model by adding registering it with the model in
SubsystemExtension.initialize(). So we add the following just before the end of the method.
WildFly 9
@Override
public void initialize(ExtensionContext context)
{
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0);
final ManagementResourceRegistration registration =
subsystem.registerSubsystemModel(TrackerSubsystemDefinition.INSTANCE);
//Add the type child
ManagementResourceRegistration typeChild =
registration.registerSubModel(TypeDefinition.INSTANCE);
subsystem.registerXMLElementWriter(parser);
}
The above first creates a child of our main subsystem registration for the relative address type=*, and gets
the typeChild registration.
To this we add the TypeAddHandler and TypeRemoveHandler.
The add variety is added under the name add and the remove handler under the name remove, and for
each registered operation handler we use the handler singleton instance as both the handler parameter and
as the DescriptionProvider.
Finally, we register tick as a read/write attribute, the null parameter means we don't do anything special
with regards to reading it, for the write handler we supply it with an operation handler called
TrackerTickHandler.
Registering it as a read/write attribute means we can use the :write-attribute operation to modify the
value of the parameter, and it will be handled by TrackerTickHandler.
Not registering a write attribute handler makes the attribute read only.
TrackerTickHandler extends AbstractWriteAttributeHandler
directly, and so must implement its applyUpdateToRuntime and revertUpdateToRuntime method.
This takes care of model manipulation (validation, setting) but leaves us to do just to deal with what we need
to do.
WildFly 9
When implementing execute(), you must call context.completeStep() when you are done.
WildFly 9
We then need to write the parser. The contract is that we read our subsystem's xml and create the
operations that will populate the model with the state contained in the xml. These operations will then be
executed on our behalf as part of the parsing process. The entry point is the readElement() method.
WildFly 9
throw ParseUtils.unexpectedElement(reader);
}
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.isStartElement()) {
readDeploymentType(reader, list);
}
}
}
}
private void readDeploymentType(XMLExtendedStreamReader reader, List<ModelNode> list)
throws XMLStreamException {
if (!reader.getLocalName().equals("deployment-type")) {
throw ParseUtils.unexpectedElement(reader);
}
ModelNode addTypeOperation = new ModelNode();
addTypeOperation.get(OP).set(ModelDescriptionConstants.ADD);
String suffix = null;
for (int i = 0; i < reader.getAttributeCount(); i++) {
String attr = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (attr.equals("tick")) {
TypeDefinition.TICK.parseAndSetParameter(value, addTypeOperation, reader);
} else if (attr.equals("suffix")) {
suffix = value;
} else {
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
ParseUtils.requireNoContent(reader);
if (suffix == null) {
throw ParseUtils.missingRequiredElement(reader,
Collections.singleton("suffix"));
}
//Add the 'add' operation for each 'type' child
PathAddress addr = PathAddress.pathAddress(SUBSYSTEM_PATH,
PathElement.pathElement(TYPE, suffix));
addTypeOperation.get(OP_ADDR).set(addr.toModelNode());
list.add(addTypeOperation);
}
...
So in the above we always create the add operation for our subsystem. Due to its address
/subsystem=tracker defined by SUBSYSTEM_PATH this will trigger the SubsystemAddHandler we
created earlier when we invoke /subsystem=tracker:add. We then parse the child elements and create
an add operation for the child address for each type child. Since the address will for example be
/subsystem=tracker/type=sar (defined by TYPE_PATH ) and TypeAddHandler is registered for all
type subaddresses the TypeAddHandler will get invoked for those operations. Note that when we are
parsing attribute tick we are using definition of attribute that we defined in TypeDefintion to parse attribute
value and apply all rules that we specified for this attribute, this also enables us to property support
expressions on attributes.
WildFly 9
The parser is also used to marshal the model to xml whenever something modifies the model, for which the
entry point is the writeContent() method:
Then we have to implement the SubsystemDescribeHandler which translates the current state of the
model into operations similar to the ones created by the parser. The SubsystemDescribeHandler is only
used when running in a managed domain, and is used when the host controller queries the domain controller
for the configuration of the profile used to start up each server. In our case the
SubsystemDescribeHandler adds the operation to add the subsystem and then adds the operation to
add each type child. Since we are using ResourceDefinitinon for defining subsystem all that is generated
for us, but if you want to customize that you can do it by implementing it like this.
WildFly 9
WildFly 9
Now that we have modified our parsers we need to update our tests to reflect the new model. There are
currently three tests testing the basic functionality, something which is a lot easier to debug from your IDE
before you plug it into the application server. We will talk about these tests in turn and they all live in
com.acme.corp.tracker.extension.SubsystemParsingTestCase.
SubsystemParsingTestCase extends AbstractSubsystemTest which does a lot of the setup for you
and contains utility methods for verifying things from your test. See the javadoc of that class for more
information about the functionality available to you. And by all means feel free to add more tests for your
subsystem, here we are only testing for the best case scenario while you will probably want to throw in a few
tests for edge cases.
The first test we need to modify is testParseSubsystem(). It tests that the parsed xml becomes the
expected operations that will be parsed into the server, so let us tweak this test to match our subsystem.
First we tell the test to parse the xml into operations
@Test
public void testParseSubsystem() throws Exception {
//Parse the subsystem xml into operations
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
<deployment-type suffix=\"tst\" tick=\"12345\"/>" +
"
</deployment-types>" +
"</subsystem>";
List<ModelNode> operations = super.parse(subsystemXml);
There should be one operation for adding the subsystem itself and an operation for adding the
deployment-type, so check we got two operations
Now check that the first operation is add for the address /subsystem=tracker:
Then check that the second operation is add for the address /subsystem=tracker, and that 12345 was
picked up for the value of the tick parameter:
WildFly 9
The second test we need to modify is testInstallIntoController() which tests that the xml installs
properly into the controller. In other words we are making sure that the add operations we created earlier
work properly. First we create the xml and install it into the controller. Behind the scenes this will parse the
xml into operations as we saw in the last test, but it will also create a new controller and boot that up using
the created operations
@Test
public void testInstallIntoController() throws Exception {
//Parse the subsystem xml and install into the controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
<deployment-type suffix=\"tst\" tick=\"12345\"/>" +
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
The returned KernelServices allow us to execute operations on the controller, and to read the whole
model.
Now we make sure that the structure of the model within the controller has the expected format and values
WildFly 9
Assert.assertTrue(model.get(SUBSYSTEM).hasDefined(SubsystemExtension.SUBSYSTEM_NAME));
Assert.assertTrue(model.get(SUBSYSTEM,
SubsystemExtension.SUBSYSTEM_NAME).hasDefined("type"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type").hasDefined("tst"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME, "type",
"tst").hasDefined("tick"));
Assert.assertEquals(12345, model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type", "tst", "tick").asLong());
}
The last test provided is called testParseAndMarshalModel(). It's main purpose is to make sure that
our SubsystemParser.writeContent() works as expected. This is achieved by starting a controller in
the same way as before
@Test
public void testParseAndMarshalModel() throws Exception {
//Parse the subsystem xml and install into the first controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices servicesA = super.installInController(subsystemXml);
Now we read the model and the xml that was persisted from the first controller, and use that xml to start a
second controller
//Get the model and the persisted xml from the first controller
ModelNode modelA = servicesA.readWholeModel();
String marshalled = servicesA.getPersistedSubsystemXml();
//Install the persisted xml from the first controller into a second controller
KernelServices servicesB = super.installInController(marshalled);
Finally we read the model from the second controller, and make sure that the models are identical by calling
compare() on the test superclass.
We then have a test that needs no changing from what the archetype provides us with. As we have seen
before we start a controller
WildFly 9
@Test
public void testDescribeHandler() throws Exception {
//Parse the subsystem xml and install into the first controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"</subsystem>";
KernelServices servicesA = super.installInController(subsystemXml);
//Get the model and the describe operations from the first controller
ModelNode modelA = servicesA.readWholeModel();
ModelNode describeOp = new ModelNode();
describeOp.get(OP).set(DESCRIBE);
describeOp.get(OP_ADDR).set(
PathAddress.pathAddress(
PathElement.pathElement(SUBSYSTEM,
SubsystemExtension.SUBSYSTEM_NAME)).toModelNode());
List<ModelNode> operations =
super.checkResultAndGetContents(servicesA.executeOperation(describeOp)).asList();
//Install the describe options from the first controller into a second controller
KernelServices servicesB = super.installInController(operations);
And then we read the model from the second controller and make sure that the two subsystems are identical
ModelNode modelB = servicesB.readWholeModel();
//Make sure the models from the two controllers are identical
super.compare(modelA, modelB);
}
To test the removal of the the subsystem and child resources we modify the testSubsystemRemoval()
test provided by the archetype:
/**
* Tests that the subsystem can be removed
*/
@Test
public void testSubsystemRemoval() throws Exception {
//Parse the subsystem xml and install into the first controller
We provide xml for the subsystem installing a child, which in turn installs a TrackerService
WildFly 9
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
Having installed the xml into the controller we make sure the TrackerService is there
This call from the subsystem test harness will call remove for each level in our subsystem, children first and
validate
that the subsystem model is empty at the end.
Finally we check that all the services were removed by the remove handlers
//Check that any services that were installed were removed here
try {
services.getContainer().getRequiredService(TrackerService.createServiceName("tst"));
Assert.fail("Should have removed services");
} catch (Exception expected) {
}
}
For good measure let us throw in another test which adds a deployment-type and also changes its
attribute at runtime. So first of all boot up the controller with the same xml we have been using so far
@Test
public void testExecuteOperations() throws Exception {
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
Now create an operation which does the same as the following CLI command
/subsystem=tracker/type=foo:add(tick=1000)
WildFly 9
Read the whole model and make sure that the original data is still there (i.e. the same as what was done by
testInstallIntoController()
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type").hasDefined("foo"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME, "type",
"foo").hasDefined("tick"));
Assert.assertEquals(1000, model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type", "foo", "tick").asLong());
//Call write-attribute
ModelNode writeOp = new ModelNode();
writeOp.get(OP).set(WRITE_ATTRIBUTE_OPERATION);
writeOp.get(OP_ADDR).set(fooTypeAddr.toModelNode());
writeOp.get(NAME).set("tick");
writeOp.get(VALUE).set(3456);
result = services.executeOperation(writeOp);
Assert.assertEquals(SUCCESS, result.get(OUTCOME).asString());
WildFly 9
To give you exposure to other ways of doing things, now instead of reading the whole model to check the
attribute, we call read-attribute instead, and make sure it has the value we set it to.
//Check that write attribute took effect, this time by calling read-attribute instead of reading
the whole model
ModelNode readOp = new ModelNode();
readOp.get(OP).set(READ_ATTRIBUTE_OPERATION);
readOp.get(OP_ADDR).set(fooTypeAddr.toModelNode());
readOp.get(NAME).set("tick");
result = services.executeOperation(readOp);
Assert.assertEquals(3456, checkResultAndGetContents(result).asLong());
Since each type installs its own copy of TrackerService, we get the TrackerService for type=foo
from the service container exposed by the kernel services and make sure it has the right value
TrackerService service =
(TrackerService)services.getContainer().getService(TrackerService.createServiceName("foo")).getValue();
Assert.assertEquals(3456, service.getTick());
}
TypeDefinition.TICK.
@Override
public void performBoottime(OperationContext context, ModelNode operation, ModelNode model,
ServiceVerificationHandler verificationHandler, List<ServiceController<?>>
newControllers)
throws OperationFailedException {
log.info("Populating the model");
//Add deployment processors here
//Remove this if you don't need to hook into the deployers, or you can add as many as
you like
//see SubDeploymentProcessor for explanation of the phases
context.addStep(new AbstractDeploymentChainStep() {
public void execute(DeploymentProcessorTarget processorTarget) {
processorTarget.addDeploymentProcessor(SubsystemDeploymentProcessor.PHASE,
SubsystemDeploymentProcessor.priority, new SubsystemDeploymentProcessor());
}
}, OperationContext.Stage.RUNTIME);
}
WildFly 9
This adds an extra step which is responsible for installing deployment processors. You can add as many as
you like, or avoid adding any all together depending on your needs. Each processor has a Phase and a
priority. Phases are sequential, and a deployment passes through each phases deployment processors.
The priority specifies where within a phase the processor appears. See
org.jboss.as.server.deployment.Phase for more information about phases.
In our case we are keeping it simple and staying with one deployment processor with the phase and priority
created for us by the maven archetype. The phases will be explained in the next section. The deployment
processor is as follows:
WildFly 9
The deploy() method is called when a deployment is being deployed. In this case we look for the
TrackerService instance for the service name created from the deployment's suffix. If there is one it
means that we are meant to be tracking deployments with this suffix (i.e. TypeAddHandler was called for
this suffix), and if we find one we add the deployment's name to it. Similarly undeploy() is called when a
deployment is being undeployed, and if there is a TrackerService instance for the deployment's suffix,
we remove the deployment's name from it.
WildFly 9
STRUCTURE
The deployment unit processors in this phase determine the structure of a deployment, and looks for sub
deployments and metadata files.
PARSE
In this phase the deployment unit processors parse the deployment descriptors and build up the annotation
index. Class-Path entries from the META-INF/MANIFEST.MF are added.
DEPENDENCIES
Extra class path dependencies are added. For example if deploying a war file, the commonly needed
dependencies for a web application are added.
CONFIGURE_MODULE
In this phase the modular class loader for the deployment is created. No attempt should be made loading
classes from the deployment until after this phase.
POST_MODULE
Now that our class loader has been constructed we have access to the classes. In this stage deployment
processors may use the Attachments.REFLECTION_INDEX attachment which is a deployment index
used to obtain members of classes in the deployment, and to invoke upon them, bypassing the inefficiencies
of using java.lang.reflect directly.
INSTALL
Install new services coming from the deployment.
CLEANUP
Attachments put in place earlier in the deployment unit processor chain may be removed here.
WildFly 9
11.3.7 Expressions
Expressions are mechanism that enables you to support variables in your attributes, for instance when you
want the value of attribute to be resolved using system / environment properties.
An example expression is
${jboss.bind.address.management:127.0.0.1}
which means that the value should be taken from a system property named
jboss.bind.address.management and if it is not defined use 127.0.0.1.
${expression_to_resolve}
WildFly 9
SimpleAttributeDefinition MY_ATTRIBUTE =
new SimpleAttributeDefinitionBuilder("my-attribute", ModelType.INT, true)
.setAllowExpression(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setDefaultValue(new ModelNode(1))
.build();
Then later when you are parsing the xml configuration you should use the MY_ATTRIBUTE attribute
definition to set the value to the management operation ModelNode you are creating.
....
String attr = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (attr.equals("my-attribute")) {
MY_ATTRIBUTE.parseAndSetParameter(value, operation, reader);
} else if (attr.equals("suffix")) {
.....
Note that this just helps you to properly set the value to the model node you are working on, so no need to
additionally set anything to the model for this attribute. Method parseAndSetParameter parses the value that
was read from xml for possible expressions in it and if it finds any it creates special model node that defines
that node is of type ModelType.EXPRESSION.
Later in your operation handlers where you implement populateModel and have to store the value from the
operation to the configuration model you also use this MY_ATTRIBUTE attribute definition.
@Override
protected void populateModel(ModelNode operation, ModelNode model) throws
OperationFailedException {
MY_ATTRIBUTE.validateAndSet(operation,model);
}
This will make sure that the attribute that is stored from the operation to the model is valid and nothing is
lost. It also checks the value stored in the operation ModelNode, and if it isn't already
ModelType.EXPRESSION, it checks if the value is a string that contains the expression syntax. If so, the
value stored in the model will be of type ModelType.EXPRESSION. Doing this ensures that expressions are
properly handled when they appear in operations that weren't created by the subsystem parser, but are
instead passed in from CLI or admin console users.
As last step we need to use the value of the attribute. This is usually needed inside of the performRuntime
method
WildFly 9
As you can see resolving of attribute's value is not done until it is needed for use in the subsystem's runtime
services. The resolved value is not stored in the configuration model, the unresolved expression is. That way
we do not lose any information in the model and can assure that also marshalling is done properly, where we
must marshall back the unresolved value.
Attribute definitinon also helps you with that:
WildFly 9
WildFly 9
ResourceDescriptionResolver
TODO
Most commonly used implementation: StandardResourceDescriptionResolver
WildFly 9
WildFly 9
WildFly 9
How do I write a transformer?
ResourceTransformationDescriptionBuilder
Silently discard child resources
Reject child resource
Redirect address for child resource
Getting a child resource builder
AttributeTransformationDescriptionBuilder
Attribute transformation lifecycle
Discarding attributes
The DiscardAttributeChecker interface
DiscardAttributeChecker helper classes/implementations
DiscardAttributeChecker.DefaultDiscardAttributeChecker
DiscardAttributeChecker.DiscardAttributeValueChecker
DiscardAttributeChecker.ALWAYS
DiscardAttributeChecker.UNDEFINED
Rejecting attributes
The RejectAttributeChecker interface
RejectAttributeChecker helper classes/implementations
RejectAttributeChecker.DefaultRejectAttributeChecker
RejectAttributeChecker.DEFINED
RejectAttributeChecker.SIMPLE_EXPRESSIONS
RejectAttributeChecker.ListRejectAttributeChecker
RejectAttributeChecker.ObjectFieldsRejectAttributeChecker
Converting attributes
The AttributeConverter interface
Introducing attributes during transformation
Renaming attributes
OperationTransformationOverrideBuilder
Evolving transformers with subsystem ModelVersions
Testing a configuration that works
Testing a configuration that does not work
Common transformation use-cases
Child resource type does not exist in legacy model
Attribute does not exist in the legacy subsystem
Default value of the attribute is the same as legacy implied behaviour
Default value of the attribute is different from legacy implied behaviour
Attribute has a different default value
Attribute has a different type
WildFly 9
11.6.1 "Abstract"
A WildFly/JBoss AS 7 domain may consist of a new Domain Controller (DC) controlling slave Host
Controllers (HC) running older versions. Each slave HC maintains a copy of the centralized domain
configuration, which they use for controlling their own servers. In order for the slave HCs to understand the
configuration from the DC, transformation is needed, whereby the DC translates the configuration and
operations into something the slave HCs can understand.
11.6.2 Background
WildFly comes with a domain mode which allows you to have one Host Controller acting as the Domain
Controller. The Domain Controller's job is to maintain the centralized domain configuration. Another term for
the DC is 'Master Host Controller'. Before explaining why transformers are important and when they should
be used, we will revisit how the domain configuration is used in domain mode.
The centralized domain configuration is stored in domain.xml. This is only ever parsed on the DC, and it
has the following structure:
extensions - contains:
extension - a references to a module that bootstraps the
org.jboss.as.controller.Extension implementation used to bootstrap your
subsystem parsers and initialize the resource definitions for your subsystems.
profiles - contains:
profile - a named set of:
subsystem - contains the configuration for a subsystem, using the parser initialized by
the subsystem's extension.
socket-binding-groups - contains:
socket-binding-group - a named set of:
socket-binding - A named port on an interface which can be referenced from the
subsystem configurations for subsystems opening sockets.
server-groups - contains
server-group - this has a name and references a profile and a
socket-binding-group. The HCs then reference the server-group name from their
<servers> section in host.xml.
When the DC parses domain.xml, it is transformed into add (and in some cases write-attribute)
operations just as explained in Parsing and marshalling of the subsystem xml. These operations build up the
model on the DC.
WildFly 9
A HC wishing to join the domain and use the DC's centralized configuration is known as a 'slave HC'. A slave
HC maintains a copy of the DC's centralized domain configuration. This copy of the domain configuration is
used to start its servers. This is done by asking the domain model to describe itself, which in turn asks the
subsystems to describe themselves. The describe operation for a subsystem looks at the state of the
subsystem model and produces the add operations necessary to create the subsystem on the server. The
same mechanism also takes place on the DC (bear in mind that the DC is also a HC, which can have its own
servers), although of course its copy of the domain configuration is the centralized one.
There are two steps involved in keeping the keeping the slave HC's domain configuration in sync with the
centralized domain configuration.
getting the initial domain model
an operation changes something in the domain configuration
Let's look a bit closer at what happens in each of these steps.
WildFly 9
[{
"domain-resource-address" => [],
"domain-resource-model" => {
"management-major-version" => 2,
"management-minor-version" => 0,
"management-micro-version" => 0,
"release-version" => "8.0.0.Beta1-SNAPSHOT",
"release-codename" => "WildFly"
}
},
{
"domain-resource-address" => [("extension" => "org.jboss.as.clustering.infinispan")],
"domain-resource-model" => {"module" => "org.jboss.as.clustering.infinispan"}
},
--SNIP - the rest of the extensions -{
"domain-resource-address" => [("extension" => "org.jboss.as.weld")],
"domain-resource-model" => {"module" => "org.jboss.as.weld"}
},
{
"domain-resource-address" => [("system-property" => "java.net.preferIPv4Stack")],
"domain-resource-model" => {
"value" => "true",
"boot-time" => undefined
}
},
{
"domain-resource-address" => [("profile" => "full-ha")],
"domain-resource-model" => undefined
},
{
"domain-resource-address" => [
("profile" => "full-ha"),
("subsystem" => "logging")
],
"domain-resource-model" => {}
},
{
"domain-resource-address" => [sss|WFLY8:Example subsystem],
"domain-resource-model" => {
"level" => "INFO",
"enabled" => undefined,
"encoding" => undefined,
"formatter" => "%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n",
"filter-spec" => undefined,
"autoflush" => undefined,
"target" => undefined,
"named-formatter" => undefined
}
},
--SNIP---
The slave HC then applies these one at a time and builds up the initial domain model. It needs to do this
before it can start any of its servers.
WildFly 9
[disconnected /] connect
[domain@localhost:9990 /]
/profile=full/subsystem=datasources/data-source=ExampleDS:write-attribute(name=enabled,value=false){
"outcome" => "success",
"result" => undefined,
"server-groups" => {"main-server-group" => {"host" => {
"slave" => {"server-one" => {"response" => {
"outcome" => "success",
"result" => undefined,
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}}},
"master" => {
"server-one" => {"response" => {
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}},
"server-two" => {"response" => {
"outcome" => "success",
"response-headers" => {
"operation-requires-restart" => true,
"process-state" => "restart-required"
}
}}
}
}}}
}
the DC propagates the changes to itself host=master, which in turn propagates it to its two servers
belonging to main-server-group which uses the full profile. More interestingly, it also propagates it to
host=slave which updates its local copy of the domain model, and then propagates the change to its
server-one which belongs to main-server-group which uses the full profile.
WildFly 9
Important
A Doman Controller should be able to manage slave Host Controllers older than itself.
This means that for example a WildFly 8 DC should be able to work with slave HCs running JBoss AS 7.1.2.
The opposite is not true, the DC must be the same or the newest version in the domain.
Versioning of subsystems
To help with being able to know what is compatible we have versions within the subsystems, this is stored in
the subsystem's extension. When registering the subsystem you will typically see something like:
WildFly 9
Important
Whenever something changes in the subsystem, such as:
an attribute is added or removed from a resource
a attribute is renamed in a resource
an attribute has its type changed
an attribute or operation parameter's nillable or allows expressions is changed
an attribute or operation parameter's default value changes
a child resource type is added or removed
an operation is added or removed
an operation has its parameters changed
and the current version of the subsystem has been part of a Final release of WildFly, we must
bump the version of the subsystem.
Once it has been increased you can of course make more changes until the next Final release without more
version bumps. It is also worth noting that a new WildFly release does not automatically mean a new version
for the subsystem, the new version is only needed if something was changed. For example the jaxrs
subsystem has remained on 1.0.0 for all versions of WildFly and JBoss AS 7.
You can find the ModelVersion of a subsystem by querying its extension:
domain@localhost:9990 /]
/extension=org.jboss.as.clustering.infinispan:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {
"module" => "org.jboss.as.clustering.infinispan",
"subsystem" => {"infinispan" => {
"management-major-version" => 2,
"management-micro-version" => 0,
"management-minor-version" => 0,
"xml-namespaces" => [jboss:domain:infinispan:1.0",
"urn:jboss:domain:infinispan:1.1",
"urn:jboss:domain:infinispan:1.2",
"urn:jboss:domain:infinispan:1.3",
"urn:jboss:domain:infinispan:1.4",
"urn:jboss:domain:infinispan:2.0"]
}}
}
}
WildFly 9
{
"description" => "The configuration of the weld subsystem.",
"attributes" => {},
"operations" => {
"remove" => {
"operation-name" => "remove",
"description" => "Operation removing the weld subsystem.",
"request-properties" => {},
"reply-properties" => {}
},
"add" => {
"operation-name" => "add",
"description" => "Operation creating the weld subsystem.",
"request-properties" => {},
"reply-properties" => {}
}
},
"children" => {}
},
WildFly 9
In WildFly 8, it has a ModelVersion of 2.0.0 and has added two attributes, require-bean-descriptor
and non-portable mode:
{
"description" => "The configuration of the weld subsystem.",
"attributes" => {
"require-bean-descriptor" => {
"type" => BOOLEAN,
"description" => "If true then implicit bean archives without bean descriptor
file (beans.xml) are ignored by Weld",
"expressions-allowed" => true,
"nillable" => true,
"default" => false,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
},
"non-portable-mode" => {
"type" => BOOLEAN,
"description" => "If true then the non-portable mode is enabled. The
non-portable mode is suggested by the specification to overcome problems with legacy
applications that do not use CDI SPI properly and may be rejected by more strict validation in
CDI 1.1.",
"expressions-allowed" => true,
"nillable" => true,
"default" => false,
"access-type" => "read-write",
"storage" => "configuration",
"restart-required" => "no-services"
}
},
"operations" => {
"remove" => {
"operation-name" => "remove",
"description" => "Operation removing the weld subsystem.",
"request-properties" => {},
"reply-properties" => {}
},
"add" => {
"operation-name" => "add",
"description" => "Operation creating the weld subsystem.",
"request-properties" => {
"require-bean-descriptor" => {
"type" => BOOLEAN,
"description" => "If true then implicit bean archives without bean
descriptor file (beans.xml) are ignored by Weld",
"expressions-allowed" => true,
"required" => false,
"nillable" => true,
"default" => false
},
"non-portable-mode" => {
"type" => BOOLEAN,
"description" => "If true then the non-portable mode is enabled. The
non-portable mode is suggested by the specification to overcome problems with legacy
applications that do not use CDI SPI properly and may be rejected by more strict validation in
WildFly 9
CDI 1.1.",
"expressions-allowed" => true,
"required" => false,
"nillable" => true,
"default" => false
}
},
"reply-properties" => {}
}
},
"children" => {}
}
In the rest of this section we will assume that we are running a DC running WildFly 8 so it will have
ModelVersion 2.0.0 of the weld subsystem, and that we are running a slave using ModelVersion 1.0.0 of the
weld subsystem.
Important
Transformation always takes place on the Domain Controller, and is done when sending across the
initial domain model AND forwarding on operations to legacy slave HCs.
WildFly 9
Resource transformers
When copying over the centralized domain configuration as mentioned in Getting the initial domain model,
we need to make sure that the copy of the domain model is something that the servers running on the legacy
slave HC understand. So if the centralized domain configuration had any of the two new attributes set, we
would need to reject the transformation in the transformers. One reason for this is to keep things consistent,
it doesn't look good if you connect to the slave HC and find attributes and/or child resources when doing
:read-resource which are not there when you do :read-resource-description. Also, to make life
easier for subsystem writers, most instances of the describe operation use a standard implementation
which would include these attributes when creating the add operation for the server, which could cause
problems there.
Another, more concrete example from the logging subsystem is that it allows a ' %K{...}' in the pattern
formatter which makes the formatter use colour:
This '%K{...}' however was introduced in JBoss AS < 7.1.3 (ModelVersion 1.2.0), so if that makes it across
to a slave HC running an older version, the servers will fail to start up. So the logging extension registers
transformers to strip out the '%K{...}' from the attribute value (leaving '%-5p %c (%t) %s%E%n"') so that
the old slave HC's servers can understand it.
WildFly 9
Operation transformers
When An operation changes something in the domain configuration the operation gets sent across to the
slave HCs to update their domain models. The slave HCs then forward this operation onto the affected
servers. The same considerations as in Resource transformers are true, although operation transformers
give you quicker 'feedback' if something is not valid. If you try to execute:
/profile=full/subsystem=weld:write-attribute(name=require-bean-descriptor, value=false)
This will fail on the legacy slave HC since its version of the subsystem does not contain any such attribute.
However, it is best to aggressively reject in such cases.
<subsystem xmlns="urn:jboss:domain:weld:2.0"
require-bean-descriptor="true"
non-portable-mode="true"/>
We will see the exact mechanics for how this is actually done later but in short when pushing this to a legacy
slave DC we register transformers which reject the transformation if these attributes are not set to true
since that implies some behaviour not supported on the legacy slave DC. If they are true, all is well, and
the transformers discard, or remove, these attributes since they don't exist in the legacy model. This removal
is fine since they have the values which would result in the behaviour assumed on the legacy slave HC.
WildFly 9
That way the older slave HCs will work fine. However, we might also have WildFly 8 slave HCs in our
domain, and they are missing out on the new features introduced by the attributes introduced in
ModelVersion 2.0.0. If we do
<subsystem xmlns="urn:jboss:domain:weld:2.0"
require-bean-descriptor="false"
non-portable-mode="false"/>
then it will fail when doing transformation for the legacy controller. The solution is to put these in two different
profiles in domain.xml
<domain>
....
<profiles>
<profile name="full">
<subsystem xmlns="urn:jboss:domain:weld:2.0"
require-bean-descriptor="false"
non-portable-mode="false"/>
...
</profile>
<profile name="full-legacy">
<subsystem xmlns="urn:jboss:domain:weld:2.0"
require-bean-descriptor="true"
non-portable-mode="true"/>
...
</profile>
</profiles>
...
<server-groups>
<server-group name="main-server-group" profile="full">
....
<server-group>
<server-group name="main-server-group-legacy" profile="full-legacy">
....
<server-group>
</server-groups>
</domain>
Then have the HCs using WildFly 8 make their servers reference the main-server-group server group,
and the HCs using older versions of WildFly 8 make their servers reference the
main-server-group-legacy server group.
WildFly 9
Important
Any top-level resource type can be ignored profile, extension, server=group etc. Ignoring a
resource instance ignores that resource, and all its children.
WildFly 9
WildFly 9
So we can see that for the remoting subsystem, we have added a child type called http-connector,
and we have added an attribute called protocol (they are missing in legacy).
in the weld subsystem, we have added the require-bean-descriptor and non-portable-mode
attributes in the current version. It will also point out other issues like changed attribute types, changed
defaults etc.
WildFly 9
Warning
Note that CompareModelVersionsUtil simply inspects the raw resource descriptions of the specified
legacy and current models. Its results show the differences between the two. They do not take into
account whether one or more transformers have already been written for those versions
differences. You will need to check that transformers are not already in place for those versions.
One final point to consider are that some subsystems register runtime-only resources and operations. For
example the modcluster subsystem has a stop method. These do not get registered on the DC, e.g. there
is no /profile=full-ha/subsystem=modcluster:stop operation, it only exists on the servers, for
example /host=xxx/server=server-one/subsystem=modcluster:stop. What this means is that
you don't have to transform such operations and resources. The reason is they are not callable on the DC,
and so do not need propagation to the servers in the domain, which in turn means no transformation is
needed.
WildFly 9
registerRelayTransformers(stack);
}
Having implemented a number of transformers using the above approach, we decided to simplify things, so
we introduced the
org.jboss.as.controller.transform.description.ResourceTransformationDescriptionBuilder
API. It is a lot simpler and avoids a lot of the duplication of functionality required by the low-level API
approach. While it doesn't give you the full power that the low-level API does, we found that there are very
few places in the WildFly codebase where this does not work, so we will focus on the
ResourceTransformationDescriptionBuilder API here. (If you come across a problem where this
does not work, get in touch with someone from the WildFly Domain Management Team and we should be
able to help). The builder API makes all the nasty calls to TransformersSubRegistration for you under
the hood. It also allows you to fall back to the low-level API in places, although that will not be covered in the
current version of this guide. The entry point for using the builder API here is taken from the WeldExtension
(in current WildFly this has ModelVersion 2.0.0).
WildFly 9
Here we register a discard check and a reject check. As mentioned in Attribute transformation
lifecycle all attributes are inspected for whether they should be discarded first. Then all attributes which were
not discarded are checked for if they should be rejected. We will dig more into what this code means in the
next few sections, but in short it means that we discard the require-bean-descriptor and
non-portable attributes on the weld subsystem resource if they have the value true. If they have any
other value, they will not get discarded and so reach the reject check, which will reject the transformation of
the attributes if they have any other value.
Here we are saying that we should discard the require-bean-descriptor and non-portable-mode
attributes on the weld subsystem resource if they are undefined, and reject them if they are defined. So that
means that if the weld subsystem looks like
{
"non-portable-mode" => false,
"require-bean-descriptor" => false
}
WildFly 9
or
{
"non-portable-mode" => undefined,
"require-bean-descriptor" => undefined
}
or any other combination (the default values for these attributes if undefined is false) we will reject the
transformation for the slave legacy HC.
If the resource has true for these attributes:
{
"non-portable-mode" => true,
"require-bean-descriptor" => true
}
they both get discarded (i.e. removed), so they will not get inspected for rejection, and an empty model not
containing these attributes gets sent to the legacy HC.
Here we will discuss this API a bit more, to outline the most important features/most commonly needed
tasks.
ResourceTransformationDescriptionBuilder
The ResourceTransformationDescriptionBuilder contains transformations for a resource type. The
initial one is for the subsystem, obtained by the following call:
ResourceTransformationDescriptionBuilder subsystemBuilder =
TransformationDescriptionBuilder.Factory.createSubsystemInstance();
TransformationDescription.Tools.register(subsystemBuilder.build(), subsystem,
ModelVersion.create(1, 0, 0));
Important
If you have several old ModelVersions you could be transforming to, you need a separate builder
for each of those.
WildFly 9
subsystemBuilder.discardChildResource(PathElement.pathElement("child", "discarded"));
Warning
Note that discarding, although the simplest option in theory, is rarely the right thing to do.
The presence of the defined child normally implies some behaviour on the DC, and that behaviour is not
available on the legacy slave HC, so normally rejection is a better policy for those cases. Remember we can
have different profiles targeting different groups of versions of legacy slave HCs.
subsystemBuilder.rejectChildResource(PathElement.pathElement("child", "reject"));
Now, if there are any legacy slaves running ModelVersion 1.0.0, any usage of
/subsystem=my-subsystem/child=reject will get rejected for those slaves. Both during the initial
domain model transfer, and if any operations are invoked on that address. For example the remoting
subsystem did not have a http-connector=* child until ModelVersion 2.0.0, so it is set up to reject that
child when transforming to legacy HCs for all previous ModelVersions (1.1.0, 1.2.0 and 1.3.0). (See
Rejection in resource transformers and Rejection in operation transformers for exactly what happens when
something is rejected).
WildFly 9
ResourceTransformationDescriptionBuilder childBuilder =
subsystemBuilder.addChildRedirection(PathElement.pathElement("newChild"),
PathElement.pathElement("oldChild");
ResourceTransformationDescriptionBuilder childBuilder =
subsystemBuilder.addChildRedirection(PathElement.pathElement("newChild", "newName"),
PathElement.pathElement("oldChild", "oldName");
ResourceTransformationDescriptionBuilder childBuilder =
subsystemBuilder.addChildResource(PathElement.pathElement("some-child"));
//We don't actually want to transform anything in /subsystem-my-subsystem/some-child=*
either :-)
//We are interested in /subsystem-my-subsystem/some-child=*/another-level
ResourceTransformationDescriptionBuilder anotherBuilder =
childBuilder.addChildResource(PathElement.pathElement("another-level"));
//Use anotherBuilder to add child-resource and/or attribute transformation
....
WildFly 9
AttributeTransformationDescriptionBuilder
To transform attributes you call
ResourceTransformationDescriptionBuilder.getAttributeBuilder() which returns you a
AttributeTransformationDescriptionBuilder which is used to define transformation for the
resource's attributes. For example this gets the attribute builder for the subsystem resource:
AttributeTransformationDescriptionBuilder attributeBuilder =
subSystemBuilder.getAttributeBuilder();
ResourceTransformationDescriptionBuilder childBuilder =
subsystemBuilder.addChildResource(PathElement.pathElement("some-child"));
AttributeTransformationDescriptionBuilder attributeBuilder =
childBuilder.getAttributeBuilder();
/subsystem=my-subsystem/some-child=test:add(example=true)
/subsystem=my-subsystem:write-attribute(name=example, value=true)
/subsystem=my-subsystem:custom-operation(example=true)
The following operations will pass in this example, since the example attribute is not getting set to true
/subsystem=my-subsystem/some-child=test:add(example=false)
/subsystem=my-subsystem/some-child=test:add()
undefined
/subsystem=my-subsystem:write-attribute(name=example, value=false)
/subsystem=my-subsystem:undefine-attribute(name=example)
undefined
/subsystem=my-subsystem:custom-operation(example=false)
For the rest of the examples in this section we assume that the attributeBuilder is for
/subsystem=my-subsystem
WildFly 9
Discarding attributes
The general idea behind a discard is that we remove attributes which do not exist in the legacy slave HC's
model. However, as hopefully described below, we normally can't simply discard everything, we need to
check the values first.
To discard an attribute we need an instance of
org.jboss.as.controller.transform.description.DiscardAttributeChecker, and call the
following method on the AttributeTransformationDescriptionBuilder:
As shown, you can register the DiscardAttributeChecker for several attributes at once, in the above
example both attr1 and attr2 get checked for if they should be discarded. You can also register different
DiscardAttributeChecker instances for different attributes:
WildFly 9
Note that you can only have one DiscardAttributeChecker per attribute, so the following would cause
an error (if running with assertions enabled, otherwise discardCheckerB will overwrite
discardCheckerA):
Return true here to discard the attribute if it is an expression. If it is an expression, and this method returns
true, the isOperationParameterDiscardable and isResourceAttributeDiscardable methods
will not get called.
/**
* Returns {@code true} if the attribute should be discarded if it is undefined
*
* @return whether to discard if the attribute is undefined
*/
boolean isDiscardUndefined();
Return true here to discard the attribute if it is undefined. If it is undefined, and this method returns
true, the isDiscardExpressions, isOperationParameterDiscardable and
isResourceAttributeDiscardable methods will not get called.
WildFly 9
/**
* Gets whether the given operation parameter can be discarded
*
* @param address the address of the operation
* @param attributeName the name of the operation parameter.
* @param attributeValue the value of the operation parameter.
* @param operation the operation executed. This is unmodifiable.
* @param context the context of the transformation
*
* @return {@code true} if the operation parameter value should be discarded, {@code false}
otherwise.
*/
boolean isOperationParameterDiscardable(PathAddress address, String attributeName, ModelNode
attributeValue, ModelNode operation, TransformationContext context);
If we are transforming an operation, this method gets called for each operation parameter. We have access
to the address of the operation, the name and value of the operation parameter, an unmodifiable copy of the
original operation and the TransformationContext. The TransformationContext allows you access
to the original resource the operation is working on before any transformation happened, which is useful if
you want to check other values in the resource if this is, say a write-attribute operation. Return true
to discard the operation.
/**
* Gets whether the given attribute can be discarded
*
* @param address the address of the resource
* @param attributeName the name of the attribute
* @param attributeValue the value of the attribute
* @param context the context of the transformation
*
* @return {@code true} if the attribute value should be discarded, {@code false} otherwise.
*/
boolean isResourceAttributeDiscardable(PathAddress address, String attributeName, ModelNode
attributeValue, TransformationContext context);
If we are transforming a resource, this method gets called for each attribute in the resource. We have access
to the address of the resource, the name and value of the attribute, and the TransformationContext.
Return true to discard the operation.
WildFly 9
DiscardAttributeChecker.DefaultDiscardAttributeChecker
DiscardAttributeChecker.DefaultDiscardAttributeChecker is an abstract convenience class.
In most cases you don't need a separate check for if an operation or a resource is being transformed, so it
makes both the isResourceAttributeDiscardable() and
isOperationParameterDiscardable() methods call the following method.
All you loose, in the case of an operation transformation, is the name of the transformed operation. The
constructor of DiscardAttributeChecker.DefaultDiscardAttributeChecker also allows you to
define values for isDiscardExpressions() and isDiscardUndefined().
DiscardAttributeChecker.DiscardAttributeValueChecker
This is another convenience class, which allows you to discard an attribute if it has one or more values. Here
is a real-world example from the jpa subsystem:
We will come back to the reject checks in the Rejecting attributes section. We are saying that we should
discard the JPADefinition.DEFAULT_EXTENDEDPERSISTENCE_INHERITANCE attribute if it has the
value deep. The reasoning here is that this attribute did not exist in the old model, but the legacy slave HCs
implied behaviour is that this was deep. In the current version we added the possibility to toggle this setting,
but only deep is consistent with what is available in the legacy slave HC. In this case we are using the
constructor for DiscardAttributeChecker.DiscardAttributeValueChecker which says don't
discard if it uses expressions, and discard if it is undefined. If it is undefined in the current model,
looking at the default value of JPADefinition.DEFAULT_EXTENDEDPERSISTENCE_INHERITANCE, it is
deep, so a discard is in line with the implied legacy behaviour. If an expression is used, we cannot discard
since we have no idea what the expression will resolve to on the slave HC.
WildFly 9
DiscardAttributeChecker.ALWAYS
DiscardAttributeChecker.ALWAYS will always discard an attribute. Use this sparingly, since normally
the presence of an attribute in the current model implies some behaviour should be turned on, and if that
does not exist in the legacy model it implies that that behaviour does not exist in the legacy slave HC and its
servers. Normally the legacy slave HC's subsystem has some implied behaviour which is better checked for
by using a DiscardAttributeChecker.DiscardAttributeValueChecker. One valid use for
DiscardAttributeChecker.ALWAYS can be found in the ejb3 subsystem:
As the comment says, this attribute only makes sense with the security-manager susbsystem, which does
not exist on legacy slaves running ModelVersion 1.1.0 of the ejb3 subsystem.
DiscardAttributeChecker.UNDEFINED
DiscardAttributeChecker.UNDEFINED will discard an attribute if it is undefined. This is normally
safer than DiscardAttributeChecker.ALWAYS since the attribute is not set in the current model, we
don't need to send it to the legacy model. However, you should check that this attribute not existing in the
legacy slave HC, implies the same functionality as being undefined in the current DC.
Rejecting attributes
The next step is to check attributes and values which we know for sure will not work on the target legacy
slave HC.
To reject an attribute we need an instance of
org.jboss.as.controller.transform.description.RejectAttributeChecker, and call the
following method on the AttributeTransformationDescriptionBuilder:
As shown you can register the RejectAttributeChecker for several attributes at once, in the above
example both attr1 and attr2 get checked for if they should be discarded. You can also register different
RejectAttributeChecker instances for different attributes:
WildFly 9
You can also register several RejectAttributeChecker instances per attribute
In this case attr1 gets both rejectCheckerA and rejectCheckerB. For attributes with several
RejectAttributeChecker registered, they get processed in the order that they have been added. So
when checking attr1 for rejection, rejectCheckerA gets run before rejectCheckerB. As mentioned in
Attribute transformation lifecycle, if an attribute is rejected, we still invoke the rest of the reject checkers.
* @param attributeName
If we are transforming an operation, this method gets called for each operation parameter. We have access
to the address of the operation, the name and value of the operation parameter, an unmodifiable copy of the
original operation and the TransformationContext. The TransformationContext allows you access
to the original resource the operation is working on before any transformation happened, which is useful if
you want to check other values in the resource if this is, say a write-attribute operation. Return true
to reject the operation.
WildFly 9
/**
* Gets whether the given resource attribute value is not understandable by the target
process and needs
* to be rejected.
*
* @param address
* @param attributeName
If we are transforming a resource, this method gets called for each attribute in the resource. We have access
to the address of the resource, the name and value of the attribute, and the TransformationContext.
Return true to discard the operation.
/**
* Returns the log message id used by this checker. This is used to group it so that all
attributes failing a type of rejction
* end up in the same error message
*
* @return the log message id
*/
String getRejectionLogMessageId();
Here we need a unique id for the log message from the RejectAttributeChecker. It is used to group
rejected attributes by their log message. A typical implementation will contain {{return
getRejectionLogMessage(Collections.<String, ModelNode>emptyMap());}
/**
* Gets the log message if the attribute failed rejection
*
* @param attributes a map of all attributes failed in this checker and their values
* @return the formatted log message
*/
String getRejectionLogMessage(Map<String, ModelNode> attributes);
Here we return a message saying why the attributes were rejected, with the possiblity to format the message
to include the names of all the rejected attributes and the values they had.
WildFly 9
RejectAttributeChecker contains a few helper classes for the most common scenarios to save you
from writing the same stuff again and again.
RejectAttributeChecker.DefaultRejectAttributeChecker
RejectAttributeChecker.DefaultRejectAttributeChecker is an abstract convenience class. In
most cases you don't need a separate check for if an operation or a resource is being transformed, so it
makes both the rejectOperationParameter() and rejectResourceAttribute() methods call the
following method.
Like DefaultDiscardAttributeChecker, all you loose is the name of the transformed operation, in the
case of operation transformation.
RejectAttributeChecker.DEFINED
RejectAttributeChecker.DEFINED is used to reject any attribute that has a defined value. Normally
this is because the attribute does not exist on the target legacy slave HC. A typical use case for these is for
the implied behaviour example we looked at in the jpa subsystem in
DiscardAttributeChecker.DiscardAttributeValueChecker
Important
Reject and discard often work in pairs.
WildFly 9
RejectAttributeChecker.SIMPLE_EXPRESSIONS
RejectAttributeChecker.SIMPLE_EXPRESSIONS can be used to reject an attribute that contains
expressions. This was used a lot for transformations to subsystems in JBoss AS 7.1.x, since we had not fully
realized the importance of where to support expressions until JBoss AS 7.2.0 was released, so a lot of
attributes in earlier versions were missing expressions support.
RejectAttributeChecker.ListRejectAttributeChecker
The RejectAttributeChecker}}s we have seen so far work on simple attributes,
i.e. where the attribute has a ModelType which is one of the primitives. We also
have a {{RejectAttributeChecker.ListRejectAttributeChecker which allows you to define a
checker for the elements of a list, when the type of an attribute is ModelType.LIST.
attributeBuilder
.addRejectCheck(new ListRejectAttributeChecker(RejectAttributeChecker.EXPRESSIONS),
"attr1");
For attr1 it will check each element of the list and run RejectAttributeChecker.EXPRESSIONS to
check that each element is not an expression. You can of course pass in another kind of
RejectAttributeChecker to check the elements as well.
RejectAttributeChecker.ObjectFieldsRejectAttributeChecker
For attributes where the type is ModelType.OBJECT we have
RejectAttributeChecker.ObjectFieldsRejectAttributeChecker which allows you to register
different reject checkers for the different fields of the registered object.
Converting attributes
To convert an attribute you register an
org.jboss.as.controller.transform.description.AttributeConverter instance against the
attributes you want to convert:
WildFly 9
Now if attr1 and attr2 get converted with converterA, while attr3 gets converted with converterB.
If we are transforming an operation, this method gets called for each operation parameter for which the con.
We have access to the address of the operation, the name and value of the operation parameter, an
unmodifiable copy of the original operation and the TransformationContext. The
TransformationContext allows you access to the original resource the operation is working on before
any transformation happened, which is useful if you want to check other values in the resource if this is, say
a write-attribute operation. To change the attribute value, you modify the attributeValue.
/**
* Converts a resource attribute
*
* @param address the address of the operation
* @param attributeName the name of the attribute
* @param attributeValue the value of the attribute to be converted
* @param context the context of the transformation
*/
void convertResourceAttribute(PathAddress address, String attributeName, ModelNode
attributeValue, TransformationContext context);
If we are transforming a resource, this method gets called for each attribute in the resource. We have access
to the address of the resource, the name and value of the attribute, and the TransformationContext. To
change the attribute value, you modify the attributeValue.
A hypothetical example is if the current and legacy subsystems both contain an attribute called timeout. In
the legacy model this was specified to be milliseconds, however in the current model it has been changed to
be seconds, hence we need to convert the value when sending it to slave HCs using the legacy model:
WildFly 9
We need to be a bit careful here. If the timeout attribute is an expression our nice conversion will not work,
so we need to add a reject check to make sure it is not an expression as well:
attributeBuilder.
.addRejectCheck(SIMPLE_EXPRESSIONS, "timeout")
.setValueConverter(secondsToMs , "timeout")
WildFly 9
Introducing attributes during transformation
Say both the current and the legacy models have an attribute called port. In the legacy version this attribute
had to be specified, and the default xml configuration had 1234 for its value. In the current version this
attribute has been made optional with a default value of 1234 so that it does not need to be specified. When
transforming to a slave HC using the old version we will need to introduce this attribute if the new model
does not contain it:
attributeBuilder.
setValueConverter(AttributeConverter.Factory.createHardCoded(new ModelNode(1234) true),
"port");
Renaming attributes
To rename an attribute, you simply do
attributeBuilder.addRename("my-name", "legacy-name");
Now, in the initial domain transfer to the legacy slave HC, we rename /subsystem=my-subsystem's
my-name attribute to legacy-name. Also, the operations involving this attribute are affected, so
/subsystem=my-subsystem/:add(my-name=true)
->
/subsystem=my-subsystem/:add(legacy-name=true)
/subsystem=my-subsystem:write-attribute(name=my-name, value=true) ->
/subsystem=my-subsystem:write-attribute(name=legacy-name, value=true)
/subsystem=my-subsystem:undefine-attribute(name=my-name) ->
/subsystem=my-subsystem:undefine-attribute(name=legacy-name)
WildFly 9
OperationTransformationOverrideBuilder
All operations on a resource automatically get the same transformations on their parameters as set up by the
AttributeTransformationDescriptionBuilder. In some cases you might want to change this, so
you can use the OperationTransformationOverrideBuilder, which is got from:
OperationTransformationOverrideBuilder operationBuilder =
subSystemBuilder.addOperationTransformationOverride("some-operation");
In this case the operation will now no longer inherit the attribute/operation parameter transformations, so
they are effectively turned off. In other cases you might want to include them by calling
inheritResourceAttributeDefinitions(), and to include some more checks (the
OperationTransformationBuilder interface has all the methods found in
AttributeTransformationBuilder:
OperationTransformationOverrideBuilder operationBuilder =
subSystemBuilder.addOperationTransformationOverride("some-operation");
operationBuilder.inheritResourceAttributeDefinitions();
operationBuilder.setValueConverter(AttributeConverter.Factory.createHardCoded(new
ModelNode(1234) true), "port");
You can also rename operations, in this case the operation some-operation gets renamed to
legacy-operation before getting sent to the legacy slave HC.
OperationTransformationOverrideBuilder operationBuilder =
subSystemBuilder.addOperationTransformationOverride("some-operation");
operationBuilder.rename("legacy-operation");
WildFly 9
Now say we want to do a new version of the model. This new version contains a new attribute called
'new-attr' which cannot be defined when transforming to 1.1.0, we bump the model version to 2.0.0:
WildFly 9
Now we need some new transformers from the current ModelVersion to 1.1.0 where we reject any defined
occurrances of our new attribute new-attr:
So that is all well and good, however we also need to take into account that new-attr does not exist in
ModelVersion 1.0.0 either, so we need to extend our transformer for 1.0.0 to reject it there as well
WildFly 9
/**
* Registers transformers from the current version to ModelVersion 1.0.0
*/
private void registerTransformers_1_0_0(SubsystemRegistration subsystem) {
ResourceTransformationDescriptionBuilder builder =
TransformationDescriptionBuilder.Factory.createSubsystemInstance();
builder.getAttributeBuilder()
.addRejectCheck(RejectAttributeChecker.DEFINED, "attr1", "new-attr")
.end();
TransformationDescription.Tools.register(builder.build(), subsystem,
ModelVersion.create(1, 0, 0));
}
}
Now new-attr will be rejected if defined for all previous model versions.
It has been pointed out that this approach does not really scale as the number of old versions
increases, https://issues.jboss.org/browse/WFLY-2512 is a suggestion to only need to implement
transformers for each version delta
To test transformation you need to extend
org.jboss.as.subsystem.test.AbstractSubsystemTest or
org.jboss.as.subsystem.test.AbstractSubsystemBaseTest. Then, in order to have the best test
coverage possible, you should test the fullest configuration that will work, and you should also test
configurations that don't work if you have rejecting transformers registered. The following example is from
the threads subsystem, and I have only included the tests against 7.1.2 - there are more! First we need to
set up our test:
So we say that this test is for the threads subsystem, and that it is implemented by ThreadsExtension.
This is the same test framework as we use in Example subsystem#Testing the parsers, but we will only talk
about the parts relevant to transformers here.
WildFly 9
@Test
public void testTransformerAS712() throws Exception {
testTransformer_1_0(ModelTestControllerVersion.V7_1_2_FINAL);
}
/**
* Tests transformation of model from 1.1.0 version into 1.0.0 version.
*
* @throws Exception
*/
private void testTransformer_1_0(ModelTestControllerVersion controllerVersion) throws
Exception {
String subsystemXml = "threads-transform-1_0.xml";
understood by 1.0
ModelVersion modelVersion = ModelVersion.create(1, 0, 0); //The old model version
//Use the non-runtime version of the extension which will happen on the HC
KernelServicesBuilder builder =
createKernelServicesBuilder(AdditionalInitialization.MANAGEMENT)
.setSubsystemXmlResource(subsystemXml);
final PathAddress subsystemAddress =
PathAddress.pathAddress(PathElement.pathElement(SUBSYSTEM, mainSubsystemName));
// Add legacy subsystems
builder.createLegacyKernelServicesBuilder(null, controllerVersion, modelVersion)
.addOperationValidationResolve("add",
subsystemAddress.append(PathElement.pathElement("thread-factory")))
.addMavenResourceURL("org.jboss.as:jboss-as-threads:" +
controllerVersion.getMavenGavVersion())
.excludeFromParent(SingleClassFilter.createFilter(ThreadsLogger.class));
KernelServices mainServices = builder.build();
KernelServices legacyServices = mainServices.getLegacyServices(modelVersion);
Assert.assertNotNull(legacyServices);
checkSubsystemModelTransformation(mainServices, modelVersion);
}
What this test does is get the builder to configure the test controller using threads-transform-1_0.xml.
This main builder works with the current subsystem version, and the jars in the WildFly checkout.
Next we configure a 'legacy' controller. This will run the version of the core libraries (e.g the controller
module) as found in the targeted legacy version of JBoss AS/Wildfly), and the subsystem. We need to pass
in that it is using the core AS version 7.1.2.Final (i.e. the
ModelTestControllerVersion.V7_1_2_FINAL part) and that that version is ModelVersion 1.0.0. Next
we have some addMavenResourceURL() calls passing in the Maven GAVs of the old version of the
subsystem and any dependencies it has needed to boot up. Normally, specifying just the Maven GAV of the
old version of the subsystem is enough, but that depends on your subsystem. In this case the old subsystem
GAV is enough. When booting up the legacy controller the framework uses the parsed operations from the
main controller and transforms them using the 1.0.0 transformer in the threads subsystem. The
addOperationValidationResolve() and excludeFromParent() calls are not normally necessary,
see the javadoc for more examples.
WildFly 9
The call to KernelServicesBuilder.build() will build both the main controller and the legacy
controller. As part of that it also boots up a second copy of the main controller using the transformed
operations to make sure that the 'old' ops to boot our subsystem will still work on the current controller, which
is important for backwards compatibility of CLI scripts. To tweak how that is done if you see failures there,
see LegacyKernelServicesInitializer.skipReverseControllerCheck() and
LegacyKernelServicesInitializer.configureReverseControllerCheck(). The
LegacyKernelServicesInitializer is what gets returned by
KernelServicesBuilder.createLegacyKernelServicesBuilder().
Finally we call checkSubsystemModelTransformation() which reads the full legacy subsystem model.
The legacy subsystem model will have been built up from the transformed boot operations from the parsed
xml. The operations get transformed by the operation transformers. Then it takes the model of the current
subsystem and transforms that using the resource transformers. Then it compares the two models, which
should be the same. In some rare cases it is not possible to get those two models exactly the same, so there
is a version of this method that takes a ModelFixer to make adjustments. The
checkSubsystemModelTransformation() method also makes sure that the legacy model is valid
according to the legacy subsystem's resource definition. These legacy subsystem resource defintion's are
stored in subsystem-test/framework/src/main/resources/org/jboss/as/subsystem/test
and the file names are <your-subsystem-name>-<legacy-version>.dmr. If this file does
not exist, you need to generate it by adding a temporary test (make sure that
you adjust {{controllerVersion and modelVersion to what you want to generate):
@Test
public void deleteMeWhenDone() throws Exception {
ModelTestControllerVersion controllerVersion = ModelTestControllerVersion.V7_1_2_FINAL;
ModelVersion modelVersion = ModelVersion.create(1, 0, 0);
KernelServicesBuilder builder = createKernelServicesBuilder(null);
builder.createLegacyKernelServicesBuilder(null, controllerVersion, modelVersion)
.addMavenResourceURL("org.jboss.as:jboss-as-threads:" +
controllerVersion.getMavenGavVersion());
KernelServices services = builder.build();
generateLegacySubsystemResourceRegistrationDmr(services, modelVersion);
}
Now run the test and delete it. The legacy .dmr file should be in
target/test-classes/org/jboss/as/subsystem/test/<your-subsystem-name>-<your-version>.dmr
. Copy this .dmr file to
subsystem-test/framework/src/main/resources/org/jboss/as/subsystem/test. You will
likely also need to update org.jboss.as.subsystem.test.KnownVersions to include your latest
legacy subsystem version, once you start doing real testing.
WildFly 9
@Test
public void testRejectExpressionsAS712() throws Exception {
testRejectExpressions_1_0_0(ModelTestControllerVersion.V7_1_2_FINAL);
}
private void testRejectExpressions_1_0_0(ModelTestControllerVersion controllerVersion)
throws Exception {
// create builder for current subsystem version
KernelServicesBuilder builder =
createKernelServicesBuilder(createAdditionalInitialization());
// create builder for legacy subsystem version
ModelVersion version_1_0_0 = ModelVersion.create(1, 0, 0);
builder.createLegacyKernelServicesBuilder(null, controllerVersion, version_1_0_0)
.addMavenResourceURL("org.jboss.as:jboss-as-threads:" +
controllerVersion.getMavenGavVersion())
.excludeFromParent(SingleClassFilter.createFilter(ThreadsLogger.class));
KernelServices mainServices = builder.build();
KernelServices legacyServices = mainServices.getLegacyServices(version_1_0_0);
Assert.assertNotNull(legacyServices);
Assert.assertTrue("main services did not boot", mainServices.isSuccessfulBoot());
Assert.assertTrue(legacyServices.isSuccessfulBoot());
List<ModelNode> xmlOps = builder.parseXmlResource("expressions.xml");
ModelTestUtils.checkFailedTransformedBootOperations(mainServices, version_1_0_0, xmlOps,
getConfig());
}
Again we boot up a current and a legacy controller. However, note in this case that they are both empty, no
xml was parsed on boot so there are no operations to boot up the model. Instead once the controllers have
been booted, we call KernelServicesBuilder.parseXmlResource() which gets the operations from
expressions.xml. expressions.xml uses expressions in all the places they were not allowed in
7.1.2.Final. For each resource ModelTestUtils.checkFailedTransformedBootOperations() will
check that the add operation gets rejected, and then correct one attribute at a time until the resource has
been totally corrected. Once the add operation is totally correct, it will check that the add operation no longer
is rejected. The configuration for this is the FailedOperationTransformationConfig returned by the
getConfig() method:
WildFly 9
.addFailedAttribute(subsystemAddress.append(PathElement.pathElement(CommonAttributes.BLOCKING_BOUNDED_QUEUE_TH
allowedAndKeepalive)
.addFailedAttribute(subsystemAddress.append(PathElement.pathElement(CommonAttributes.BOUNDED_QUEUE_THREAD_POOL
allowedAndKeepalive)
}
So what this means is that we expect the allow-core-timeout and keepalive-time attributes for the
blocking-bounded-queue-thread-pool=* and bounded-queue-thread-pool=* add operations to
use expressions in the parsed xml. We then expect them to fail since there should be transformers in place
to reject expressions, and correct them one at a time until the add operation should pass. As well as doing
the add operations the ModelTestUtils.checkFailedTransformedBootOperations() method will
also try calling write-attribute for each attribute, correcting as it goes along. As well as allowing you to
test rejection of expressions FailedOperationTransformationConfig also has some helper classes
to help testing rejection of other scenarios.
WildFly 9
====== Resource root address: ["subsystem" => "remoting"] - Current version: 2.0.0; legacy
version: 1.2.0 =======
--- Problems for relative address to root []:
Missing child types in current: []; missing in legacy [http-connector]
So our current model has added a child type called http-connector which was not there in 7.2.0. This is
configurable, and adds new behaviour, so it can not be part of a configuration sent across to a legacy slave
running version 1.2.0. So we add the following to RemotingExtension to reject all instances of that child
type against ModelVersion 1.2.0.
@Override
public void initialize(ExtensionContext context) {
....
if (context.isRegisterTransformers()) {
registerTransformers_1_1(registration);
registerTransformers_1_2(registration);
}
}
private void registerTransformers_1_2(SubsystemRegistration registration) {
TransformationDescription.Tools.register(get1_2_0_1_3_0Description(), registration,
VERSION_1_2);
}
private static TransformationDescription get1_2_0_1_3_0Description() {
ResourceTransformationDescriptionBuilder builder =
ResourceTransformationDescriptionBuilder.Factory.createSubsystemInstance();
builder.rejectChildResource(HttpConnectorResource.PATH);
return builder.build();
}
Since this child resource type also does not exist in ModelVersion 1.1.0 we need to reject it there as well
using a similar mechanism.
WildFly 9
====== Resource root address: ["subsystem" => "remoting"] - Current version: 2.0.0; legacy
version: 1.2.0 =======
--- Problems for relative address to root []:
....
--- Problems for relative address to root ["remote-outbound-connection" => "*"]:
Missing attributes in current: []; missing in legacy [protocol]
Missing parameters for operation 'add' in current: []; missing in legacy [protocol]
This difference also affects the add operation. Looking at the current model the valid values for the
protocol attribute are remote, http-remoting and https-remoting. The last two are new protocols
introduced in WildFly 8, meaning that the implied behaviour in JBoss 7.2.0 and earlier is the remote
protocol. Since this attribute does not exist in the legacy model we want to discard this attribute if it is
undefined or if it has the value remote, both of which are in line with what the legacy slave HC is
hardwired to use. Also we want to reject it if it has a value different from remote. So what we need to do
when registering transformers against ModelVersion 1.2.0 to handle this attribute:
WildFly 9
The reject check remains the same, but we have implemented the discard check by using
DiscardAttributeChecker.DefaultDiscardAttributeChecker instead. However, the effect of the
discard check is exactly the same as when we used
DiscardAttributeChecker.DiscardAttributeValueChecker.
====== Resource root address: ["subsystem" => "weld"] - Current version: 2.0.0; legacy version:
1.0.0 =======
--- Problems for relative address to root []:
Missing attributes in current: []; missing in legacy [require-bean-descriptor,
non-portable-mode]
Missing parameters for operation 'add' in current: []; missing in legacy
[require-bean-descriptor, non-portable-mode]
Now when we look at this we see that the default value for both of the attributes in the current model is
false, which allows us more flexible behaviour introduced in CDI 1.1 (which was introduced with this
version of the subsystem). The old model does not have these attributes, and implements CDI 1.0, which
under the hood (using our weld subsystem expertise knowledge) implies the values true for both of these.
So our transformer must reject anything that is not true for these attributes. Let us look at the transformer
registered by the WeldExtension:
WildFly 9
This looks a bit more scary than the previous transformer we have seen, but isn't actually too bad. The first
thing we do is register a DiscardAttributeChecker.DiscardAttributeValueChecker which will
discard the attribute if it has the value true. It will not discard if it is undefined since that defaults to
false. This is registered for both attributes.
If the attributes had the value true they will get discarded we will not hit the reject checker since discarded
attributes never get checked for rejection. If on the other hand they were an expression (since we are
interested in the actual value, but cannot evaluate what value an expression will resolve to on the target from
the DC running the transformers), false, or undefined (which will then default to false) they will not get
discarded and will need to be rejected. So our
RejectAttributeChecker.DefaultRejectAttributeChecker.rejectAttribute() method will
return true (i.e. reject) if the attribute value is undefined (since that defaults to false) or if it is defined
and 'not equal to true'. It is better to check for 'not equal to true' than to check for 'equal to false' since if
an expression was used we still want to reject, and only the 'not equal to true' check would actually kick in
in that case.
WildFly 9
The other thing we need in our DiscardAttributeChecker.DiscardAttributeValueChecker is to
override the getRejectionLogMessage() method to get the message to be displayed when rejecting the
transformation. In this case it says something along the lines "These attributes must be 'true' for use with
CDI 1.0 '%s'", with the names of the attributes having been rejected substituting the %s.
====== Resource root address: ["subsystem" => "modcluster"] - Current version: 2.0.0; legacy
version: 1.2.0 =======
...
--- Problems for relative address to root ["mod-cluster-config" =>
"configuration","dynamic-load-provider" => "configuration","custom-load-m
etric" => "*"]:
Different 'type' for attribute 'capacity'. Current: DOUBLE; legacy: INT
Different 'expressions-allowed' for attribute 'capacity'. Current: true; legacy: false
...
Different 'type' for parameter 'capacity' of operation 'add'. Current: DOUBLE; legacy: INT
Different 'expressions-allowed' for parameter 'capacity' of operation 'add'. Current: true;
legacy: false
So as we can see expressions are not allowed for the capacity attribute, and the current type is double
while the legacy subsystem is int. So this means that if the value is for example 2.0 we can convert this to
2, but 2.5 cannot be converted. The way this is solved in the ModClusterExtension is to register the
following some other attributes are registered here, but hopefully it is clear anyway:
dynamicLoadProvider.addChildResource(LOAD_METRIC_PATH)
.getAttributeBuilder()
.addRejectCheck(RejectAttributeChecker.SIMPLE_EXPRESSIONS, TYPE, WEIGHT,
CAPACITY, PROPERTY)
.addRejectCheck(CapacityCheckerAndConverter.INSTANCE, CAPACITY)
.setValueConverter(CapacityCheckerAndConverter.INSTANCE, CAPACITY)
...
.end();
WildFly 9
@Override
protected boolean isValueDiscardable(PathAddress address, String attributeName,
ModelNode attributeValue, TransformationContext context) {
//Not used for discard
return false;
}
@Override
public String getRejectionLogMessage(Map<String, ModelNode> attributes) {
return
ModClusterMessages.MESSAGES.capacityIsExpressionOrGreaterThanIntegerMaxValue(attributes.get(CAPACITY.getName()
}
Now we check to see if we can convert the attribute to an int and reject if not. Note that if it is an
expression, we have no idea what its value will resolve to on the target host, so we need to reject it. Then we
try to change it into an int, and reject if that was not possible:
@Override
protected boolean rejectAttribute(PathAddress address, String attributeName, ModelNode
attributeValue, TransformationContext context) {
if (checkForExpression(attributeValue)
|| (attributeValue.isDefined() &&
!isIntegerValue(attributeValue.asDouble()))) {
return true;
}
Long converted = convert(attributeValue);
return (converted != null && (converted > Integer.MAX_VALUE || converted <
Integer.MIN_VALUE));
}
WildFly 9
@Override
protected void convertAttribute(PathAddress address, String attributeName, ModelNode
attributeValue, TransformationContext context) {
Long converted = convert(attributeValue);
if (converted != null && converted <= Integer.MAX_VALUE && converted >=
Integer.MIN_VALUE) {
attributeValue.set((int)converted.longValue());
}
}
mvn archetype:generate \
-DarchetypeArtifactId=wildfly-subsystem \
-DarchetypeGroupId=org.wildfly.archetypes \
-DarchetypeVersion=8.0.0.Final \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
Maven will download the archetype and it's dependencies, and ask you some questions:
WildFly 9
$ mvn archetype:generate \
-DarchetypeArtifactId=wildfly-subsystem \
-DarchetypeGroupId=org.wildfly.archetypes \
-DarchetypeVersion=8.0.0.Final \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------------------------------------------------[INFO] Building Maven Stub Project (No POM) 1
[INFO] -----------------------------------------------------------------------[INFO]
.........
Define value for property 'groupId': : com.acme.corp
Define value for property 'artifactId': : acme-subsystem
Define value for property 'version': 1.0-SNAPSHOT: :
Define value for property 'package':
com.acme.corp: : com.acme.corp.tracker
Instruction
1 Enter the groupId you wish to use
2 Enter the artifactId you wish to use
3 Enter the version you wish to use, or just hit Enter if you wish to accept the default 1.0-SNAPSHOT
4 Enter the java package you wish to use, or just hit Enter if you wish to accept the default (which is
copied from groupId ).
5 Enter the module name you wish to use for your extension.
6 Finally, if you are happy with your choices, hit Enter and Maven will generate the project for you.
WildFly 9
You can also do this in Eclipse, see Creating your own application for more details. We now have a skeleton
project that you can use to implement a subsystem. Import the acme-subsystem project into your favourite
IDE. A nice side-effect of running this in the IDE is that you can see the javadoc of WildFly classes and
interfaces imported by the skeleton code. If you do a mvn install in the project it will work if we plug it into
WildFly 8, but before doing that we will change it to do something more useful.
The rest of this section modifies the skeleton project created by the archetype to do something more useful,
and the full code can be found in acme-subsystem.zip.
If you do a mvn install in the created project, you will see some tests being run
$mvn install
[INFO] Scanning for projects...
[...]
[INFO] Surefire report directory:
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/target/surefire-reports
------------------------------------------------------T E S T S
------------------------------------------------------Running com.acme.corp.tracker.extension.SubsystemBaseParsingTestCase
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.424 sec
Running com.acme.corp.tracker.extension.SubsystemParsingTestCase
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.074 sec
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[...]
We will talk about these later in the Testing the parsers section.
WildFly 9
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:com.acme.corp.tracker:1.0"
xmlns="urn:com.acme.corp.tracker:1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.0">
<!-- The subsystem root element -->
<xs:element name="subsystem" type="subsystemType"/>
<xs:complexType name="subsystemType">
<xs:all>
<xs:element name="deployment-types" type="deployment-typesType"/>
</xs:all>
</xs:complexType>
<xs:complexType name="deployment-typesType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="deployment-type" type="deployment-typeType"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="deployment-typeType">
<xs:attribute name="suffix" use="required"/>
<xs:attribute name="tick" type="xs:long" use="optional" default="10000"/>
</xs:complexType>
</xs:schema>
WildFly 9
<subsystem xmlns="urn:com.acme.corp.tracker:1.0">
<deployment-types>
<deployment-type suffix="sar" tick="10000"/>
<deployment-type suffix="war" tick="10000"/>
</deployment-types>
</subsystem>
Now when designing our model, we can either do a one to one mapping between the schema and the model
or come up with something slightly or very different. To keep things simple, let us stay pretty true to the
schema so that when executing a :read-resource(recursive=true) against our subsystem we'll see
something like:
{
"outcome" => "success",
"result" => {"type" => {
"sar" => {"tick" => "10000"},
"war" => {"tick" => "10000"}
}}
}
Each deployment-type in the xml becomes in the model a child resource of the subsystem's root
resource. The child resource's child-type is type, and it is indexed by its suffix. Each type resource then
contains the tick attribute.
We also need a name for our subsystem, to do that change
com.acme.corp.tracker.extension.SubsystemExtension:
WildFly 9
@Override
public void initialize(ExtensionContext context) {
//register subsystem with its model version
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0);
//register subsystem model with subsystem definition that defines all attributes and
operations
final ManagementResourceRegistration registration =
subsystem.registerSubsystemModel(SubsystemDefinition.INSTANCE);
//register describe operation, note that this can be also registered in
SubsystemDefinition
registration.registerOperationHandler(DESCRIBE,
GenericSubsystemDescribeHandler.INSTANCE, GenericSubsystemDescribeHandler.INSTANCE, false,
OperationEntry.EntryType.PRIVATE);
//we can register additional submodels here
//
subsystem.registerXMLElementWriter(parser);
}
The registerSubsystem() call registers our subsystem with the extension context. At the end of the
method we register our parser with the returned SubsystemRegistration to be able to marshal our
subsystem's model back to the main configuration file when it is modified. We will add more functionality to
this method later.
It's parameter is an implementation of the ResourceDefinition interface, which means that when you call
/subsystem=tracker:read-resource-description the information you see comes from model that
is defined by SubsystemDefinition.INSTANCE.
WildFly 9
WildFly 9
There are two way to define DescriptionProvider, one is by defining it by hand using ModelNode, but as this
has show to be very error prone there are lots of helper methods to help you automatically describe the
model. Flowing example is done by manually defining Description provider for ADD operation handler
/**
* Used to create the description of the subsystem add method
*/
public static DescriptionProvider SUBSYSTEM_ADD = new DescriptionProvider() {
public ModelNode getModelDescription(Locale locale) {
//The locale is passed in so you can internationalize the strings used in the
descriptions
final ModelNode subsystem = new ModelNode();
subsystem.get(OPERATION_NAME).set(ADD);
subsystem.get(DESCRIPTION).set("Adds the tracker subsystem");
return subsystem;
}
};
Or you can use API that helps you do that for you. For Add and Remove methods there are classes
DefaultResourceAddDescriptionProvider and DefaultResourceRemoveDescriptionProvider that do work for
you. In case you use SimpleResourceDefinition even that part is hidden from you.
resourceRegistration.registerOperationHandler(ADD, SubsystemAdd.INSTANCE, new
DefaultResourceAddDescriptionProvider(resourceRegistration,descriptionResolver), false);
resourceRegistration.registerOperationHandler(REMOVE, SubsystemRemove.INSTANCE, new
DefaultResourceRemoveDescriptionProvider(resourceRegistration,descriptionResolver), false);
For other operation handlers that are not add/remove you can use DefaultOperationDescriptionProvider that
takes additional parameter of what is the name of operation and optional array of parameters/attributes
operation takes. This is an example to register operation "add-mime" with two parameters:
container.registerOperationHandler("add-mime",
MimeMappingAdd.INSTANCE,
new DefaultOperationDescriptionProvider("add-mime",
Extension.getResourceDescriptionResolver("container.mime-mapping"), MIME_NAME, MIME_VALUE));
When descriping an operation its description provider's OPERATION_NAME must match the name
used when calling ManagementResourceRegistration.registerOperationHandler()
Next we have the actual operation handler instance, note that we have changed its populateModel()
method to initialize the type child of the model.
WildFly 9
SubsystemAdd also has a performBoottime() method which is used for initializing the deployer chain
associated with this subsystem. We will talk about the deployers later on. However, the basic idea for all
operation handlers is that we do any model updates before changing the actual runtime state.
The rule of thumb is that every thing that can be added, can also be removed so we have a remove handler
for the subsystem registered
in SubsystemDefinition.registerOperations or just provide the operation handler in constructor.
The description provider for the remove operation is simple and quite similar to that of the add handler where
just name of the method changes.
WildFly 9
Then we define subsystem model. Lets call it TypeDefinition and for ease of use let it extend
SimpleResourceDefinition instead just implement ResourceDefinition.
WildFly 9
Which will take care of describing the model for us. As you can see in example above we define
SimpleAttributeDefinition named TICK, this is a mechanism to define Attributes in more type safe way and to
add more common API to manipulate attributes. As you can see here we define default value of 1000 as
also other constraints and capabilities. There could be other properties set such as validators, alternate
names, xml name, flags for marking it attribute allows expressions and more.
Then we do the work of updating the model by implementing the populateModel() method from the
AbstractAddStepHandler, which populates the model's attribute from the operation parameters. First we
get hold of the model relative to the address of this operation (we will see later that we will register it against
/subsystem=tracker/type=*), so we just specify an empty relative address, and we then populate our
model with the parameters from the operation. There is operation validateAndSet on AttributeDefinition that
helps us validate and set the model based on definition of the attribute.
@Override
protected void populateModel(ModelNode operation, ModelNode model) throws
OperationFailedException {
TICK.validateAndSet(operation,model);
}
We then override the performRuntime() method to perform our runtime changes, which in this case
involves installing a service into the controller at the heart of WildFly 8. (
AbstractAddStepHandler.performRuntime() is similar to
AbstractBoottimeAddStepHandler.performBoottime() in that the model is updated before runtime
changes are made.
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode
model,
ServiceVerificationHandler verificationHandler, List<ServiceController<?>>
newControllers)
throws OperationFailedException {
String suffix =
PathAddress.pathAddress(operation.get(ModelDescriptionConstants.ADDRESS)).getLastElement().getValue();
long tick = TICK.resolveModelAttribute(context,model).asLong();
TrackerService service = new TrackerService(suffix, tick);
ServiceName name = TrackerService.createServiceName(suffix);
ServiceController<TrackerService> controller = context.getServiceTarget()
.addService(name, service)
.addListener(verificationHandler)
.setInitialMode(Mode.ACTIVE)
.install();
newControllers.add(controller);
}
}
WildFly 9
The tracker service is quite simple. All services installed into WildFly 8 must implement the
org.jboss.msc.service.Service interface.
We then have some fields to keep the tick count and a thread which when run outputs all the deployments
registered with our service.
Next we have three methods which come from the Service interface. getValue() returns this service,
start() is called when the service is started by the controller, stop is called when the service is stopped
by the controller, and they start and stop the thread outputting the deployments.
WildFly 9
@Override
public TrackerService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}
@Override
public void start(StartContext context) throws StartException {
OUTPUT.start();
}
@Override
public void stop(StopContext context) {
OUTPUT.interrupt();
}
Next we have a utility method to create the ServiceName which is used to register the service in the
controller.
Finally we have some methods to add and remove deployments, and to set and read the tick. The 'cool'
deployments will be explained later.
WildFly 9
Since we are able to add type children, we need a way to be able to remove them, so we create a
com.acme.corp.tracker.extension.TypeRemoveHandler. In this case we extend
AbstractRemoveStepHandler which takes care of removing the resource from the model so we don't
need to override its performRemove() operationa. But we need to implement the
DescriptionProvider method to provide the model description, and since the add handler installs the
TrackerService, we need to remove that in the performRuntime() method.
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode
model) throws OperationFailedException {
String suffix =
PathAddress.pathAddress(operation.get(ModelDescriptionConstants.ADDRESS)).getLastElement().getValue();
ServiceName name = TrackerService.createServiceName(suffix);
context.removeService(name);
}
}
We then need a description provider for the type part of the model itself, so we modify TypeDefinitnion to
registerAttribute
class TypeDefinition{
...
@Override
public void registerAttributes(ManagementResourceRegistration resourceRegistration){
resourceRegistration.registerReadWriteAttribute(TICK, null, TrackerTickHandler.INSTANCE);
}
}
Then finally we need to specify that our new type child and associated handlers go under
/subsystem=tracker/type=* in the model by adding registering it with the model in
SubsystemExtension.initialize(). So we add the following just before the end of the method.
WildFly 9
@Override
public void initialize(ExtensionContext context)
{
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0);
final ManagementResourceRegistration registration =
subsystem.registerSubsystemModel(TrackerSubsystemDefinition.INSTANCE);
//Add the type child
ManagementResourceRegistration typeChild =
registration.registerSubModel(TypeDefinition.INSTANCE);
subsystem.registerXMLElementWriter(parser);
}
The above first creates a child of our main subsystem registration for the relative address type=*, and gets
the typeChild registration.
To this we add the TypeAddHandler and TypeRemoveHandler.
The add variety is added under the name add and the remove handler under the name remove, and for
each registered operation handler we use the handler singleton instance as both the handler parameter and
as the DescriptionProvider.
Finally, we register tick as a read/write attribute, the null parameter means we don't do anything special
with regards to reading it, for the write handler we supply it with an operation handler called
TrackerTickHandler.
Registering it as a read/write attribute means we can use the :write-attribute operation to modify the
value of the parameter, and it will be handled by TrackerTickHandler.
Not registering a write attribute handler makes the attribute read only.
TrackerTickHandler extends AbstractWriteAttributeHandler
directly, and so must implement its applyUpdateToRuntime and revertUpdateToRuntime method.
This takes care of model manipulation (validation, setting) but leaves us to do just to deal with what we need
to do.
WildFly 9
When implementing execute(), you must call context.completeStep() when you are done.
WildFly 9
We then need to write the parser. The contract is that we read our subsystem's xml and create the
operations that will populate the model with the state contained in the xml. These operations will then be
executed on our behalf as part of the parsing process. The entry point is the readElement() method.
WildFly 9
throw ParseUtils.unexpectedElement(reader);
}
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.isStartElement()) {
readDeploymentType(reader, list);
}
}
}
}
private void readDeploymentType(XMLExtendedStreamReader reader, List<ModelNode> list)
throws XMLStreamException {
if (!reader.getLocalName().equals("deployment-type")) {
throw ParseUtils.unexpectedElement(reader);
}
ModelNode addTypeOperation = new ModelNode();
addTypeOperation.get(OP).set(ModelDescriptionConstants.ADD);
String suffix = null;
for (int i = 0; i < reader.getAttributeCount(); i++) {
String attr = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (attr.equals("tick")) {
TypeDefinition.TICK.parseAndSetParameter(value, addTypeOperation, reader);
} else if (attr.equals("suffix")) {
suffix = value;
} else {
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
ParseUtils.requireNoContent(reader);
if (suffix == null) {
throw ParseUtils.missingRequiredElement(reader,
Collections.singleton("suffix"));
}
//Add the 'add' operation for each 'type' child
PathAddress addr = PathAddress.pathAddress(SUBSYSTEM_PATH,
PathElement.pathElement(TYPE, suffix));
addTypeOperation.get(OP_ADDR).set(addr.toModelNode());
list.add(addTypeOperation);
}
...
So in the above we always create the add operation for our subsystem. Due to its address
/subsystem=tracker defined by SUBSYSTEM_PATH this will trigger the SubsystemAddHandler we
created earlier when we invoke /subsystem=tracker:add. We then parse the child elements and create
an add operation for the child address for each type child. Since the address will for example be
/subsystem=tracker/type=sar (defined by TYPE_PATH ) and TypeAddHandler is registered for all
type subaddresses the TypeAddHandler will get invoked for those operations. Note that when we are
parsing attribute tick we are using definition of attribute that we defined in TypeDefintion to parse attribute
value and apply all rules that we specified for this attribute, this also enables us to property support
expressions on attributes.
WildFly 9
The parser is also used to marshal the model to xml whenever something modifies the model, for which the
entry point is the writeContent() method:
Then we have to implement the SubsystemDescribeHandler which translates the current state of the
model into operations similar to the ones created by the parser. The SubsystemDescribeHandler is only
used when running in a managed domain, and is used when the host controller queries the domain controller
for the configuration of the profile used to start up each server. In our case the
SubsystemDescribeHandler adds the operation to add the subsystem and then adds the operation to
add each type child. Since we are using ResourceDefinitinon for defining subsystem all that is generated
for us, but if you want to customize that you can do it by implementing it like this.
WildFly 9
WildFly 9
Now that we have modified our parsers we need to update our tests to reflect the new model. There are
currently three tests testing the basic functionality, something which is a lot easier to debug from your IDE
before you plug it into the application server. We will talk about these tests in turn and they all live in
com.acme.corp.tracker.extension.SubsystemParsingTestCase.
SubsystemParsingTestCase extends AbstractSubsystemTest which does a lot of the setup for you
and contains utility methods for verifying things from your test. See the javadoc of that class for more
information about the functionality available to you. And by all means feel free to add more tests for your
subsystem, here we are only testing for the best case scenario while you will probably want to throw in a few
tests for edge cases.
The first test we need to modify is testParseSubsystem(). It tests that the parsed xml becomes the
expected operations that will be parsed into the server, so let us tweak this test to match our subsystem.
First we tell the test to parse the xml into operations
@Test
public void testParseSubsystem() throws Exception {
//Parse the subsystem xml into operations
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
<deployment-type suffix=\"tst\" tick=\"12345\"/>" +
"
</deployment-types>" +
"</subsystem>";
List<ModelNode> operations = super.parse(subsystemXml);
There should be one operation for adding the subsystem itself and an operation for adding the
deployment-type, so check we got two operations
Now check that the first operation is add for the address /subsystem=tracker:
Then check that the second operation is add for the address /subsystem=tracker, and that 12345 was
picked up for the value of the tick parameter:
WildFly 9
The second test we need to modify is testInstallIntoController() which tests that the xml installs
properly into the controller. In other words we are making sure that the add operations we created earlier
work properly. First we create the xml and install it into the controller. Behind the scenes this will parse the
xml into operations as we saw in the last test, but it will also create a new controller and boot that up using
the created operations
@Test
public void testInstallIntoController() throws Exception {
//Parse the subsystem xml and install into the controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
<deployment-type suffix=\"tst\" tick=\"12345\"/>" +
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
The returned KernelServices allow us to execute operations on the controller, and to read the whole
model.
Now we make sure that the structure of the model within the controller has the expected format and values
WildFly 9
Assert.assertTrue(model.get(SUBSYSTEM).hasDefined(SubsystemExtension.SUBSYSTEM_NAME));
Assert.assertTrue(model.get(SUBSYSTEM,
SubsystemExtension.SUBSYSTEM_NAME).hasDefined("type"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type").hasDefined("tst"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME, "type",
"tst").hasDefined("tick"));
Assert.assertEquals(12345, model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type", "tst", "tick").asLong());
}
The last test provided is called testParseAndMarshalModel(). It's main purpose is to make sure that
our SubsystemParser.writeContent() works as expected. This is achieved by starting a controller in
the same way as before
@Test
public void testParseAndMarshalModel() throws Exception {
//Parse the subsystem xml and install into the first controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices servicesA = super.installInController(subsystemXml);
Now we read the model and the xml that was persisted from the first controller, and use that xml to start a
second controller
//Get the model and the persisted xml from the first controller
ModelNode modelA = servicesA.readWholeModel();
String marshalled = servicesA.getPersistedSubsystemXml();
//Install the persisted xml from the first controller into a second controller
KernelServices servicesB = super.installInController(marshalled);
Finally we read the model from the second controller, and make sure that the models are identical by calling
compare() on the test superclass.
We then have a test that needs no changing from what the archetype provides us with. As we have seen
before we start a controller
WildFly 9
@Test
public void testDescribeHandler() throws Exception {
//Parse the subsystem xml and install into the first controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"</subsystem>";
KernelServices servicesA = super.installInController(subsystemXml);
//Get the model and the describe operations from the first controller
ModelNode modelA = servicesA.readWholeModel();
ModelNode describeOp = new ModelNode();
describeOp.get(OP).set(DESCRIBE);
describeOp.get(OP_ADDR).set(
PathAddress.pathAddress(
PathElement.pathElement(SUBSYSTEM,
SubsystemExtension.SUBSYSTEM_NAME)).toModelNode());
List<ModelNode> operations =
super.checkResultAndGetContents(servicesA.executeOperation(describeOp)).asList();
//Install the describe options from the first controller into a second controller
KernelServices servicesB = super.installInController(operations);
And then we read the model from the second controller and make sure that the two subsystems are identical
ModelNode modelB = servicesB.readWholeModel();
//Make sure the models from the two controllers are identical
super.compare(modelA, modelB);
}
To test the removal of the the subsystem and child resources we modify the testSubsystemRemoval()
test provided by the archetype:
/**
* Tests that the subsystem can be removed
*/
@Test
public void testSubsystemRemoval() throws Exception {
//Parse the subsystem xml and install into the first controller
We provide xml for the subsystem installing a child, which in turn installs a TrackerService
WildFly 9
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
Having installed the xml into the controller we make sure the TrackerService is there
This call from the subsystem test harness will call remove for each level in our subsystem, children first and
validate
that the subsystem model is empty at the end.
Finally we check that all the services were removed by the remove handlers
//Check that any services that were installed were removed here
try {
services.getContainer().getRequiredService(TrackerService.createServiceName("tst"));
Assert.fail("Should have removed services");
} catch (Exception expected) {
}
}
For good measure let us throw in another test which adds a deployment-type and also changes its
attribute at runtime. So first of all boot up the controller with the same xml we have been using so far
@Test
public void testExecuteOperations() throws Exception {
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
Now create an operation which does the same as the following CLI command
/subsystem=tracker/type=foo:add(tick=1000)
WildFly 9
Read the whole model and make sure that the original data is still there (i.e. the same as what was done by
testInstallIntoController()
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type").hasDefined("foo"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME, "type",
"foo").hasDefined("tick"));
Assert.assertEquals(1000, model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type", "foo", "tick").asLong());
//Call write-attribute
ModelNode writeOp = new ModelNode();
writeOp.get(OP).set(WRITE_ATTRIBUTE_OPERATION);
writeOp.get(OP_ADDR).set(fooTypeAddr.toModelNode());
writeOp.get(NAME).set("tick");
writeOp.get(VALUE).set(3456);
result = services.executeOperation(writeOp);
Assert.assertEquals(SUCCESS, result.get(OUTCOME).asString());
WildFly 9
To give you exposure to other ways of doing things, now instead of reading the whole model to check the
attribute, we call read-attribute instead, and make sure it has the value we set it to.
//Check that write attribute took effect, this time by calling read-attribute instead of reading
the whole model
ModelNode readOp = new ModelNode();
readOp.get(OP).set(READ_ATTRIBUTE_OPERATION);
readOp.get(OP_ADDR).set(fooTypeAddr.toModelNode());
readOp.get(NAME).set("tick");
result = services.executeOperation(readOp);
Assert.assertEquals(3456, checkResultAndGetContents(result).asLong());
Since each type installs its own copy of TrackerService, we get the TrackerService for type=foo
from the service container exposed by the kernel services and make sure it has the right value
TrackerService service =
(TrackerService)services.getContainer().getService(TrackerService.createServiceName("foo")).getValue();
Assert.assertEquals(3456, service.getTick());
}
TypeDefinition.TICK.
@Override
public void performBoottime(OperationContext context, ModelNode operation, ModelNode model,
ServiceVerificationHandler verificationHandler, List<ServiceController<?>>
newControllers)
throws OperationFailedException {
log.info("Populating the model");
//Add deployment processors here
//Remove this if you don't need to hook into the deployers, or you can add as many as
you like
//see SubDeploymentProcessor for explanation of the phases
context.addStep(new AbstractDeploymentChainStep() {
public void execute(DeploymentProcessorTarget processorTarget) {
processorTarget.addDeploymentProcessor(SubsystemDeploymentProcessor.PHASE,
SubsystemDeploymentProcessor.priority, new SubsystemDeploymentProcessor());
}
}, OperationContext.Stage.RUNTIME);
}
WildFly 9
This adds an extra step which is responsible for installing deployment processors. You can add as many as
you like, or avoid adding any all together depending on your needs. Each processor has a Phase and a
priority. Phases are sequential, and a deployment passes through each phases deployment processors.
The priority specifies where within a phase the processor appears. See
org.jboss.as.server.deployment.Phase for more information about phases.
In our case we are keeping it simple and staying with one deployment processor with the phase and priority
created for us by the maven archetype. The phases will be explained in the next section. The deployment
processor is as follows:
WildFly 9
The deploy() method is called when a deployment is being deployed. In this case we look for the
TrackerService instance for the service name created from the deployment's suffix. If there is one it
means that we are meant to be tracking deployments with this suffix (i.e. TypeAddHandler was called for
this suffix), and if we find one we add the deployment's name to it. Similarly undeploy() is called when a
deployment is being undeployed, and if there is a TrackerService instance for the deployment's suffix,
we remove the deployment's name from it.
WildFly 9
STRUCTURE
The deployment unit processors in this phase determine the structure of a deployment, and looks for sub
deployments and metadata files.
PARSE
In this phase the deployment unit processors parse the deployment descriptors and build up the annotation
index. Class-Path entries from the META-INF/MANIFEST.MF are added.
DEPENDENCIES
Extra class path dependencies are added. For example if deploying a war file, the commonly needed
dependencies for a web application are added.
CONFIGURE_MODULE
In this phase the modular class loader for the deployment is created. No attempt should be made loading
classes from the deployment until after this phase.
POST_MODULE
Now that our class loader has been constructed we have access to the classes. In this stage deployment
processors may use the Attachments.REFLECTION_INDEX attachment which is a deployment index
used to obtain members of classes in the deployment, and to invoke upon them, bypassing the inefficiencies
of using java.lang.reflect directly.
INSTALL
Install new services coming from the deployment.
CLEANUP
Attachments put in place earlier in the deployment unit processor chain may be removed here.
WildFly 9
11.7.7 Expressions
Expressions are mechanism that enables you to support variables in your attributes, for instance when you
want the value of attribute to be resolved using system / environment properties.
An example expression is
${jboss.bind.address.management:127.0.0.1}
which means that the value should be taken from a system property named
jboss.bind.address.management and if it is not defined use 127.0.0.1.
${expression_to_resolve}
WildFly 9
SimpleAttributeDefinition MY_ATTRIBUTE =
new SimpleAttributeDefinitionBuilder("my-attribute", ModelType.INT, true)
.setAllowExpression(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setDefaultValue(new ModelNode(1))
.build();
Then later when you are parsing the xml configuration you should use the MY_ATTRIBUTE attribute
definition to set the value to the management operation ModelNode you are creating.
....
String attr = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (attr.equals("my-attribute")) {
MY_ATTRIBUTE.parseAndSetParameter(value, operation, reader);
} else if (attr.equals("suffix")) {
.....
Note that this just helps you to properly set the value to the model node you are working on, so no need to
additionally set anything to the model for this attribute. Method parseAndSetParameter parses the value that
was read from xml for possible expressions in it and if it finds any it creates special model node that defines
that node is of type ModelType.EXPRESSION.
Later in your operation handlers where you implement populateModel and have to store the value from the
operation to the configuration model you also use this MY_ATTRIBUTE attribute definition.
@Override
protected void populateModel(ModelNode operation, ModelNode model) throws
OperationFailedException {
MY_ATTRIBUTE.validateAndSet(operation,model);
}
This will make sure that the attribute that is stored from the operation to the model is valid and nothing is
lost. It also checks the value stored in the operation ModelNode, and if it isn't already
ModelType.EXPRESSION, it checks if the value is a string that contains the expression syntax. If so, the
value stored in the model will be of type ModelType.EXPRESSION. Doing this ensures that expressions are
properly handled when they appear in operations that weren't created by the subsystem parser, but are
instead passed in from CLI or admin console users.
As last step we need to use the value of the attribute. This is usually needed inside of the performRuntime
method
WildFly 9
As you can see resolving of attribute's value is not done until it is needed for use in the subsystem's runtime
services. The resolved value is not stored in the configuration model, the unresolved expression is. That way
we do not lose any information in the model and can assure that also marshalling is done properly, where we
must marshall back the unresolved value.
Attribute definitinon also helps you with that:
WildFly 9
@Override
public void performBoottime(OperationContext context, ModelNode operation, ModelNode model,
ServiceVerificationHandler verificationHandler, List<ServiceController<?>>
newControllers)
throws OperationFailedException {
log.info("Populating the model");
//Add deployment processors here
//Remove this if you don't need to hook into the deployers, or you can add as many as
you like
//see SubDeploymentProcessor for explanation of the phases
context.addStep(new AbstractDeploymentChainStep() {
public void execute(DeploymentProcessorTarget processorTarget) {
processorTarget.addDeploymentProcessor(SubsystemDeploymentProcessor.PHASE,
SubsystemDeploymentProcessor.priority, new SubsystemDeploymentProcessor());
}
}, OperationContext.Stage.RUNTIME);
}
This adds an extra step which is responsible for installing deployment processors. You can add as many as
you like, or avoid adding any all together depending on your needs. Each processor has a Phase and a
priority. Phases are sequential, and a deployment passes through each phases deployment processors.
The priority specifies where within a phase the processor appears. See
org.jboss.as.server.deployment.Phase for more information about phases.
In our case we are keeping it simple and staying with one deployment processor with the phase and priority
created for us by the maven archetype. The phases will be explained in the next section. The deployment
processor is as follows:
WildFly 9
The deploy() method is called when a deployment is being deployed. In this case we look for the
TrackerService instance for the service name created from the deployment's suffix. If there is one it
means that we are meant to be tracking deployments with this suffix (i.e. TypeAddHandler was called for
this suffix), and if we find one we add the deployment's name to it. Similarly undeploy() is called when a
deployment is being undeployed, and if there is a TrackerService instance for the deployment's suffix,
we remove the deployment's name from it.
WildFly 9
STRUCTURE
The deployment unit processors in this phase determine the structure of a deployment, and looks for sub
deployments and metadata files.
PARSE
In this phase the deployment unit processors parse the deployment descriptors and build up the annotation
index. Class-Path entries from the META-INF/MANIFEST.MF are added.
DEPENDENCIES
Extra class path dependencies are added. For example if deploying a war file, the commonly needed
dependencies for a web application are added.
CONFIGURE_MODULE
In this phase the modular class loader for the deployment is created. No attempt should be made loading
classes from the deployment until after this phase.
POST_MODULE
Now that our class loader has been constructed we have access to the classes. In this stage deployment
processors may use the Attachments.REFLECTION_INDEX attachment which is a deployment index
used to obtain members of classes in the deployment, and to invoke upon them, bypassing the inefficiencies
of using java.lang.reflect directly.
INSTALL
Install new services coming from the deployment.
CLEANUP
Attachments put in place earlier in the deployment unit processor chain may be removed here.
WildFly 9
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:com.acme.corp.tracker:1.0"
xmlns="urn:com.acme.corp.tracker:1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.0">
<!-- The subsystem root element -->
<xs:element name="subsystem" type="subsystemType"/>
<xs:complexType name="subsystemType">
<xs:all>
<xs:element name="deployment-types" type="deployment-typesType"/>
</xs:all>
</xs:complexType>
<xs:complexType name="deployment-typesType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="deployment-type" type="deployment-typeType"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="deployment-typeType">
<xs:attribute name="suffix" use="required"/>
<xs:attribute name="tick" type="xs:long" use="optional" default="10000"/>
</xs:complexType>
</xs:schema>
WildFly 9
mvn archetype:generate \
-DarchetypeArtifactId=wildfly-subsystem \
-DarchetypeGroupId=org.wildfly.archetypes \
-DarchetypeVersion=8.0.0.Final \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
Maven will download the archetype and it's dependencies, and ask you some questions:
$ mvn archetype:generate \
-DarchetypeArtifactId=wildfly-subsystem \
-DarchetypeGroupId=org.wildfly.archetypes \
-DarchetypeVersion=8.0.0.Final \
-DarchetypeRepository=http://repository.jboss.org/nexus/content/groups/public
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------------------------------------------------------[INFO] Building Maven Stub Project (No POM) 1
[INFO] -----------------------------------------------------------------------[INFO]
.........
Define value for property 'groupId': : com.acme.corp
Define value for property 'artifactId': : acme-subsystem
Define value for property 'version': 1.0-SNAPSHOT: :
Define value for property 'package': com.acme.corp: : com.acme.corp.tracker
Define value for property 'module': : com.acme.corp.tracker
[INFO] Using property: name = WildFly subsystem project
Confirm properties configuration:
groupId: com.acme.corp
artifactId: acme-subsystem
version: 1.0-SNAPSHOT
package: com.acme.corp.tracker
module: com.acme.corp.tracker
name: WildFly subsystem project
Y: : Y
[INFO] -----------------------------------------------------------------------[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------------------[INFO] Total time: 1:42.563s
[INFO] Finished at: Fri Jul 08 14:30:09 BST 2011
[INFO] Final Memory: 7M/81M
[INFO] -----------------------------------------------------------------------$
WildFly 9
Instruction
1 Enter the groupId you wish to use
2 Enter the artifactId you wish to use
3 Enter the version you wish to use, or just hit Enter if you wish to accept the default 1.0-SNAPSHOT
4 Enter the java package you wish to use, or just hit Enter if you wish to accept the default (which is
copied from groupId ).
5 Enter the module name you wish to use for your extension.
6 Finally, if you are happy with your choices, hit Enter and Maven will generate the project for you.
You can also do this in Eclipse, see Creating your own application for more details. We now have a skeleton
project that you can use to implement a subsystem. Import the acme-subsystem project into your favourite
IDE. A nice side-effect of running this in the IDE is that you can see the javadoc of WildFly classes and
interfaces imported by the skeleton code. If you do a mvn install in the project it will work if we plug it into
WildFly 8, but before doing that we will change it to do something more useful.
The rest of this section modifies the skeleton project created by the archetype to do something more useful,
and the full code can be found in acme-subsystem.zip.
If you do a mvn install in the created project, you will see some tests being run
$mvn install
[INFO] Scanning for projects...
[...]
[INFO] Surefire report directory:
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/target/surefire-reports
------------------------------------------------------T E S T S
------------------------------------------------------Running com.acme.corp.tracker.extension.SubsystemBaseParsingTestCase
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.424 sec
Running com.acme.corp.tracker.extension.SubsystemParsingTestCase
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.074 sec
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
[...]
We will talk about these later in the Testing the parsers section.
WildFly 9
<subsystem xmlns="urn:com.acme.corp.tracker:1.0">
<deployment-types>
<deployment-type suffix="sar" tick="10000"/>
<deployment-type suffix="war" tick="10000"/>
</deployment-types>
</subsystem>
Now when designing our model, we can either do a one to one mapping between the schema and the model
or come up with something slightly or very different. To keep things simple, let us stay pretty true to the
schema so that when executing a :read-resource(recursive=true) against our subsystem we'll see
something like:
{
"outcome" => "success",
"result" => {"type" => {
"sar" => {"tick" => "10000"},
"war" => {"tick" => "10000"}
}}
}
Each deployment-type in the xml becomes in the model a child resource of the subsystem's root
resource. The child resource's child-type is type, and it is indexed by its suffix. Each type resource then
contains the tick attribute.
We also need a name for our subsystem, to do that change
com.acme.corp.tracker.extension.SubsystemExtension:
WildFly 9
@Override
public void initialize(ExtensionContext context) {
//register subsystem with its model version
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0);
//register subsystem model with subsystem definition that defines all attributes and
operations
final ManagementResourceRegistration registration =
subsystem.registerSubsystemModel(SubsystemDefinition.INSTANCE);
//register describe operation, note that this can be also registered in
SubsystemDefinition
registration.registerOperationHandler(DESCRIBE,
GenericSubsystemDescribeHandler.INSTANCE, GenericSubsystemDescribeHandler.INSTANCE, false,
OperationEntry.EntryType.PRIVATE);
//we can register additional submodels here
//
subsystem.registerXMLElementWriter(parser);
}
The registerSubsystem() call registers our subsystem with the extension context. At the end of the
method we register our parser with the returned SubsystemRegistration to be able to marshal our
subsystem's model back to the main configuration file when it is modified. We will add more functionality to
this method later.
It's parameter is an implementation of the ResourceDefinition interface, which means that when you call
/subsystem=tracker:read-resource-description the information you see comes from model that
is defined by SubsystemDefinition.INSTANCE.
WildFly 9
WildFly 9
There are two way to define DescriptionProvider, one is by defining it by hand using ModelNode, but as this
has show to be very error prone there are lots of helper methods to help you automatically describe the
model. Flowing example is done by manually defining Description provider for ADD operation handler
/**
* Used to create the description of the subsystem add method
*/
public static DescriptionProvider SUBSYSTEM_ADD = new DescriptionProvider() {
public ModelNode getModelDescription(Locale locale) {
//The locale is passed in so you can internationalize the strings used in the
descriptions
final ModelNode subsystem = new ModelNode();
subsystem.get(OPERATION_NAME).set(ADD);
subsystem.get(DESCRIPTION).set("Adds the tracker subsystem");
return subsystem;
}
};
Or you can use API that helps you do that for you. For Add and Remove methods there are classes
DefaultResourceAddDescriptionProvider and DefaultResourceRemoveDescriptionProvider that do work for
you. In case you use SimpleResourceDefinition even that part is hidden from you.
resourceRegistration.registerOperationHandler(ADD, SubsystemAdd.INSTANCE, new
DefaultResourceAddDescriptionProvider(resourceRegistration,descriptionResolver), false);
resourceRegistration.registerOperationHandler(REMOVE, SubsystemRemove.INSTANCE, new
DefaultResourceRemoveDescriptionProvider(resourceRegistration,descriptionResolver), false);
For other operation handlers that are not add/remove you can use DefaultOperationDescriptionProvider that
takes additional parameter of what is the name of operation and optional array of parameters/attributes
operation takes. This is an example to register operation "add-mime" with two parameters:
container.registerOperationHandler("add-mime",
MimeMappingAdd.INSTANCE,
new DefaultOperationDescriptionProvider("add-mime",
Extension.getResourceDescriptionResolver("container.mime-mapping"), MIME_NAME, MIME_VALUE));
When descriping an operation its description provider's OPERATION_NAME must match the name
used when calling ManagementResourceRegistration.registerOperationHandler()
Next we have the actual operation handler instance, note that we have changed its populateModel()
method to initialize the type child of the model.
WildFly 9
SubsystemAdd also has a performBoottime() method which is used for initializing the deployer chain
associated with this subsystem. We will talk about the deployers later on. However, the basic idea for all
operation handlers is that we do any model updates before changing the actual runtime state.
The rule of thumb is that every thing that can be added, can also be removed so we have a remove handler
for the subsystem registered
in SubsystemDefinition.registerOperations or just provide the operation handler in constructor.
The description provider for the remove operation is simple and quite similar to that of the add handler where
just name of the method changes.
WildFly 9
Then we define subsystem model. Lets call it TypeDefinition and for ease of use let it extend
SimpleResourceDefinition instead just implement ResourceDefinition.
WildFly 9
Which will take care of describing the model for us. As you can see in example above we define
SimpleAttributeDefinition named TICK, this is a mechanism to define Attributes in more type safe way and to
add more common API to manipulate attributes. As you can see here we define default value of 1000 as
also other constraints and capabilities. There could be other properties set such as validators, alternate
names, xml name, flags for marking it attribute allows expressions and more.
Then we do the work of updating the model by implementing the populateModel() method from the
AbstractAddStepHandler, which populates the model's attribute from the operation parameters. First we
get hold of the model relative to the address of this operation (we will see later that we will register it against
/subsystem=tracker/type=*), so we just specify an empty relative address, and we then populate our
model with the parameters from the operation. There is operation validateAndSet on AttributeDefinition that
helps us validate and set the model based on definition of the attribute.
@Override
protected void populateModel(ModelNode operation, ModelNode model) throws
OperationFailedException {
TICK.validateAndSet(operation,model);
}
We then override the performRuntime() method to perform our runtime changes, which in this case
involves installing a service into the controller at the heart of WildFly 8. (
AbstractAddStepHandler.performRuntime() is similar to
AbstractBoottimeAddStepHandler.performBoottime() in that the model is updated before runtime
changes are made.
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode
model,
ServiceVerificationHandler verificationHandler, List<ServiceController<?>>
newControllers)
throws OperationFailedException {
String suffix =
PathAddress.pathAddress(operation.get(ModelDescriptionConstants.ADDRESS)).getLastElement().getValue();
long tick = TICK.resolveModelAttribute(context,model).asLong();
TrackerService service = new TrackerService(suffix, tick);
ServiceName name = TrackerService.createServiceName(suffix);
ServiceController<TrackerService> controller = context.getServiceTarget()
.addService(name, service)
.addListener(verificationHandler)
.setInitialMode(Mode.ACTIVE)
.install();
newControllers.add(controller);
}
}
WildFly 9
The tracker service is quite simple. All services installed into WildFly 8 must implement the
org.jboss.msc.service.Service interface.
We then have some fields to keep the tick count and a thread which when run outputs all the deployments
registered with our service.
Next we have three methods which come from the Service interface. getValue() returns this service,
start() is called when the service is started by the controller, stop is called when the service is stopped
by the controller, and they start and stop the thread outputting the deployments.
WildFly 9
@Override
public TrackerService getValue() throws IllegalStateException, IllegalArgumentException {
return this;
}
@Override
public void start(StartContext context) throws StartException {
OUTPUT.start();
}
@Override
public void stop(StopContext context) {
OUTPUT.interrupt();
}
Next we have a utility method to create the ServiceName which is used to register the service in the
controller.
Finally we have some methods to add and remove deployments, and to set and read the tick. The 'cool'
deployments will be explained later.
WildFly 9
Since we are able to add type children, we need a way to be able to remove them, so we create a
com.acme.corp.tracker.extension.TypeRemoveHandler. In this case we extend
AbstractRemoveStepHandler which takes care of removing the resource from the model so we don't
need to override its performRemove() operationa. But we need to implement the
DescriptionProvider method to provide the model description, and since the add handler installs the
TrackerService, we need to remove that in the performRuntime() method.
@Override
protected void performRuntime(OperationContext context, ModelNode operation, ModelNode
model) throws OperationFailedException {
String suffix =
PathAddress.pathAddress(operation.get(ModelDescriptionConstants.ADDRESS)).getLastElement().getValue();
ServiceName name = TrackerService.createServiceName(suffix);
context.removeService(name);
}
}
We then need a description provider for the type part of the model itself, so we modify TypeDefinitnion to
registerAttribute
class TypeDefinition{
...
@Override
public void registerAttributes(ManagementResourceRegistration resourceRegistration){
resourceRegistration.registerReadWriteAttribute(TICK, null, TrackerTickHandler.INSTANCE);
}
}
Then finally we need to specify that our new type child and associated handlers go under
/subsystem=tracker/type=* in the model by adding registering it with the model in
SubsystemExtension.initialize(). So we add the following just before the end of the method.
WildFly 9
@Override
public void initialize(ExtensionContext context)
{
final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, 1, 0);
final ManagementResourceRegistration registration =
subsystem.registerSubsystemModel(TrackerSubsystemDefinition.INSTANCE);
//Add the type child
ManagementResourceRegistration typeChild =
registration.registerSubModel(TypeDefinition.INSTANCE);
subsystem.registerXMLElementWriter(parser);
}
The above first creates a child of our main subsystem registration for the relative address type=*, and gets
the typeChild registration.
To this we add the TypeAddHandler and TypeRemoveHandler.
The add variety is added under the name add and the remove handler under the name remove, and for
each registered operation handler we use the handler singleton instance as both the handler parameter and
as the DescriptionProvider.
Finally, we register tick as a read/write attribute, the null parameter means we don't do anything special
with regards to reading it, for the write handler we supply it with an operation handler called
TrackerTickHandler.
Registering it as a read/write attribute means we can use the :write-attribute operation to modify the
value of the parameter, and it will be handled by TrackerTickHandler.
Not registering a write attribute handler makes the attribute read only.
TrackerTickHandler extends AbstractWriteAttributeHandler
directly, and so must implement its applyUpdateToRuntime and revertUpdateToRuntime method.
This takes care of model manipulation (validation, setting) but leaves us to do just to deal with what we need
to do.
WildFly 9
When implementing execute(), you must call context.completeStep() when you are done.
WildFly 9
11.7.12 Expressions
Expressions are mechanism that enables you to support variables in your attributes, for instance when you
want the value of attribute to be resolved using system / environment properties.
An example expression is
${jboss.bind.address.management:127.0.0.1}
which means that the value should be taken from a system property named
jboss.bind.address.management and if it is not defined use 127.0.0.1.
${expression_to_resolve}
SimpleAttributeDefinition MY_ATTRIBUTE =
new SimpleAttributeDefinitionBuilder("my-attribute", ModelType.INT, true)
.setAllowExpression(true)
.setFlags(AttributeAccess.Flag.RESTART_ALL_SERVICES)
.setDefaultValue(new ModelNode(1))
.build();
WildFly 9
Then later when you are parsing the xml configuration you should use the MY_ATTRIBUTE attribute
definition to set the value to the management operation ModelNode you are creating.
....
String attr = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (attr.equals("my-attribute")) {
MY_ATTRIBUTE.parseAndSetParameter(value, operation, reader);
} else if (attr.equals("suffix")) {
.....
Note that this just helps you to properly set the value to the model node you are working on, so no need to
additionally set anything to the model for this attribute. Method parseAndSetParameter parses the value that
was read from xml for possible expressions in it and if it finds any it creates special model node that defines
that node is of type ModelType.EXPRESSION.
Later in your operation handlers where you implement populateModel and have to store the value from the
operation to the configuration model you also use this MY_ATTRIBUTE attribute definition.
@Override
protected void populateModel(ModelNode operation, ModelNode model) throws
OperationFailedException {
MY_ATTRIBUTE.validateAndSet(operation,model);
}
This will make sure that the attribute that is stored from the operation to the model is valid and nothing is
lost. It also checks the value stored in the operation ModelNode, and if it isn't already
ModelType.EXPRESSION, it checks if the value is a string that contains the expression syntax. If so, the
value stored in the model will be of type ModelType.EXPRESSION. Doing this ensures that expressions are
properly handled when they appear in operations that weren't created by the subsystem parser, but are
instead passed in from CLI or admin console users.
As last step we need to use the value of the attribute. This is usually needed inside of the performRuntime
method
WildFly 9
As you can see resolving of attribute's value is not done until it is needed for use in the subsystem's runtime
services. The resolved value is not stored in the configuration model, the unresolved expression is. That way
we do not lose any information in the model and can assure that also marshalling is done properly, where we
must marshall back the unresolved value.
Attribute definitinon also helps you with that:
[kabir ~/sourcecontrol/temp/archetype-test/acme-subsystem]
$mvn install
[INFO] Scanning for projects...
[...]
main:
[delete] Deleting:
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/null1004283288
[delete] Deleting directory
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/target/module
[copy] Copying 1 file to
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/target/module/com/acme/corp/tracker/main
[copy] Copying 1 file to
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/target/module/com/acme/corp/tracker/main
[echo] Module com.acme.corp.tracker has been created in the target/module directory. Copy to
your JBoss AS 7 installation.
[INFO] Executed tasks
[INFO]
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ acme-subsystem --[INFO] Installing
/Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/target/acme-subsystem.jar to
/Users/kabir/.m2/repository/com/acme/corp/acme-subsystem/1.0-SNAPSHOT/acme-subsystem-1.0-SNAPSHOT.jar[INFO]
Installing /Users/kabir/sourcecontrol/temp/archetype-test/acme-subsystem/pom.xml to
/Users/kabir/.m2/repository/com/acme/corp/acme-subsystem/1.0-SNAPSHOT/acme-subsystem-1.0-SNAPSHOT.pom[INFO]
-----------------------------------------------------------------------[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------------------[INFO] Total time: 5.851s
[INFO] Finished at: Mon Jul 11 23:24:58 BST 2011
[INFO] Final Memory: 7M/81M
[INFO] ------------------------------------------------------------------------
WildFly 9
This will have built our project and assembled a module for us that can be used for installing it into WildFly 8.
If you go to the target/module folder where you built the project you will see the module
$ls target/module/com/acme/corp/tracker/main/
acme-subsystem.jar
module.xml
And has a default set of dependencies needed by every subsystem created. If your subsystem requires
additional module dependencies you can add them here before building and installing.
<dependencies>
<module name="javax.api"/>
<module name="org.jboss.staxmapper"/>
<module name="org.jboss.as.controller"/>
<module name="org.jboss.as.server"/>
<module name="org.jboss.modules"/>
<module name="org.jboss.msc"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.vfs"/>
</dependencies>
</module>
Note that the name of the module corresponds to the directory structure containing it. Now copy the
target/module/com/acme/corp/tracker/main/ directory and its contents to
$WFLY/modules/com/acme/corp/tracker/main/ (where $WFLY is the root of your WildFly install).
Next we need to modify $WFLY/standalone/configuration/standalone.xml. First we need to add
our new module to the <extensions> section:
<extensions>
...
<extension module="org.jboss.as.weld"/>
<extension module="com.acme.corp.tracker"/>
</extensions>
WildFly 9
<profile>
...
<subsystem xmlns="urn:com.acme.corp.tracker:1.0">
<deployment-types>
<deployment-type suffix="sar" tick="10000"/>
<deployment-type suffix="war" tick="10000"/>
</deployment-types>
</subsystem>
...
</profile>
Adding this to a managed domain works exactly the same apart from in this case you need to modify
$AS7/domain/configuration/domain.xml.
Now start up WildFly 8 by running $WFLY/bin/standalone.sh and you should see messages like these
after the server has started, which means our subsystem has been added and our TrackerService is
working:
15:27:33,838 INFO
started in 2861ms - Started 94 of 149 services (55 services are passive or on-demand)
15:27:42,966 INFO
15:27:42,966 INFO
15:27:42,967 INFO
15:27:42,967 INFO
15:27:42,967 INFO
15:27:42,967 INFO
15:27:52,967 INFO
[stdout] (Thread-9) []
[stdout] (Thread-9) Cool: 0
[stdout] (Thread-8) Current deployments deployed while sar tracking active:
15:27:52,967 INFO
[stdout] (Thread-8) []
15:27:52,967 INFO
If you run the command line interface you can execute some commands to see more about the subsystem.
For example
[standalone@localhost:9999 /] /subsystem=tracker/:read-resource-description(recursive=true,
operations=true)
will return a lot of information, including what we provided in the DescriptionProviders we created to
document our subsystem.
To see the current subsystem state you can execute
WildFly 9
[standalone@localhost:9999 /] /subsystem=tracker/:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"type" => {
"war" => {"tick" => 10000L},
"sar" => {"tick" => 10000L}
}}
}
We can remove both the deployment types which removes them from the model:
[standalone@localhost:9999 /] /subsystem=tracker/type=sar:remove
{"outcome" => "success"}
[standalone@localhost:9999 /] /subsystem=tracker/type=war:remove
{"outcome" => "success"}
[standalone@localhost:9999 /] /subsystem=tracker/:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"type" => undefined}
}
You should now see the output from the TrackerService instances having stopped.
Now, let's add the war tracker again:
[standalone@localhost:9999 /] /subsystem=tracker/type=war:add
{"outcome" => "success"}
[standalone@localhost:9999 /] /subsystem=tracker/:read-resource(recursive=true)
{
"outcome" => "success",
"result" => {"type" => {"war" => {"tick" => 10000L}}}
}
and the WildFly 8 console should show the messages coming from the war TrackerService again.
Now let us deploy something. You can find two maven projects for test wars already built at test1.zip and
test2.zip. If you download them and extract them to /Downloads/test1 and /Downloads/test2, you
can see that /Downloads/test1/target/test1.war contains a META-INF/cool.txt while
/Downloads/test2/target/test2.war does not contain that file. From CLI deploy test1.war first:
And you should now see the output from the war TrackerService list the deployments:
WildFly 9
15:35:03,712 INFO
of "test1.war"
15:35:03,988 INFO
15:35:03,996 INFO
15:35:13,056 INFO
15:35:13,056 INFO
15:35:13,057 INFO
You will see that deployment get picked up as well but since there is no META-INF/cool.txt it is not
marked as a 'cool' deployment:
15:37:05,634 INFO
of "test2.war"
15:37:05,699 INFO
15:37:05,982 INFO
15:37:13,075 INFO
15:37:13,075 INFO
15:37:13,076 INFO
An undeploy
15:38:47,901 INFO
15:38:47,934 INFO
test1.war in 40ms
15:38:53,091 INFO
15:38:53,092 INFO
15:38:53,092 INFO
Finally, we registered a write attribute handler for the tick property of the type so we can change the
frequency
[standalone@localhost:9999 /] /subsystem=tracker/type=war:write-attribute(name=tick,value=1000)
{"outcome" => "success"}
You should now see the output from the TrackerService happen every second
WildFly 9
15:39:43,100 INFO
15:39:43,100 INFO
15:39:43,101 INFO
15:39:44,101 INFO
15:39:44,102 INFO
15:39:44,105 INFO
15:39:45,106 INFO
15:39:45,106 INFO
<subsystem xmlns="urn:com.acme.corp.tracker:1.0">
<deployment-types>
<deployment-type suffix="war" tick="1000"/>
</deployment-types>
</subsystem>
We then need to write the parser. The contract is that we read our subsystem's xml and create the
operations that will populate the model with the state contained in the xml. These operations will then be
executed on our behalf as part of the parsing process. The entry point is the readElement() method.
WildFly 9
* The subsystem parser, which uses stax to read and write to and from xml
*/
private static class SubsystemParser implements XMLStreamConstants,
XMLElementReader<List<ModelNode>>, XMLElementWriter<SubsystemMarshallingContext> {
/** {@inheritDoc} */
@Override
public void readElement(XMLExtendedStreamReader reader, List<ModelNode> list) throws
XMLStreamException {
// Require no attributes
ParseUtils.requireNoAttributes(reader);
//Add the main subsystem 'add' operation
final ModelNode subsystem = new ModelNode();
subsystem.get(OP).set(ADD);
subsystem.get(OP_ADDR).set(PathAddress.pathAddress(SUBSYSTEM_PATH).toModelNode());
list.add(subsystem);
//Read the children
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (!reader.getLocalName().equals("deployment-types")) {
throw ParseUtils.unexpectedElement(reader);
}
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
if (reader.isStartElement()) {
readDeploymentType(reader, list);
}
}
}
}
private void readDeploymentType(XMLExtendedStreamReader reader, List<ModelNode> list)
throws XMLStreamException {
if (!reader.getLocalName().equals("deployment-type")) {
throw ParseUtils.unexpectedElement(reader);
}
ModelNode addTypeOperation = new ModelNode();
addTypeOperation.get(OP).set(ModelDescriptionConstants.ADD);
String suffix = null;
for (int i = 0; i < reader.getAttributeCount(); i++) {
String attr = reader.getAttributeLocalName(i);
String value = reader.getAttributeValue(i);
if (attr.equals("tick")) {
TypeDefinition.TICK.parseAndSetParameter(value, addTypeOperation, reader);
} else if (attr.equals("suffix")) {
suffix = value;
} else {
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
ParseUtils.requireNoContent(reader);
if (suffix == null) {
throw ParseUtils.missingRequiredElement(reader,
Collections.singleton("suffix"));
}
//Add the 'add' operation for each 'type' child
WildFly 9
PathAddress addr = PathAddress.pathAddress(SUBSYSTEM_PATH,
PathElement.pathElement(TYPE, suffix));
addTypeOperation.get(OP_ADDR).set(addr.toModelNode());
list.add(addTypeOperation);
}
...
So in the above we always create the add operation for our subsystem. Due to its address
/subsystem=tracker defined by SUBSYSTEM_PATH this will trigger the SubsystemAddHandler we
created earlier when we invoke /subsystem=tracker:add. We then parse the child elements and create
an add operation for the child address for each type child. Since the address will for example be
/subsystem=tracker/type=sar (defined by TYPE_PATH ) and TypeAddHandler is registered for all
type subaddresses the TypeAddHandler will get invoked for those operations. Note that when we are
parsing attribute tick we are using definition of attribute that we defined in TypeDefintion to parse attribute
value and apply all rules that we specified for this attribute, this also enables us to property support
expressions on attributes.
The parser is also used to marshal the model to xml whenever something modifies the model, for which the
entry point is the writeContent() method:
WildFly 9
Then we have to implement the SubsystemDescribeHandler which translates the current state of the
model into operations similar to the ones created by the parser. The SubsystemDescribeHandler is only
used when running in a managed domain, and is used when the host controller queries the domain controller
for the configuration of the profile used to start up each server. In our case the
SubsystemDescribeHandler adds the operation to add the subsystem and then adds the operation to
add each type child. Since we are using ResourceDefinitinon for defining subsystem all that is generated
for us, but if you want to customize that you can do it by implementing it like this.
WildFly 9
Now that we have modified our parsers we need to update our tests to reflect the new model. There are
currently three tests testing the basic functionality, something which is a lot easier to debug from your IDE
before you plug it into the application server. We will talk about these tests in turn and they all live in
com.acme.corp.tracker.extension.SubsystemParsingTestCase.
SubsystemParsingTestCase extends AbstractSubsystemTest which does a lot of the setup for you
and contains utility methods for verifying things from your test. See the javadoc of that class for more
information about the functionality available to you. And by all means feel free to add more tests for your
subsystem, here we are only testing for the best case scenario while you will probably want to throw in a few
tests for edge cases.
The first test we need to modify is testParseSubsystem(). It tests that the parsed xml becomes the
expected operations that will be parsed into the server, so let us tweak this test to match our subsystem.
First we tell the test to parse the xml into operations
@Test
public void testParseSubsystem() throws Exception {
//Parse the subsystem xml into operations
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
List<ModelNode> operations = super.parse(subsystemXml);
There should be one operation for adding the subsystem itself and an operation for adding the
deployment-type, so check we got two operations
WildFly 9
Now check that the first operation is add for the address /subsystem=tracker:
Then check that the second operation is add for the address /subsystem=tracker, and that 12345 was
picked up for the value of the tick parameter:
The second test we need to modify is testInstallIntoController() which tests that the xml installs
properly into the controller. In other words we are making sure that the add operations we created earlier
work properly. First we create the xml and install it into the controller. Behind the scenes this will parse the
xml into operations as we saw in the last test, but it will also create a new controller and boot that up using
the created operations
@Test
public void testInstallIntoController() throws Exception {
//Parse the subsystem xml and install into the controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
WildFly 9
The returned KernelServices allow us to execute operations on the controller, and to read the whole
model.
Now we make sure that the structure of the model within the controller has the expected format and values
Assert.assertTrue(model.get(SUBSYSTEM).hasDefined(SubsystemExtension.SUBSYSTEM_NAME));
Assert.assertTrue(model.get(SUBSYSTEM,
SubsystemExtension.SUBSYSTEM_NAME).hasDefined("type"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type").hasDefined("tst"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME, "type",
"tst").hasDefined("tick"));
Assert.assertEquals(12345, model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type", "tst", "tick").asLong());
}
The last test provided is called testParseAndMarshalModel(). It's main purpose is to make sure that
our SubsystemParser.writeContent() works as expected. This is achieved by starting a controller in
the same way as before
@Test
public void testParseAndMarshalModel() throws Exception {
//Parse the subsystem xml and install into the first controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
"
"
<deployment-types>" +
<deployment-type suffix=\"tst\" tick=\"12345\"/>" +
</deployment-types>" +
"</subsystem>";
KernelServices servicesA = super.installInController(subsystemXml);
Now we read the model and the xml that was persisted from the first controller, and use that xml to start a
second controller
//Get the model and the persisted xml from the first controller
ModelNode modelA = servicesA.readWholeModel();
String marshalled = servicesA.getPersistedSubsystemXml();
//Install the persisted xml from the first controller into a second controller
KernelServices servicesB = super.installInController(marshalled);
Finally we read the model from the second controller, and make sure that the models are identical by calling
compare() on the test superclass.
WildFly 9
We then have a test that needs no changing from what the archetype provides us with. As we have seen
before we start a controller
@Test
public void testDescribeHandler() throws Exception {
//Parse the subsystem xml and install into the first controller
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"</subsystem>";
KernelServices servicesA = super.installInController(subsystemXml);
//Get the model and the describe operations from the first controller
ModelNode modelA = servicesA.readWholeModel();
ModelNode describeOp = new ModelNode();
describeOp.get(OP).set(DESCRIBE);
describeOp.get(OP_ADDR).set(
PathAddress.pathAddress(
PathElement.pathElement(SUBSYSTEM,
SubsystemExtension.SUBSYSTEM_NAME)).toModelNode());
List<ModelNode> operations =
super.checkResultAndGetContents(servicesA.executeOperation(describeOp)).asList();
//Install the describe options from the first controller into a second controller
KernelServices servicesB = super.installInController(operations);
And then we read the model from the second controller and make sure that the two subsystems are identical
ModelNode modelB = servicesB.readWholeModel();
//Make sure the models from the two controllers are identical
super.compare(modelA, modelB);
}
To test the removal of the the subsystem and child resources we modify the testSubsystemRemoval()
test provided by the archetype:
WildFly 9
/**
* Tests that the subsystem can be removed
*/
@Test
public void testSubsystemRemoval() throws Exception {
//Parse the subsystem xml and install into the first controller
We provide xml for the subsystem installing a child, which in turn installs a TrackerService
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
<deployment-type suffix=\"tst\" tick=\"12345\"/>" +
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
Having installed the xml into the controller we make sure the TrackerService is there
This call from the subsystem test harness will call remove for each level in our subsystem, children first and
validate
that the subsystem model is empty at the end.
Finally we check that all the services were removed by the remove handlers
//Check that any services that were installed were removed here
try {
services.getContainer().getRequiredService(TrackerService.createServiceName("tst"));
Assert.fail("Should have removed services");
} catch (Exception expected) {
}
}
For good measure let us throw in another test which adds a deployment-type and also changes its
attribute at runtime. So first of all boot up the controller with the same xml we have been using so far
WildFly 9
@Test
public void testExecuteOperations() throws Exception {
String subsystemXml =
"<subsystem xmlns=\"" + SubsystemExtension.NAMESPACE + "\">" +
"
<deployment-types>" +
"
"
</deployment-types>" +
"</subsystem>";
KernelServices services = super.installInController(subsystemXml);
Now create an operation which does the same as the following CLI command
/subsystem=tracker/type=foo:add(tick=1000)
Read the whole model and make sure that the original data is still there (i.e. the same as what was done by
testInstallIntoController()
WildFly 9
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type").hasDefined("foo"));
Assert.assertTrue(model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME, "type",
"foo").hasDefined("tick"));
Assert.assertEquals(1000, model.get(SUBSYSTEM, SubsystemExtension.SUBSYSTEM_NAME,
"type", "foo", "tick").asLong());
//Call write-attribute
ModelNode writeOp = new ModelNode();
writeOp.get(OP).set(WRITE_ATTRIBUTE_OPERATION);
writeOp.get(OP_ADDR).set(fooTypeAddr.toModelNode());
writeOp.get(NAME).set("tick");
writeOp.get(VALUE).set(3456);
result = services.executeOperation(writeOp);
Assert.assertEquals(SUCCESS, result.get(OUTCOME).asString());
To give you exposure to other ways of doing things, now instead of reading the whole model to check the
attribute, we call read-attribute instead, and make sure it has the value we set it to.
//Check that write attribute took effect, this time by calling read-attribute instead of reading
the whole model
ModelNode readOp = new ModelNode();
readOp.get(OP).set(READ_ATTRIBUTE_OPERATION);
readOp.get(OP_ADDR).set(fooTypeAddr.toModelNode());
readOp.get(NAME).set("tick");
result = services.executeOperation(readOp);
Assert.assertEquals(3456, checkResultAndGetContents(result).asLong());
Since each type installs its own copy of TrackerService, we get the TrackerService for type=foo
from the service container exposed by the kernel services and make sure it has the right value
TrackerService service =
(TrackerService)services.getContainer().getService(TrackerService.createServiceName("foo")).getValue();
Assert.assertEquals(3456, service.getTick());
}
TypeDefinition.TICK.
WildFly 9
WildFly 9
WildFly 9
ResourceDescriptionResolver
TODO
Most commonly used implementation: StandardResourceDescriptionResolver
WildFly 9
11.9 Transformers
This guide is work in progress
----
WildFly 9
Model Transformer
Model transformer, works on top of current model and transforms its model to target version.
Operation Transformer
Operation transformer works on top of operations instead of model.
Testing transformers
There is testing framework in place for testing proper behavior of transformers
WildFly 9
11.10.2 Architecture
WildFly relies on MSC to provide the data source for the JNDI tree. Each resource bound in JNDI is stored in
a MSC service (BinderService), and such services are installed as children of subsystem/deployment
services, for an automatically unbound as consequence of uninstall of the parent services.
Since there is the need to know what entries are bound, and MSC does not provides that, there is also the
(ServiceBased)NamingStore concept, which internally manage the set of service names bound. There are
multiple naming stores in every WildFly instance, serving different JNDI namespaces:
java:comp - the standard EE namespace for entries scoped to a specific component, such as an EJB
java:module - the standard EE namespace for entries scoped to specific module, such as an EJB jar,
and shared by all components in it
java:app - the standard EE namespace for entries scoped to a specific application, i.e. EAR, and
shared by all modules in it
java:global - the standard EE namespace for entries shared by all deployments
java:jboss - a proprietary namespace "global" namespace
java:jboss/exported - a proprietary "global" namespace which entries are exposed to remote JNDI
java: - any entries not in the other namespaces
One particular implementation choice, to save resources, is that JNDI contexts by default are not bound, the
naming stores will search for any entry bound with a name that is a child of the context name, if found then
its assumed the context exists.
The reworked implementation introduces shared/global java:comp, java:module and java:app namespaces.
Any entry bound on these will automatically be available to every EE deployment scoped instance of these
namespaces, what should result in a significant reduction of binder services, and also of EE deployment
processors. Also, the Naming subsystem may now configure bind on these shared contexts, and these
contexts will be available when there is no EE component in the invocation, which means that entries such
as java:comp/DefaultDatasource will always be available.
WildFly 9
Subsystem
At the lowest level a JNDI entry is bound by installing a BinderService to a ServiceTarget:
/**
* Binds a new entry to JNDI.
* @param serviceTarget the binder service's target
* @param name the new JNDI entry's name
* @param value the new JNDI entry's value
*/
private ServiceController<?> bind(ServiceTarget serviceTarget, String name, Object value) {
// the bind info object provides MSC service names to use when creating the binder service
final ContextNames.BindInfo bindInfo = ContextNames.bindInfoFor(name);
final BinderService binderService = new BinderService(bindInfo.getBindName());
// the entry's value is provided by a managed reference factory,
// since the value may need to be obtained on lookup (e.g. EJB reference)
final ManagedReferenceFactory managedReferenceFactory = new
ImmediateManagedReferenceFactory(value);
return serviceTarget
// add binder service to specified target
.addService(bindInfo.getBinderServiceName(), binderService)
// when started the service will be injected with the factory
.addInjection(binderService.getManagedObjectInjector(), managedReferenceFactory)
// the binder service depends on the related naming store service,
// and on start/stop will add/remove its service name
.addDependency(bindInfo.getParentContextServiceName(),
ServiceBasedNamingStore.class,
binderService.getNamingStoreInjector())
.install();
}
But the example above is the simplest usage possible, it may become quite complicated if the entry's value
is not immediately available, for instance it is a value in another MSC service, or is a value in another JNDI
entry. It's also quite easy to introduce bugs when working with the service names, or incorrectly assume that
other MSC functionality, such as alias names, may be used.
Using the new high level API, it's as simple as:
WildFly 9
If there is the need to access the binder's service builder, perhaps to add a service verification handler or
simply not install the binder service right away:
ContextNames.bindInfoFor("java:comp/ORB").builder(serviceTarget, verificationHandler,
ServiceController.Mode.ON_DEMAND).installService(this.orb);
EE Deployment
With respect to EE deployments, the subsystem API should not be used, since bindings may need to be
discarded/overridden, thus a EE deployment processor should add a new binding in the form of a
BindingConfiguration, to the EeModuleDescription or ComponentDescription, depending if the bind is
specific to a component or not. An example of a deployment processor adding a binding:
WildFly 9
A deployment processor may now also add a binding configuration to all components in a module:
moduleDescription.getBindingConfigurations().addPlatformBindingToAllComponents(bindingConfiguration);
WildFly 9
In the reworked implementation there is now no need to behave differently considering the
deployment type, for instance if deployment is a WAR or app client, the Module/Component
BindingConfigurations objects handle all of that. The processor should simply go for the 3 use
cases: module binding, component binding or binding shared by all components.
All deployment binding configurations MUST be added before INSTALL phase, this is needed
because on such phase, when the bindings are actually done, there must be a final set of
deployment binding names known, such information is need to understand if a resource injection
targets entries in the global or scoped EE namespaces.
Most cases for adding bindings to EE deployments are in the context of a processor deploying a XML
descriptor, or scanning deployment classes for annotations, and there abstract types, such as the
AbstractDeploymentDescriptorBindingsProcessor, which simplifies greatly the processor code for such use
cases.
One particular use case is the parsing of EE Resource Definitions, and the reworked implementation
provides high level abstract deployment processors for both XML descriptor and annotations, an example for
each:
WildFly 9
/**
* Deployment processor responsible for processing administered-object deployment descriptor
elements
*
* @author Eduardo Martins
*/
public class AdministeredObjectDefinitionDescriptorProcessor extends
ResourceDefinitionDescriptorProcessor {
@Override
protected void processEnvironment(RemoteEnvironment environment,
ResourceDefinitionInjectionSources injectionSources) throws DeploymentUnitProcessingException {
final AdministeredObjectsMetaData metaDatas = environment.getAdministeredObjects();
if (metaDatas != null) {
for(AdministeredObjectMetaData metaData : metaDatas) {
injectionSources.addResourceDefinitionInjectionSource(getResourceDefinitionInjectionSource(metaData));
}
}
}
private ResourceDefinitionInjectionSource getResourceDefinitionInjectionSource(final
AdministeredObjectMetaData metaData) {
final String name = metaData.getName();
final String className = metaData.getClassName();
final String resourceAdapter = metaData.getResourceAdapter();
final AdministeredObjectDefinitionInjectionSource resourceDefinitionInjectionSource =
new AdministeredObjectDefinitionInjectionSource(name, className, resourceAdapter);
resourceDefinitionInjectionSource.setInterface(metaData.getInterfaceName());
if (metaData.getDescriptions() != null) {
resourceDefinitionInjectionSource.setDescription(metaData.getDescriptions().toString());
}
resourceDefinitionInjectionSource.addProperties(metaData.getProperties());
return resourceDefinitionInjectionSource;
}
}
and
WildFly 9
/**
* Deployment processor responsible for processing {@link
javax.resource.AdministeredObjectDefinition} and {@link
javax.resource.AdministeredObjectDefinitions}.
*
* @author Jesper Pedersen
* @author Eduardo Martins
*/
public class AdministeredObjectDefinitionAnnotationProcessor extends
ResourceDefinitionAnnotationProcessor {
private static final DotName ANNOTATION_NAME =
DotName.createSimple(AdministeredObjectDefinition.class.getName());
private static final DotName COLLECTION_ANNOTATION_NAME =
DotName.createSimple(AdministeredObjectDefinitions.class.getName());
@Override
protected DotName getAnnotationDotName() {
return ANNOTATION_NAME;
}
@Override
protected DotName getAnnotationCollectionDotName() {
return COLLECTION_ANNOTATION_NAME;
}
@Override
protected ResourceDefinitionInjectionSource processAnnotation(AnnotationInstance
annotationInstance) throws DeploymentUnitProcessingException {
final String name = AnnotationElement.asRequiredString(annotationInstance,
AnnotationElement.NAME);
final String className = AnnotationElement.asRequiredString(annotationInstance,
"className");
final String ra = AnnotationElement.asRequiredString(annotationInstance,
"resourceAdapter");
final AdministeredObjectDefinitionInjectionSource
directAdministeredObjectInjectionSource =
new AdministeredObjectDefinitionInjectionSource(name, className, ra);
directAdministeredObjectInjectionSource.setDescription(AnnotationElement.asOptionalString(annotationInstance,
AdministeredObjectDefinitionInjectionSource.DESCRIPTION));
directAdministeredObjectInjectionSource.setInterface(AnnotationElement.asOptionalString(annotationInstance,
AdministeredObjectDefinitionInjectionSource.INTERFACE));
directAdministeredObjectInjectionSource.addProperties(AnnotationElement.asOptionalStringArray(annotationInstan
AdministeredObjectDefinitionInjectionSource.PROPERTIES));
return directAdministeredObjectInjectionSource;
}
}
WildFly 9
The abstract processors with respect to Resource Definitions are already submitted through
WFLY-3292's PR.
WildFly 9
12 Common
12.1 All WildFly 9 documentation
There are several guides in the WildFly 9 documentation series. This list gives an overview of each of the
guides:
*Getting Started Guide - Explains how to download and start WildFly 9.
*Getting Started Developing Applications Guide - Talks you through developing your first applications on
WildFly 9, and introduces you to JBoss Tools and how to deploy your applications.
*JavaEE 6 Tutorial - A Java EE 6 Tutorial.
*Admin Guide - Tells you how to configure and manage your WildFly 9 instances.
*Developer Guide - Contains concepts that you need to be aware of when developing applications for
WildFly 9. Classloading is explained in depth.
*High Availability Guide - Reference guide for how to set up clustered WildFly 9 instances.
*Extending WildFly - A guide to adding new functionality to WildFly 9.
WildFly 9
13 Testsuite
13.1 JBoss AS 7 Testsuite
Where to go next?
WildFly Integration Testsuite User Guide if you changed JBoss AS 7 code and want to check for
regressions.
AS 7 Testsuite Harness Developer Guide to learn how the testsuite works (shell scripts, Ant scripts,
pom.xml files)
AS 7 Testsuite Test Developer Guide if you want to add a new test case to the testsuite (to increase
code coverage or to reproduce a bug)
WildFly 9
WildFly 9
13.2.2 Profiles
You should not activate the abovementioned profiles by -P, because that disables other profiles which are
activated by default.
Instead, you should always use activating properties, which are in parenthesis in the lists below.
Testsuite profiles are used to group tests into logical groups.
all-modules.module.profile (all-modules)
integration.module.profile (integration.module)
compat.module.profile
(compat.module)
domain.module.profile
(domain.module)
benchmark.module.profile (benchmark.module)
stress.module.profile
(stress.module)
They also pprepare WildFly instances and resources for respective testsuite submodules.
jpda.profile - sets surefire.jpda.args
(debug)
ds.profile -sets database properties and prepares the datasource (ds=<db id>)
Has related database-specific profiles, like mysql51.profile etc.
Integration testsuite profiles configure surefire executions.
smoke.integration.tests.profile
basic.integration.tests.profile
clustering.integration.tests.profile
WildFly 9
-Dts.smoke, -Dts.noSmoke
Basic
-Dts.basic
Basic integration tests - those which do not need special configuration like cluster.
Divided into three Surefire executions:
One with full profile,
Second with web profile (majority of tests).
Third with web profile, but needs to be run after server restart to check whether persistent data are
really persisted.
Cluster
-Dts.clust
IIOP
-Dts.iiop
XTS
-Dts.XTS
Multinode
-Dts.multinode
WildFly 9
WildFly 9
Testsuite structure
testsuite
integration
smoke
basic
clust
iiop
multinode
xts
compat
domain
mixed-domain
stress
benchmark
Test groups
To define groups of tests to be run, these properties are available:
-DallTests
-DallInteg
-Dts.clust
- Clustering tests.
-Dts.iiop
- IIOP tests.
-Dts.multinode
- Benchmark tests.
-Dts.stress
- Stress tests.
-Dts.domain
-Dts.compat
- Compatibility tests.
WildFly 9
13.3.2 Examples
integration-tests.sh [install]
integration-tests.sh clean install
-- Same as above.
-- Runs all
testsuite tests.
integration-tests.sh install -Dts.stress
-- Runs stress
tests only.
Pure maven - if you prefer not to use scripts, you may achieve the same result with:
mvn ... -rf testsuite
The -rf ... parameter stands for "resume from" and causes Maven to run the specified module and all
successive.
It's possible to run only a single module (provided the ancestor modules were already run to create the AS
copies) :
mvn ... -pl testsuite/integration/cluster
The -pl ... parameter stands for "project list" and causes Maven to run the specified module only.
Output to console
-DtestLogToFile
Other options
-DnoWebProfile - Run all tests with the full profile (standalone-full.xml). By default, most tests are
run under web profile (standalone.xml).
-Dts.skipTests - Skip testsuite's tests. Defaults to the value of -DskipTests, which defaults to false.
To build AS, skip unit tests and run testsuite, use -DskipTests -Dts.skipTests=false.
WildFly 9
Timeouts
Surefire execution timeout
Unfortunatelly, no math can be done in Maven, so instead of applying a timeout ratio, you need to specify
timeout manually for Surefire.
-Dsurefire.forked.process.timeout=900
-Dtimeout.ratio.fsio=100
-Dtimeout.ratio.netio=100
-Dtimeout.ratio.memio=100
-Dtimeout.ratio.proc=100
-Dtimeout.ratio.db=100
WildFly 9
# No need for
WildFly 9
<mirror>
<id>eap6-mirror-setting</id>
<mirrorOf>
*,!central-eap6,!central-eap6-plugins,!jboss-public-eap6,!jboss-public-eap6-plugins
</mirrorOf>
<name>Mirror Settings for EAP 6 build</name>
<url>file:///opt/jboss/eap6-maven-repo</url>
</mirror>
</mirrors>
2) Build EAP. You won't use the resulting EAP build, though. The purpose is to get the artifacts which the
testsuite depends on.
3) Run the testsuite. Assuming that EAP is located in /opt/eap6, you would run:
For further information on building EAP and running the testsuite against it, see the official EAP
documentation (link to be added).
How-to for EAP QA can be found here (Red Hat internal only).
WildFly 9
What will start with debugger Default port Port change arg.
-Ddebug
-Djpda
AS CLI
8787
-Ddebug.port.as=...
5050
-Ddebug.port.surefire=...
5051
-Ddebug.port.cli=...
Examples
./integration-tests.sh install -DdebugClient -Ddebug.port.surefire=4040
...
------------------------------------------------------T E S T S
------------------------------------------------------Listening for transport dt_socket at address: 4040
JBoss AS is started by Arquillian, when the first test which requires given instance is run. Unless
you pass -DtestLogToFile=false, there's (currently) no challenge text in the console; it will
look like the first test is stuck. This is being solved in
http://jira.codehaus.org/browse/SUREFIRE-781.
Depending on which test group(s) you run, multiple AS instances may be started. In that case, you
need to attach the debugger multiple times.
WildFly 9
-Dds.jdbc.driver=
-Dds.jdbc.driver.version=
-Dds.jdbc.url=
-Dds.jdbc.user=test
-Dds.jdbc.pass=test
-Dds.jdbc.driver.jar=${ds.db}-jdbc-driver.jar
driver is JDBC driver class. JDBC url, user and pass is as expected.
driver.version is used for automated JDBC driver downloading. Users can set up internal Maven
repository hosting JDBC drivers, with artifacts with
GAV = jdbcdrivers:${ds.db}:${ds.jdbc.driver.version}
Internally, JBoss has such repo at
http://nexus.qa.jboss.com:8081/nexus/content/repositories/thirdparty/jdbcdrivers/ .
The ds.db value is set depending on ds. E.g. -Dds=mssql2005 sets ds.db=mssql (since they have the
same driver). -Dds.db may be overriden to use different driver.
In case you don't want to use such driver, set just -Dds.db= (empty) and provide the driver to the AS
manually.
Not supported; work in progress on parameter to provide JDBC Driver jar.
Default values
For WildFly continuous integration, there are some predefined values for some of databases, which can be
set using:
-Dds.db=<database-identifier>
WildFly 9
IPv4
default
IPv6
default
-Dnode0
127.0.0.1
::1
Single-node tests.
-Dnode1
127.0.0.1
::1
ff01::1
-Dmcast.jgroupsDiag 224.0.75.75
ff01::2
224.0.1.105
ff01::3
-Dmcast
-Dmcast.modcluster
230.0.0.4
Values are set in AS configuration XML, replaced in resources (like ejb-jar.xml) and used in tests.
WildFly 9
./integration-tests.sh site
Note that it will take all test results under testsuite/integration/ - the pattern is **/*TestCase.xml
, without need to specify -DallTests.
Usage
./build.sh clean install -DskipTests
./integration-tests.sh clean install -DallTests -Dcoverage
./integration-tests.sh site -DallTests -Dcoverage ## Must run in separatedly.
Alternative:
WildFly 9
mvn clean install -DskipTests -DallTests ## ...to clean all testsuite modules.
mvn dependency:purge-local-repository build-helper:remove-project-artifact
-Dbuildhelper.removeAll
In case the build happens in a shared environment (e.g. network disk), it's recommended to use local
repository:
cp /home/hudson/.m2/settings.xml .
sed
"s|<settings>|<settings><localRepository>/home/ozizka/hudson-repos/$JOBNAME</localRepository>|"
-i settings.xml
Or:
WildFly 9
Database failures
Build gets stuck at first test of a module
If you use NFS (Network file system), it might be a file locking issue.
Try running using a local disk.
WildFly 9
WildFly 9
IP settings
${ip.server.stack} - used in <systemPropertyVariables> / <server.jvm.args> which
is used in *-arquillian.xml.
Testsuite directories
${jbossas.ts.integ.dir}
${jbossas.ts.dir}
${jbossas.project.dir}
Clustering properties
node0
node1
WildFly 9
- default
<surefire.jpda.args>-Xrunjdwp:transport=dt_socket,address=${as.debug.port},server=y,suspend=y</surefire.jpda.a
- activated by -Ddebug or -Djpda
testsuite/pom.xml:
<surefire.system.args>... ${surefire.jpda.args}
...</surefire.system.args>
testsuite/pom.xml:
testsuite/integration/pom.xml:
<jboss.options>${surefire.system.args}</jboss.options>
<server.jvm.args>${surefire.system.args}
integration/pom.xml:
<server.jvm.args>${surefire.system.args} ${jvm.args.ip.server} ${jvm.args.security}
${jvm.args.timeouts} -Dnode0=${node0} -Dnode1=${node1} -DudpGroup=${udpGroup}
${jvm.args.dirs}</server.jvm.args>
arquillian.xml:
<property name="javaVmArguments">${server.jvm.args}
-Djboss.inst=${basedir}/target/jbossas</property>
WildFly 9
<ant antfile="$\{basedir}/src/test/scripts/basic-integration-build.xml">
<target name="build-basic-integration"/>
<target name="build-basic-integration-jts"/>
</ant>
Which invokes
Which invokes
WildFly 9
maven-help-plugin
xx
properties-maven-plugin:write-project-properties x
maven-antrun-plugin:1.6:run (banner)
process-resources
maven-resources-plugin:2.5:resources
xx
(default-resources)
maven-dependency-plugin:2.3:copy
(copy-annotations-endorsed)
xx!
compile
maven-compiler-plugin:2.3.2:compile
(default-compile)
xx
generate-test-resources
maven-resources-plugin:2.5:copy-resources
xx!
(build-jbossas.server)
Should be:
maven-resources-plugin:2.5:copy-resources
(ts.copy-jbossas)
maven-resources-plugin:2.5:copy-resources
(ts.copy-jbossas.groups)
Should be:
xx
x!?
process-test-resources
maven-resources-plugin:2.5:testResources
(default-testResources)
xx
maven-antrun-plugin:1.6:run
(build-smoke.server)
maven-antrun-plugin:1.6:run
(prepare-jars-basic-integration.server)
maven-antrun-plugin:1.6:run
(build-clustering.server)
test-compile
maven-compiler-plugin:2.3.2:testCompile
(default-testCompile)
xx
xml-maven-plugin:1.0:transform
(update-ip-addresses-jbossas.server)
WildFly 9
maven-antrun-plugin:1.6:run (build-jars)
test
maven-surefire-plugin:2.10:test
(smoke-full.surefire)
maven-surefire-plugin:2.10:test
(smoke-web.surefire)
maven-surefire-plugin:2.10:test (default-test)
maven-surefire-plugin:2.10:test
(basic-integration-default-full.surefire)
maven-surefire-plugin:2.10:test
(basic-integration-default-web.surefire)
maven-surefire-plugin:2.10:test
(basic-integration-2nd.surefire)
maven-surefire-plugin:2.10:test
(tests-clust-multi-node-unm...surefire)
maven-surefire-plugin:2.10:test
(tests-clustering-single-node.surefire)
maven-surefire-plugin:2.10:test
(tests-clustering-multi-node.surefire)
maven-surefire-plugin:2.10:test
(tests-iiop-multi-node.surefire)
package
maven-jar-plugin:2.3.1:jar (default-jar)
xx!
maven-source-plugin:2.1.2:jar-no-fork
(attach-sources)
install
maven-install-plugin:2.3.1:install (default-install)
xx!
TS integ smoke basic clust iiop comp domain bench
WildFly 9
##
##
##
##
cat $1 \
| egrep ' --- |Building| ---------|Tests run: | T E S T S' \
| grep -v 'Time elapsed'
| sed 's|Tests run:|
Tests run:|' \
| grep -v maven-clean-plugin \
| grep -v maven-enforcer-plugin \
| grep -v buildnumber-maven-plugin \
| grep -v maven-help-plugin \
| grep -v properties-maven-plugin:.*:write-project-properties \
;
WildFly 9
applies ${xslt.scripts.dir}/changeIPAddresses.xsl on
${basedir}/target/jbossas/standalone/configuration/standalone-*.xml
Currently inherited, IMO should not be.
[INFO] --- maven-source-plugin:2.1.2:jar-no-fork (attach-sources) @ jboss-as-testsuite --TODO: Remove
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @ jboss-as-testsuite --[INFO] -----------------------------------------------------------------------[INFO] Building JBoss Application Server Test Suite: Integration Aggregator 7.1.0.CR1-SNAPSHOT
[INFO] -----------------------------------------------------------------------[INFO] --- maven-dependency-plugin:2.3:copy (copy-annotations-endorsed) @
jboss-as-testsuite-integration-agg --[INFO] --- maven-resources-plugin:2.5:copy-resources (build-jbossas.server) @
jboss-as-testsuite-integration-agg --TODO: Remove
[INFO] --- maven-resources-plugin:2.5:copy-resources (ts.copy-jbossas) @
jboss-as-testsuite-integration-agg --[INFO] --- maven-resources-plugin:2.5:copy-resources (ts.copy-jbossas.groups) @
jboss-as-testsuite-integration-agg --[INFO] --- xml-maven-plugin:1.0:transform (update-ip-addresses-jbossas.server) @
jboss-as-testsuite-integration-agg --TODO: Remove
[INFO] --- maven-source-plugin:2.1.2:jar-no-fork (attach-sources) @
jboss-as-testsuite-integration-agg --TODO: Remove
[INFO] --- maven-install-plugin:2.3.1:install (default-install) @
jboss-as-testsuite-integration-agg --[INFO] -----------------------------------------------------------------------[INFO] Building JBoss AS Test Suite: Integration - Smoke 7.1.0.CR1-SNAPSHOT
[INFO] -----------------------------------------------------------------------[INFO] --- maven-dependency-plugin:2.3:copy (copy-annotations-endorsed) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @
jboss-as-testsuite-integration-smoke --TODO: Remove
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-resources-plugin:2.5:copy-resources (build-jbossas.server) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-resources-plugin:2.5:copy-resources (ts.copy-jbossas.groups) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @
jboss-as-testsuite-integration-smoke --[INFO] --- xml-maven-plugin:1.0:transform (update-ip-addresses-jbossas.server) @
jboss-as-testsuite-integration-smoke --TODO: Remove
[INFO] --- maven-antrun-plugin:1.6:run (build-smoke.server) @
jboss-as-testsuite-integration-smoke --[echo] Building AS instance "smoke" from /home/ondra/work/EAP/EAP6-DR9 to
/home/ondra/work/AS7/ozizka-as7/testsuite/integration/smoke/target
TODO: Should be running one level above!
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-surefire-plugin:2.10:test (smoke-full.surefire) @
WildFly 9
jboss-as-testsuite-integration-smoke --T E S T S
Tests run: 4, Failures: 0, Errors: 4, Skipped: 0
WildFly 9
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-resources-plugin:2.5:copy-resources (build-jbossas.server) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-resources-plugin:2.5:copy-resources (ts.copy-jbossas.groups) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-antrun-plugin:1.6:run (build-smoke.server) @
jboss-as-testsuite-integration-smoke --[echo] Building AS instance "smoke" from
/home/ondra/work/AS7/ozizka-git/testsuite/integration/smoke/../../../build/target/jboss-as-7.1.0.Final-SNAPSHO
to /home/ondra/work/AS7/ozizka-git/testsuite/integration/smoke/target
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @
jboss-as-testsuite-integration-smoke --[INFO] --- maven-surefire-plugin:2.10:test (smoke-full.surefire) @
jboss-as-testsuite-integration-smoke --T E S T S
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
[INFO] --- maven-surefire-plugin:2.10:test (smoke-web.surefire) @
jboss-as-testsuite-integration-smoke --T E S T S
Tests run: 116, Failures: 0, Errors: 0, Skipped: 6
WildFly 9
jboss-as-testsuite-integration-clust --[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @
jboss-as-testsuite-integration-clust --[INFO] --- maven-resources-plugin:2.5:copy-resources (build-jbossas.server) @
jboss-as-testsuite-integration-clust --[INFO] --- maven-resources-plugin:2.5:copy-resources (ts.copy-jbossas.groups) @
jboss-as-testsuite-integration-clust --[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @
jboss-as-testsuite-integration-clust --[INFO] --- maven-antrun-plugin:1.6:run (build-clustering.server) @
jboss-as-testsuite-integration-clust --[echo] Building config clustering-udp-0
[echo] Building AS instance "clustering-udp-0" from
/home/ondra/work/AS7/ozizka-git/testsuite/integration/clust/../../../build/target/jboss-as-7.1.0.Final-SNAPSHO
to /home/ondra/work/AS7/ozizka-git/testsuite/integration/clust/target
[echo] Building config clustering-udp-1
[echo] Building AS instance "clustering-udp-1" from
/home/ondra/work/AS7/ozizka-git/testsuite/integration/clust/../../../build/target/jboss-as-7.1.0.Final-SNAPSHO
to /home/ondra/work/AS7/ozizka-git/testsuite/integration/clust/target
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @
jboss-as-testsuite-integration-clust --[INFO] --- maven-surefire-plugin:2.10:test (tests-clustering-multi-node-unmanaged.surefire) @
jboss-as-testsuite-integration-clust --T E S T S
Tests run: 9, Failures: 0, Errors: 0, Skipped: 0
[INFO] --- maven-surefire-plugin:2.10:test (tests-clustering-single-node.surefire) @
jboss-as-testsuite-integration-clust --T E S T S
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] --- maven-surefire-plugin:2.10:test (tests-clustering-multi-node.surefire) @
jboss-as-testsuite-integration-clust --T E S T S
Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
/home/ondra/work/AS7/ozizka-git/testsuite/integration/iiop/../../../build/target/jboss-as-7.1.0.Final-SNAPSHOT
WildFly 9
to /home/ondra/work/AS7/ozizka-git/testsuite/integration/iiop/target
[echo] Building config iiop-server
[echo] Building AS instance "iiop-server" from
/home/ondra/work/AS7/ozizka-git/testsuite/integration/iiop/../../../build/target/jboss-as-7.1.0.Final-SNAPSHOT
to /home/ondra/work/AS7/ozizka-git/testsuite/integration/iiop/target
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @
jboss-as-testsuite-integration-iiop --[INFO] --- maven-surefire-plugin:2.10:test (tests-iiop-multi-node.surefire) @
jboss-as-testsuite-integration-iiop --T E S T S
Tests run: 12, Failures: 0, Errors: 0, Skipped: 0
WildFly 9
/home/ondra/work/AS7/ozizka-git/testsuite/domain/target/jboss-as-testsuite-integration-domain-7.1.0.Final-SNAP
--- maven-install-plugin:2.3.1:install (default-install) @ jboss-as-testsuite-integration-domain
--[INFO] -----------------------------------------------------------------------[INFO] Building JBoss Application Server Test Suite: Benchmark Tests 7.1.0.Final-SNAPSHOT
[INFO] -----------------------------------------------------------------------[INFO] --- maven-dependency-plugin:2.3:copy (copy-annotations-endorsed) @
jboss-as-testsuite-benchmark --[INFO] --- maven-resources-plugin:2.5:resources (default-resources) @
jboss-as-testsuite-benchmark --[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ jboss-as-testsuite-benchmark
--[INFO] --- maven-resources-plugin:2.5:copy-resources (build-jbossas.server) @
jboss-as-testsuite-benchmark --[INFO] --- maven-resources-plugin:2.5:testResources (default-testResources) @
jboss-as-testsuite-benchmark --[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @
jboss-as-testsuite-benchmark --[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ jboss-as-testsuite-benchmark --T E S T S
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
/home/ondra/work/AS7/ozizka-git/testsuite/stress/target/jboss-as-testsuite-stress-7.1.0.Final-SNAPSHOT.jar[INF
--- maven-install-plugin:2.3.1:install (default-install) @ jboss-as-testsuite-stress --[INFO] -----------------------------------------------------------------------[INFO] -----------------------------------------------------------------------[INFO] -----------------------------------------------------------------------[INFO] ------------------------------------------------------------------------
WildFly 9
13.5.1 requisites
Please be sure to read Pre-requisites - test quality standards and follow those guidelines.
TBD
WildFly 9
<arquillian>
<container qualifier="test" mode="manual" />
</arquillian>
See Arquillian's Resource Injection docs for more info, https://github.com/arquillian/arquillian-examples for
examples.
See also Arquillian Reference.
Note to @ServerSetup annotation: It works as expected only on non-manual containers. In case of manual
mode containers it calls setup() method after each server start up which is right (or actually before
deployment), but the tearDown() method is called only at AfterClass event, i.e. usually after your manual
shutdown of the server. Which limits you on the ability to revert some configuration changes on the server
and so on. I cloned the annotation and changed it to fit the manual mode, but it is still in my github branch :)
WildFly 9
jbossas.ts.dir
- Testsuite dir.
jbossas.ts.integ.dir - Testsuite's integration module dir.
jboss.dist
- Path to AS distribution, either built (build/target/jboss-as-...) or user-provided via
-Djboss.dist
jboss.inst
- (Arquillian in-container only) Path to the AS instance in which the test is
running (until ARQ-650 is possibly done)
jboss.home
Networking
node0
node1
230.0.0.4
WildFly 9
WildFly 9
https://jenkins.mw.lab.eng.bos.redhat.com/hudson/job/wildfly-as-testsuite-RHEL-matrix-openJDK7/lastCompletedBu
.
If any tests fail and they do not fail in master, fix it and go back to the "Fetch" step.
Push to a new branch in your GitHub repo: git push origin WFLY-1234-new-XY-tests
Create a pull-request on GitHub. Go to your branch and click on "Pull Request".
If you have a jira, start the title with it, like - WFLY-1234 New tests for XYZ.
If you don't, write some apposite title. In the description, describe in detail what was done and
why should it be merged. Keep in mind that the diff will be visible under your description.
Keep the branch rebased daily until it's merged (see the Fetch step). If you don't, you're
dramatically decreasing chance to get it merged.
There's a mailing list, jbossas-pull-requests, which is notified of every pull-request.
You might have someone with merge privileges to cooperate with you, so they know what you're
doing, and expect your pull request.
When your pull request is reviewed and merged, you'll be notified by mail from GitHub.
You may also check if it was merged by the following: git fetch upstream; git cherry
<branch>
Your commits will appear in master. They will have the same hash as in your branch.
You are now safe to delete both your local and remote branches: git branch -D
WFLY-1234-your-branch; git push origin :WFLY-1234-your-branch
WildFly 9
WildFly 9
If you don't understand what a test is doing (perhaps too complex), or
it's going about things in a strange way that might not be correct, THEN
DO NOT PORT IT. Instead we should have a simpler, understandable, and
correct test. Write a new one, ping the author, or skip it altogether.
WildFly 9
The EE spec is full of odd requirements. If the test is covering
behavior that is not obvious then please add something like "Verifies EE
X.T.Z - The widget can't have a foobar if it is declared like blah"
WildFly 9
junit.framework.AssertionFailedError
at junit.framework.Assert.fail(Assert.java:48) [arquillian-service:]
at junit.framework.Assert.assertTrue(Assert.java:20) [arquillian-service:]
at junit.framework.Assert.assertTrue(Assert.java:27) [arquillian-service:]
at
org.jboss.as.test.smoke.embedded.parse.ParseAndMarshalModelsTestCase.getOriginalStandaloneXml(ParseAndMarshalM
[bogus.jar:]
Clean up
Close sockets, connections, file descriptors;
Don't put much data to static fields, or clean them in a finaly {...} block.
Don't alter AS config (unless you are absolutely sure that it will reload in a final {...} block or an
@After* method)
WildFly 9
WildFly 9
14 Quickstarts
WildFly ships with a number of quickstarts that show you how to get started with a variety of technologies in
WildFly. You'll find out how to write a web application using the latest Java EE technologies like CDI and
JAX-RS. How to write client libraries to talk to WildFly using web services, JMS or EJB. How to set up a
distributed transaction, and how to recover from a transaction failure. And much, much more.
14.2 Contributing
If you want to contribute to the quickstarts, check out our Contributing a Quickstart page.
WildFly 9