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

log4j.properties

Things to remember :-):

  • The  log4j.properties  is searched in the class path.
  • The rootLogger properties are inherited by all loggers in terms of appenders (if for instance it has a console appender all other defined loggers will have also this appender even if not specifically configured)
In order to configure your specific logger(s):
  • add the desired appender(s) (like below):
    • log4j.appender.myLog=org.apache.log4j.FileAppender
    • log4j.appender.myLog.File=logs/myLog.txt
    • log4j.appender.myLog.layout=org.apache.log4j.PatternLayout
    • log4j.appender.myLog.layout.conversionPattern=%-5p %d [%t] %c: %m%n
  • add the logger by specifying logging level and appender(s):
    • log4j.logger.myLog=DEBUG, myLog

The actual place where the logs will be generated depend on the implicit/explicit setting for the working directory of your application;  to have a more specific control over this behaviour you can use environment variables expansion like:

  • log4j.appender.file.File=${mule.home}/logs/mule-logging-example.log

Running ApacheMQ as a Windows service

After downloading/extracting ActiveMQ:

  • open a command window as administrator
  • place the right activemq.xml in conf directory (along with any other related config files like the one describing Camel context)
  • navigate to bin\win64 (do not try the win32 version, the service satrup will fail on x64 Windows)
  • edit wrapper.config by changing the working directory to:
    • wrapper.working.dir=%ACTIVEMQ_BASE%
  • (if not, the working directory will be win64)
  • run InstallService.bat
  • manually start the service (named ApacheMQ)

Run Mule ESB as a service on Windows

After downloading/extracting standalone version:

  • open a command line window (cmd.exe) as administrator
  • navigate to Mule bin directory
  • run mule install
  • check in Services that a service with Mule name exists; start the service
  • place any Mule packages (zip archive) in apps directory and wait for the deployment to occur (a subdirectory with exploded package content is created and a text file <package name>-anchor.txt is present)
  • you can control the service by running mule [start|stop|restart]
When running Mule as a service by default current path is set to the root directory of the expanded standalone package (on the same level with bin, apps, logs, etc) so if we have defined in log4j.properties
log4j.appender.MyLog.File=logs/MyLog.txt
teh MyLog.txt file will be created in logs subdirectory of the installation along with Mule standard log files (mule.log, etc)

Just supposing/not tried with Mule:  you can change the working path by adding an entry to conf/wrapper.conf, something like:
  • wrapper.working.dir="%MULE_HOME%/workingDir"

Be aware: if at start-up there are some unrecoverable errors Mule will try to undeploy the application by also deleting the exploded directory; since the original zip package was already deleted this means that your application will never be launched. To be more explicit:
  • we have a Mule application that uses as inbound endpoint an ActiveMQ JMS queue that is configured (by default) without the reconnect-forever option and with for the connector it references
  • First time when we configure Mule as a service the ActiveMQ broker is up so the application is deployed fine and works as expected
  •  For some maintenance activities we restart the server. Suppose that the Mule service comes up before ActiveMQ; the application start-up will fail and application will be deleted. The failure is due to the fact that Mule tries to activate the connector even before the flow that references it it is started.

Thursday, January 30, 2014

Camel cxfendpoint to ActiveMQ queue


  • cxfendpoint expects an outgoing message to be present in order to be sent back; if an out endpoint posting the message to an ActiveMQ  broker is used this will not happen and a timeout error will occur
  • By default output of cxfendpoint message  payload  is of java.io.InputStream. An outgoing ActiveMQ endpoint will just ignore the payload and will save just the headers.
Below is the solution to above mentioned problems 9this must be included in the master ActiveMQ configuration file):
<?xml version="1.0" encoding="UTF-8"?>
<!--
    Licensed to the Apache Software Foundation (ASF) under one or more
    contributor license agreements.  See the NOTICE file distributed with
    this work for additional information regarding copyright ownership.
    The ASF licenses this file to You under the Apache License, Version 2.0
    (the "License"); you may not use this file except in compliance with
    the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:cxf="http://camel.apache.org/schema/cxf"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
       http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd">


      <bean id="jmsConnectionFactory" 
         class="org.apache.activemq.ActiveMQConnectionFactory">
         <property name="brokerURL" value="vm://amq-broker?create=false" />
      </bean>
       
      <bean id="pooledConnectionFactory" 
         class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
         <property name="maxConnections" value="8" />
         <property name="connectionFactory" ref="jmsConnectionFactory" />
      </bean>
       
      <bean id="jmsConfig" 
         class="org.apache.camel.component.jms.JmsConfiguration">
         <property name="connectionFactory" ref="pooledConnectionFactory"/>
         <property name="concurrentConsumers" value="10"/>
      </bean>
       
      <bean id="activemq" 
          class="org.apache.activemq.camel.component.ActiveMQComponent">
          <property name="configuration" ref="jmsConfig"/>
       
          <!-- if we are using transacted then enable CACHE_CONSUMER (if not using XA) to run faster
               see more details at: http://camel.apache.org/jms 
          <property name="transacted" value="true"/>
          <property name="cacheLevelName" value="CACHE_CONSUMER" />
         -->
      </bean>      

    <!-- camelContext is the Camel runtime, where we can host Camel routes -->    
    <cxf:cxfEndpoint id="server"
                     address="http://localhost:8085/OTRS/service"
                     endpointName="s:BasicHttpBinding_ChangeStateOperations"
                     serviceName="s:ChangeStateService"
                     wsdlURL="examples\conf\wsdl\server.wsdl"
                     xmlns:s="http://tempuri.org/"/>
    
    
    
    <camelContext xmlns="http://camel.apache.org/schema/spring">
         <route>
            <from uri="cxf:bean:server?dataFormat=MESSAGE"/>
                <transform>
                  <simple>${bodyAs(String)}</simple>
                </transform>
                <wireTap uri="activemq:topic:otrs.statusChanged"/>
                <wireTap uri="stream:out"/>
                <transform>
                    <simple>
                        <![CDATA[
    <?xml version="1.0" encoding="utf-8"?>
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
        <TestWm1Response xmlns="http://tempuri.org/" />
      </s:Body>
    </s:Envelope>
                        ]]>
                    </simple>
                </transform>
            <!--to uri="cxf:bean:ocalculator?dataFormat=MESSAGE"/-->
        </route>
    </camelContext>
</beans>

Camel cxfenpoint in ActiveMQ 5.9.0

Using cxfendpoints in ActiveMQ requires deplyment of dependent jars in lib\Camel subdirectory. By default just core, jms and spring (2.12.1 version) are deployed.
In order to obtain required jars:

  • create a Maven pom.xml file with the following content:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>


    <groupId>org.apache.camel</groupId>

    <version>2.12.1</version>


    <artifactId>camel-example-console</artifactId>
    <packaging>jar</packaging>
    <name>Camel cxf</name>
    <description>camel-cxf dependencies</description>

    <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-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.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>
    </dependencies>

    <build>
        <plugins>
            <!-- Allows the example to be run via 'mvn compile exec:java' -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <configuration>
                    <mainClass>org.apache.camel.example.console.CamelConsoleMain</mainClass>
                    <includePluginDependencies>true</includePluginDependencies>
                </configuration>
            </plugin>
        </plugins>

    </build>

</project>
  • run the following command: mvn dependency:copy-dependencies
  • find in target\dependencies all required dependencies
Remark: because camel-cxf 2.12.1 depends on cxf-rt-transports-http-jetty 2.7.8 some newer versions of jetty jars will be aslo downloaded which will interfere with ActiveMQ already deployed jars (jetty-all-server and jetty-websocket, version 7.6.9.v20130131, lib\web ) so also jetty-all-server and jetty-websocket dependencies are downloaded. If this is not done web console will not work.

Put all jars in lib\camel.