Kohei Nozaki's blog 

jconsole.sh in WildFly 8.2.0.Final doesn't work


Posted on Thursday Feb 12, 2015 at 10:06AM in Technology


Environment

  • WildFly 8.2.0.Final

Problem

A shell script $WILDFLY_HOME/bin/jconsole.sh is shipped with WildFly to launch JConsole with an additional jar to connect to WildFly instance, but it doesn’t work. as reported in this issue, it made wrong classpath.

Workaround

Launch $JAVA_HOME/bin/jconsole directly instead with an additional parameter as follows:

jconsole -J-Djava.class.path=$JAVA_HOME/lib/jconsole.jar:$JAVA_HOME/lib/tools.jar:/Users/kyle/servers/wildfly-8.2.0.Final/bin/client/jboss-cli-client.jar


Defining Embedded Derby as a DataSource of Tomcat 8


Posted on Wednesday Feb 11, 2015 at 12:16AM in Technology


Configuration

  1. Put derby.jar into $CATALINA_HOME/lib

  2. Define a Resource element inside Context element in $CATALINA_HOME/conf/context.xml as follows:

    <Resource name="jdbc/derby" auth="Container"
    		  driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
    		  username="sa" password="sa"
    		  type="javax.sql.DataSource"
    		  url="jdbc:derby:/Users/kyle/tmp/sampledb;create=true"/>
  3. Clone derby-shutdown-listener, exec mvn clean package and put target/derby-shutdown-listener.jar into $CATALINA_HOME/lib

  4. Put following fragment into Server element in $CATALINA_HOME/conf/server.xml

    <Listener className="org.nailedtothex.derby.DerbyShutdownLifecycleListener" />

Test of lookup from Servlet

  1. Put following fragment into WEB-INF/web.xml of your web application

    <?xml version="1.0" encoding="UTF-8"?>
    <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">
        <resource-ref>
            <res-ref-name>jdbc/derby</res-ref-name>
            <res-type>javax.sql.DataSource</res-type>
            <res-auth>Container</res-auth>
        </resource-ref>
    </web-app>
  2. Put an example Servlet as follows

    @WebServlet(urlPatterns = "/")
    public class TestServlet extends HttpServlet {
    
        private Context context;
        private DataSource dataSource;
    
        @Override
        public void init() throws ServletException {
            try {
                context = new InitialContext();
                dataSource = (DataSource) context.lookup("java:comp/env/jdbc/derby");
            } catch (NamingException e) {
                throw new ServletException(e);
            }
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            try (Connection cn = dataSource.getConnection();
                 Statement st = cn.createStatement();
                 ResultSet rs = st.executeQuery("SELECT CURRENT_TIMESTAMP FROM SYSIBM.SYSDUMMY1")) {
                while (rs.next()) {
                    resp.getWriter().write(rs.getTimestamp(1).toString());
                }
            } catch (SQLException e) {
                throw new ServletException(e);
            }
        }
    
        @Override
        public void destroy() {
            if (context != null) {
                try {
                    context.close();
                } catch (NamingException e) {
                    // no-op
                }
            }
        }
    }
  3. Access from your browser


Complex string replacing on Java


Posted on Tuesday Feb 10, 2015 at 10:06PM in Technology


Sometimes annoying requirement of string replacing will risen. everytime I forgotten how to do it so I leave this as my note. also there’s a JUnit test case.

Requirement

Assume we have following string literals. we have to convert input string to expected.

String input = "<li><a href=\"../../jbatch/hello/\" >anchor</a></li>";
String expected = "<li><a href=\"/entry/articles-jbatch-hello\" >anchor</a></li>";

Solutions

Using numbered groups

Pattern p = Pattern.compile("(<a href=\")\\.\\./\\.\\./(.*)/(.*)/\"");
Matcher matcher = p.matcher(input);
String result = matcher.replaceAll("$1/entry/articles-$2-$3\"");

Using named groups

Pattern p = Pattern.compile("(?<prefix><a href=\")\\.\\./\\.\\./(?<category>.*)/(?<handle>.*)/\"");
Matcher matcher = p.matcher(input);
String result = matcher.replaceAll("${prefix}/entry/articles-${category}-${handle}\"");

Using Matcher#appendReplacement(). this one is most flexible.

Pattern p = Pattern.compile("(?<prefix><a href=\")(?<url>.*)\"");
Matcher matcher = p.matcher(input);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
	// any complex logic can be placed here
	String url = matcher.group("url");
	String[] urls = url.split("/");
	matcher.appendReplacement(sb, "${prefix}/entry/articles-" + urls[2] + "-" + urls[3] + "\"");
}
matcher.appendTail(sb);
String result = sb.toString();

Escaping special character for replacement

$ have special meaning for replacement string, but sometimes we may need to use $ as just a literal. for such case, we can use Matcher.quoteReplacement() for escaping $ character as follows:

String input = "../../jbatch/hello/";
String expected = "../../$1/${name}/";
Pattern p = Pattern.compile("(?<prefix>\\.\\./\\.\\.)/.*/.*/");
String result = p.matcher(input).replaceAll("${prefix}/" + Matcher.quoteReplacement("$1/${name}") + "/");


Enabling SSL for Apache/WildFly


Posted on Monday Feb 09, 2015 at 05:56PM in Technology


Environment

  • WildFly 8.2.0.Final

  • httpd-2.2.15-39.el6.centos.x86_64

  • CentOS 6.5

  • public.crt: begins with BEGIN CERTIFICATE

  • intermediate.crt: begins with BEGIN CERTIFICATE

  • private.key: begins with BEGIN RSA PRIVATE KEY

Edit /etc/httpd/conf.d/ssl.conf

SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCertificateFile /usr/local/ssl/public.crt
SSLCertificateKeyFile /usr/local/ssl/private.key
SSLCertificateChainFile /usr/local/ssl/intermediate.crt
SSLPassPhraseDialog exec:/usr/local/ssl/passphrase.sh

Put passphrase.sh

#!/bin/sh
echo "put the passphrase here"

Define an ajp-listener

Execute following command with jboss-cli:

/socket-binding-group=standard-sockets/socket-binding=https-external:add(port=443)
/subsystem=undertow/server=default-server/ajp-listener=myListener:add(socket-binding=ajp, redirect-socket="https-external", enabled=true)

Put /etc/httpd/conf.d/jk.conf

<VirtualHost *:80>
ProxyPass / ajp://localhost:8009/
ProxyPassReverse / http://www.example.org/
</VirtualHost>

Put following inside VirtualHost element of /etc/httpd/conf.d/ssl.conf

ProxyPass / ajp://localhost:8009/
ProxyPassReverse / https://www.example.org/


Configuring WildFly as a standalone HTTP/HTTPS server


Posted on Sunday Feb 08, 2015 at 12:23PM in Technology


Environment

  • WildFly 8.2.0.Final

Requirement

  • WildFly runs as a regular user owning process

  • WildFly listens port 8080 and 8443

  • iptables forwards 80 and 443 to ports of WildFly is listening

  • Record combined access_log equivalent on http/https listener

  • Gzip compression enabled

Defining SSL listener

  1. Set https port to 8443

    /socket-binding-group=standard-sockets/socket-binding=https:write-attribute(name=port, value="${jboss.https.port:8443}")
  2. Put your Java KeyStore in $WILDFLY_HOME/standalone/configuration/mykeystore.jks

  3. Create a security realm named CertificateRealm

    /core-service=management/security-realm=CertificateRealm:add
    /core-service=management/security-realm=CertificateRealm/server-identity=ssl:add( \
    	keystore-path="mykeystore.jks", \
    	keystore-relative-to="jboss.server.config.dir", \
    	keystore-password="PASSPHRASE")
  4. Create a https listener:

    /subsystem=undertow/server=default-server/https-listener=myHttpsListener:add( \
    	socket-binding="https", \
    	security-realm="CertificateRealm")

Defining a socket binding for HTTP ⇒ HTTPS redirection

As default WildFly redirects to 8443 port when client attempt to enter confidential area because WildFly listen to it but in my case client needs to be redirected to port 443 instead of 8443. so I need to tell WildFly to send redirects to 443 not 8443.

/socket-binding-group=standard-sockets/socket-binding=https-external:add(port=443)
/subsystem=undertow/server=default-server/http-listener=default:write-attribute(name=redirect-socket,value="https-external")

Configuring WildFly to listen 0.0.0.0

/system-property=jboss.bind.address:add(value=0.0.0.0)

Defining combined access_log equivalent

/subsystem=undertow/server=default-server/host=default-host/setting=access-log:add
/subsystem=undertow/server=default-server/host=default-host/setting=access-log:write-attribute(name=pattern, value="%h %l %u [%t] \"%r\" %s %b \"%{i,Referer}\" \"%{i,User-Agent}\"")

Enabling gzip compression

/subsystem=undertow/configuration=filter/gzip=gzipFilter/:add
/subsystem=undertow/server=default-server/host=default-host/filter-ref=gzipFilter:add(\
 predicate="exists['%{o,Content-Type}'] and regex[pattern='(?:application/javascript|text/css|text/html|text/xml|application/json)(;.*)?', value=%{o,Content-Type}, full-match=true]")

Also sending Vary: Accept-Encoding is better for proxies. conditional insertion is best, but an issue reported about it at present time, so I’d go constant insertion this time.

/subsystem=undertow/configuration=filter/response-header=vary-header:add(header-name="Vary", header-value="Accept-Encoding")
/subsystem=undertow/server=default-server/host=default-host/filter-ref=vary-header:add

Configuring iptables redirection

An example of /etc/sysconfig/iptables:

*nat
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination :8080 -m comment --comment "HTTP"
-A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination :8443 -m comment --comment "HTTPS"
-A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to-destination :10025 -m comment --comment "SMTP"
-A PREROUTING -i eth0 -p tcp --dport 465 -j DNAT --to-destination :10465 -m comment --comment "SMTPS"
-A PREROUTING -i eth0 -p tcp --dport 993 -j DNAT --to-destination :10993 -m comment --comment "IMAPS"
COMMIT
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT -m comment --comment "SSH"
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT -m comment --comment "HTTP"
-A INPUT -m state --state NEW -m tcp -p tcp --dport 8443 -j ACCEPT -m comment --comment "HTTPS"
-A INPUT -m state --state NEW -m tcp -p tcp --dport 10025 -j ACCEPT -m comment --comment "SMTP"
-A INPUT -m state --state NEW -m tcp -p tcp --dport 10465 -j ACCEPT -m comment --comment "SMTPS"
-A INPUT -m state --state NEW -m tcp -p tcp --dport 10993 -j ACCEPT -m comment --comment "IMAPS"
COMMIT