Monday, November 24, 2014

Run WildFly as a service on Windows

Go to bin\service directory; use an x64 file explorer so that the x64 service wrapper will be launched.

At a command prompt enter service install and press Enter. The service is now installed but need to be manually configured for Automatic start-up.

Note for WildFly 10: bin\service directory doesn't exist any more, it's content was moved in docs\contrib\scripts\service; the above described procedure is still valid but service must be copied to bin before applying it.

R28gdG8gYGJpblxzZXJ2aWNlYCBkaXJlY3Rvcnk7IHVzZSBhbiB4NjQgZmlsZSBleHBsb3JlciBzbyB0aGF0IHRoZSB4NjQgc2VydmljZSB3cmFwcGVyIHdpbGwgYmUgbGF1bmNoZWQuDQoNCkF0IGEgY29tbWFuZCBwcm9tcHQgZW50ZXIgYHNlcnZpY2UgaW5zdGFsbGAgYW5kIHByZXNzIEVudGVyLiBUaGUgc2VydmljZSBpcyBub3cgaW5zdGFsbGVkIGJ1dCBuZWVkIHRvIGJlIG1hbnVhbGx5IGNvbmZpZ3VyZWQgZm9yIEF1dG9tYXRpYyBzdGFydC11cC4NCg0KKipOb3RlIGZvciBXaWxkRmx5IDEwKio6IGBiaW5cc2VydmljZWAgZGlyZWN0b3J5IGRvZXNuJ3QgZXhpc3QgYW55IG1vcmUsIGl0J3MgY29udGVudCB3YXMgbW92ZWQgaW4gYGRvY3NcY29udHJpYlxzY3JpcHRzXHNlcnZpY2VgOyB0aGUgYWJvdmUgZGVzY3JpYmVkIHByb2NlZHVyZSBpcyBzdGlsbCB2YWxpZCBidXQgYHNlcnZpY2VgIG11c3QgYmUgY29waWVkIHRvIGBiaW5gIGJlZm9yZSBhcHBseWluZyBpdC4=

LDAP (AD) security domain in WildFly


Regarding the previous post we will change the authentication/authorization  realm to LDAP (actually AD).

Change the AD security domain as follows:


<security-domain name="AD" cache-type="default"> 
    <authentication> 
        <login-module code="LdapExtended" flag="required"> 
            <module-option name="java.naming.provider.url" value="ldap://mydomain.local:389"/> 
            <module-option name="java.naming.factory.initial" value="com.sun.jndi.ldap.LdapCtxFactory"/> 
            <module-option name="java.naming.security.authentication" value="simple"/> 
            <module-option name="bindDN" value="domain\user"/> 
            <module-option name="bindCredential" value="password"/> 
            <module-option name="baseCtxDN" value="OU=Organization,DC=dc1,DC=dc2"/> 
            <module-option name="baseFilter" value="(&amp;(objectClass=user)(sAMAccountName={0}))"/> 
            <module-option name="rolesCtxDN" value="OU=Groups,OU=Organization,DC=dc1,DC=dc2"/> 
            <module-option name="roleFilter" value="(&amp;(objectClass=group)(member={1}))"/> 
            <module-option name="roleAttributeID" value="cn"/> 
            <module-option name="roleNameAttributeID" value="cn"/> 
            <module-option name="roleRecursion" value="0"/> 
            <module-option name="defaultRole" value="authenticateduser"/> 
            <module-option name="throwValidateError" value="true"/> 
            <module-option name="java.naming.referral" value="follow"/> 
            <module-option name="referralUserAttributeIDToCheck" value="uniqueMember"/> 
        </login-module> 
        <login-module code="RoleMapping" flag="required"> 
            <module-option name="rolesProperties" value="file:${jboss.server.config.dir}/ad.properties"/> 
            <module-option name="replaceRole" value="false"/> 
        </login-module> 
    </authentication> 
</security-domain>

ad.properties file specifies mappings between groups (the property name) and roles (comma separated values)
Please notice the almost not specified option defaultRole which adds an implicit role to authenticated users.







Sunday, November 23, 2014

From GlassFish 3.2 to WildFly 8.2

Source environment:

  • GlassFish 3.2
  • SQL Server
  • EclipseLink
Download and explode WildFly zip archieve.

DataSource 

In order to configure SQL Server based DataSource we need to add a module in WildFly:
  • create modules\system\layers\base\com\microsoft\sqlserver\jdbc\main (it not manadatory to have this name but it must be a subdirectory of modules...?)
  • copy sqljdbc4.jar in thsi subdirectory
  • create a module.xml with the following content:
<?xml version="1.0" encoding="utf-8"?> 
<module xmlns="urn:jboss:module:1.3" name="com.microsoft.sqlserver.jdbc"> 
  <resources> 
    <resource-root path="sqljdbc4.jar"/> 
  </resources> 
  <dependencies> 
    <module name="javax.api"/> 
    <module name="javax.transaction.api"/> 
  </dependencies> 
</module>

  • in the drivers section of standalone\configuration\standalone.xml add the folowing sub-section:
 <driver name="sqlserver" module="com.microsoft.sqlserver.jdbc"> 
  <xa-datasource-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</xa-datasource-class> 
</driver>
  • in the datasources section add the following sub-section (change the default settings according to your needs):
<datasource jta="true" jndi-name="java:/MyPool" pool-name="MyPool" enabled="true" use-ccm="true"> 
  <connection-url>jdbc:sqlserver://127.0.0.1:1433;databaseName=MyDatabase;</connection-url> 
  <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class> 
  <driver>sqlserver</driver> 
  <security> 
    <user-name>myuser</user-name> 
    <password>mypassword</password> 
  </security> 
  <validation> 
    <validate-on-match>false</validate-on-match> 
    <background-validation>false</background-validation> 
  </validation> 
  <timeout> 
    <set-tx-query-timeout>false</set-tx-query-timeout> 
    <blocking-timeout-millis>0</blocking-timeout-millis> 
    <idle-timeout-minutes>0</idle-timeout-minutes> 
    <query-timeout>0</query-timeout> 
    <use-try-lock>0</use-try-lock> 
    <allocation-retry>0</allocation-retry> 
    <allocation-retry-wait-millis>0</allocation-retry-wait-millis> 
  </timeout> 
  <statement> 
    <share-prepared-statements>false</share-prepared-statements> 
  </statement> 
</datasource>

You can test your datasource from the management console now.

Please notice that WildFly will accept only jndi names that start with java:/ (or java:jboss..(?)) while the practice on Glassfish is to have (for datasources) jdbc as a prefix. Trying to change the name on Glassfish (starting with java: will induce huge performance issues (high CPU) )

JPA Provider

First attempt: tryed with proposed default JPA provider for WildFly: Hibernate. Worked fine till firtst attempt to access a  property with fetch type LAZY (the default). An exception was thrown claiming that  org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: <some collection type property>, could not initialize proxy - no Session
Since the solution found on the net were not acceptable (at first sight) I tried to switch back (explicitly) to EclipseLink:
  • Download latest EclipseLink.jar and place it in existing sub-directory: modules\system\layers\base\org\eclipse\persistence\main
  • modify the existing module.xml adding  <resource-root path="eclipselink.jar"/>
  • add (top level section) in standalone.xml:
 <system-properties>
  <property name="eclipselink.archive.factory" value="org.jipijapa.eclipselink.JBossArchiveFactoryImpl"/>
 </system-properties>

Without this property eclipselink will throw an exception about non-existing named queries at application runtime

Security Realm

The application used an security realm that was configured on Glassfish to use (for development purpose) a fileRealm. The easiest way to port this is to use a security domain based on RealmDirect (which in turn will use standard application-users.properties and application-roles.properties

                <security-domain name="AD" cache-type="default">
                    <authentication>
                        <login-module code="RealmDirect" flag="required">
                            <module-option name="password-stacking" value="useFirstPass"/>
                        </login-module>
                    </authentication>
                </security-domain>

To generate the test user(s) run add-user.bat, choose b option, provide username,password and comma separated roles when prompted.

For the application to use this security domain add <security-domain>AD</security-domain> in jboss-web.xml. Without it the default 'other' security domain will be used never mind the realm-name specification in web.xml




Saturday, February 22, 2014

Camel Groovy script validator for cxfEndpoint

This applies to Camel 2.12.1/2.12.2
Using a Groovy script as a validator for incoming messages received through an inbound cfxEndpoint has an erratic behaviour: sometimes the message body has the value of a previous message. This looks like being dependent on the thread allocated to process the message: if it is the original thread that processed the first incoming message (when the script was compiled) than the expected body content is OK, otherwise it is  the previous messages processed on that first thread.

Solution:

  • get the sources for camel-script-2.12.x
  • change in org.apache.camel.builder.script.ScriptBuilder:
    • from result = compiledScript.eval();
    • to result = compiledScript.eval(getScriptContext());
    • in runScript method
  • recompile the package and deploy it

Camel, cxf:cxfEndpoint and OTRS

When used as an outbound endpoint cxf:cxfEndpoint will use a default threshold of 4096 bytes to start switching from Content-Length based HTTP transfer to Transfer-Encoding: chunked. This behaviour can cause problems if targeted server does not support this behaviour (in particular OTRS/Apache default configuration does not).
Solution: add in Camel configuration file (outside camelContex tag) the following XML snippet:
  <http-conf:conduit name="*.http-conduit">
    <http-conf:client ChunkingThreshold="15000000" />
    <!--http-conf:client ="false" /-->
  </http-conf:conduit>

This will change the default treshold from 4096 bytes  to the value specified in ChunkingThreshold attribute. The most general option of AllowChunking didn't work for me (the outbound endpoint just freezes and no content is sent over the wire)

Controlling ApacheMQ through JMX

See http://activemq.apache.org/jmx.html; first option described ("The ActiveMQ broker should appear in the list of local connections, if you are running JConsole on the same host as ActiveMQ.") didnt't work for me (ActiveMQ was started as a service, maybe this was  the cause...)

So:

  • go into bin/win64 and edit wrapper.conf; uncomment the following lines:
    • wrapper.java.additional.16=-Dcom.sun.management.jmxremote.port=1616
    • wrapper.java.additional.17=-Dcom.sun.management.jmxremote.authenticate=false
    • wrapper.java.additional.18=-Dcom.sun.management.jmxremote.ssl=false
  • be aware that you need to change the default format so that 16,17 and 18 replace the original .n format (be aware that the sequence might be different depending on other changes you made to the conf file)
  • restart ActiveMQ
  • go to your JDK\bin directory and start jconsole.exe
  • provide the following URL for Remote Process:
    • service:jmx:rmi:///jndi/rmi://localhost:1616/jmxrmi
  • press Connect (do not fill in any data for user/password)
  • press Insecure on the pop-up
  • etc...
If secure connection is required (I suppose by changing the wrapper options accordingly) provide the user name/passord for the relevant role as configured in conf\jmx.access and conf\jmx.password


Debugging ApacheMQ/Camel


  • Change activemq.bat by removing comment for the following line:
    • SET ACTIVEMQ_DEBUG_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
  • start ActiveMQ through command line
  • create a Maven project with NetBeans
  • add the required dependencies to project according to the modules you want to debug (the sample is for ActiveMQ 5.9 and cxf, scripting/Groovy and stream):

    <dependencies>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-cxf</artifactId>
            <version>2.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-script</artifactId>
            <version>2.12.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-stream</artifactId>
            <version>2.12.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>2.7.8</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty.aggregate</groupId>
            <artifactId>jetty-all-server</artifactId>
            <version>8.1.14.v20131031</version>
        </dependency>            
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-websocket</artifactId>
            <version>8.1.14.v20131031</version>
        </dependency>
  • build the project so the dependencies are downloaded to local maven  repository
  • in NetBeans go to Dependencies and select Download Sources
  • in NetBeans go to Debug menu and choose Attach Debugger
  • chgange the port to 5005 (or whatever was specified in ACTIVEMQ_DEBUG_OPTS)
  • look for the desired package/class in Dependencies, open the class, place a breakpoint, etc