Adding users in EJB

All

Intro

I did in another post about a simple Remote Sum EJB  and client. The scheme is pretty straight forward and I will do the opposite of what usually someone do (tutorial then set the user) let’s do the opposite:

Adding the users/roles

Both two steps below can be done with:

$JBOSS_HOME/bin/add-user.sh -a -u 'testUserOne' -p 'testPasswordOne' -g 'guest'
  1. Add the user you will test in the application-users.properties:

testUserOne=cf8f98f5b90ccc568e1ffc7767ac9d8b

2. Add the roles (either guest and/or admin) in the application-roles.properties:

testUserOne=guest

#testUserOne=guest, admin

3. Add Application in the security domain:

<application-security-domains>
<application-security-domain name=”other” security-domain=”ApplicationDomain”/>
</application-security-domains>

4. And add the connector:

<http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm" sasl-authentication-factory="application-sasl-authentication"/>

Maven is a friend

Maven is always a friend an helps organize the project in the pom.xml. On this case though, I will go step by step ~ thoroughly ~ so won’t use mvn.

So just do jar -cvf EjbSecure.jar SecureSum.class SecureSumRemote.class resources/

Code

1. Besides what was already there, we just need to add the annotation for the RolesAllowed and the SecurityDomain allowed, as follows:

@Stateless
@RolesAllowed({ “guest” }) //Added
@SecurityDomain(“other“) //Added
public class SecureSum implements SecureSumRemote
{
public int add(int a, int b){
return a+b;
}
}

2. Add the wildfly-config.xml (Jakarta 8 specially) for the security validation, setting up the actually user you want

<set-user-name name=”testUserOne”/>
<credentials>
<clear-password password=”testPasswordOne”/>

Testing

  1. Create a Client passing the password that you added on wildfly-config.xml:

if(username != null && password != null) {
props.put(Context.SECURITY_PRINCIPAL, username);
props.put(Context.SECURITY_CREDENTIALS, password);
}

2. Compile it with jboss-annotations-ejb3-4.2.2.GA.jar, run it:

#java StandaloneSecure
Getting the Remote
…More several
Got the remote InterfaceProxy for remote EJB StatelessEJBLocator for “/EjbSecure/SecureSum”, view is interface SecureSumRemote, affinity is None
20

Interesting

1. Not using password (or using a wrong password) there will be a Not Allowed:

02:19:47,143 ERROR [org.jboss.as.ejb3.invocation] (default task-1) WFLYEJB0034: EJB Invocation failed on component SecureSum for method public abstract int SecureSumRemote.add(int,int): javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public abstract int SecureSumRemote.add(int,int) of bean: SecureSum is not allowed

2. To add the admin feature specific, just add:

@RolesAllowed(admin) some function, like in [dont forget to add admin role for the user in application-roles.properties]:

@RolesAllowed(“admin”)
public int minus(int a, int b){ return a – b; }

Result:

Got the remote InterfaceProxy for remote EJB StatelessEJBLocator for “/EjbSecure/SecureSum”, view is interface SecureSumRemote, affinity is None
Sum:20
Minus:0

Otherwise, you get an exception: WFLYEJB0364: Invocation on method: public abstract int SecureSumRemote.minus(int,int) of bean: SecureSum is not allowed

3. The lookup get’s the remote, so cast to Remote. And to add another method, the method must be on the remote.

Reference

Of course the quickstart security. Very well done, it is a bit of an overkill at first but later understanding the basics you can add more on top of it no problem.

EJB Context

All

Intro

Reviewing some EJBs I started to play with some attributes of the Context.

//this returns java.naming.factory.initial:
System.out.println(Context.INITIAL_CONTEXT_FACTORY.toString());
//this returns java.naming.provider.url:
System.out.println(Context.PROVIDER_URL.toString());

 

EJB Port

The default http port is 8080, given in .

So if you use an offset <port-offset=”${jboss.socket.binding.port-offset:100}”> change Context.PROVIDER_URL,”remote+http://localhost:8180″);  the otherwise, you will get a connection refused:

javax.naming.CommunicationException: WFNAM00018: Failed to connect to remote host [Root exception is java.net.ConnectException: Connection refused]
at (…)

org.wildfly.naming.client.WildFlyRootContext.listBindings(WildFlyRootContext.java:300)
at javax.naming.InitialContext.listBindings(InitialContext.java:472)
at StandaloneJNDI.main(StandaloneJNDI.java:27)
Caused by: java.net.ConnectException: Connection refused

EJB context

Listing

GettingProperties

Unbinding

context.unbiding will return:

21:26:16,717 INFO [org.wildfly.naming] (default task-1) WildFly Naming version 1.0.11.Final-redhat-00001
21:26:16,746 WARN [org.wildfly.naming] (default task-2) WFNAM00036: Unexpected internal error: java.lang.UnsupportedOperationException:  : Naming context is read-only
at org.jboss.as.naming.WritableServiceBasedNamingStore.requireOwner(WritableServiceBasedNamingStore.java:160)
at org.jboss.as.naming.WritableServiceBasedNamingStore.unbind(WritableServiceBasedNamingStore.java:131)
at org.jboss.as.naming.NamingContext.unbind(NamingContext.java:318)

The code is on Github

 

Tag distributable/

All

Intro

HTTP Session Replication, during a session in case a node fails a way to avoid a client to close it is through replication to the other nodes. This is explained on the tutorial Distributable and that’s pretty much how mod_cluster makes its way.

JBoss EAP

In JBoss, this can be modified/tuned with the usage of the jboss-web.xml that contains several attributes. Although very very outdated, this reference can be used to get some idea of the attributes.

One example of what can be used for is to set the context-root of the project:

   <module>
        <web>
            <web-uri>web-client.war</web-uri>
            <context-root>bank</context-root>
        </web>
    </module>

Demo

[standalone@embedded /] /subsystem=distributable-web/infinispan-session-management=default:read-resource

 

Listing all names in JNDI in EJB

All

Intro

Based on here and here created a program that lists all Bindings (using context.Bindings) and JDNI names from the context.list:

Code

System.out.println(“Listing all names”);
NamingEnumeration namingenumeration = context.listBindings(“”);
while (namingenumeration.hasMore()) {
Binding binding = (Binding)namingenumeration.next();
System.out.println(binding.getName() + ” XXX ” + binding.getObject()
);
}

The core part is the NameClassPair

Result on Client

INFO: JBoss Remoting version 5.0.16.Final-redhat-00001
EjbRemote XXX org.wildfly.naming.client.store.RelativeFederatingContext@32eebfca
javax.naming.Context: true:EjbRemote

org.wildfly.naming.client.store.RelativeFederatingContext@7dc222ae

This is the binding name for JBoss EAP 7.1: org.wildfly.naming.client.WildFlyInitialContextFactory

javax.naming.Context: true:EjbSum

This is the EjbSum from the EJB pt1 – post.

Result on Server side

03:01:46,984 INFO [org.wildfly.naming] (default task-1) WildFly Naming version 1.0.11.Final-redhat-00001

 

EJB pt-2

All

Comparing JBoss EAP for EJB in several versions

JBoss  EAP 4x/5x:

  1. For JBoss EAP  you will need dist/lib/jbossall-client-4.2.2.GA.jar

2. This initial context factory when trying to call a different JVM

public class EJBTester {

jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY,”org.jnp.interfaces.NamingContextFactory”);
jndiProperties.put(Context.URL_PKG_PREFIXES, “org.jboss.ejb.client.naming”);
ctx = new InitialContext(jndiProperties);

3. JBoss EAP 4 /5  – the initial context is like:

public static Context getInitialContext( String host ) throws Exception {
if ( host == null ) host = “localhost”;
Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, “org.jnp.interfaces.NamingContextFactory”);
properties.put(Context.URL_PKG_PREFIXES, “org.jboss.naming:org.jnp.interfaces”);
properties.put(“jnp.socket.Factory”, “org.jnp.interfaces.TimedSocketFactory”);
properties.setProperty(“java.naming.provider.url”, “jnp://”+ host +”:1099″);
return new InitialContext(properties);
}
    4. The EJB lookup would be :

LibrarySessionBeanRemote remoteEJB = (LibrarySessionBeanRemote) getInitialContext(“localhost”).lookup(“LibrarySessionBean/remote”);

18:21:35,100 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

LibrarySessionBean/remote – EJB3.x Default Remote Business Interface
LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote – EJB3.x Remote Business Interface

   5. Deployment

18:21:35,100 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

LibrarySessionBean/remote – EJB3.x Default Remote Business Interface
LibrarySessionBean/remote-com.tutorialspoint.stateless.LibrarySessionBeanRemote – EJB3.x Remote Business Interface

For JBoss EAP 6x

properties.put(Context.URL_PKG_PREFIXES, “org.jboss.naming:org.jnp.interfaces”);

For JBoss 7x

The process is described with more details on the post <EJB pt1>

  1. Add $JBOSS_HOME/modules/system/layers/base/javax/ejb/api/main/jboss-ejb-api_3.2_spec-1.0.1.Final-redhat-1.jar to the classpath.

2. For the Client, the initial context changed for:

props.put(Context.INITIAL_CONTEXT_FACTORY, “org.wildfly.naming.client.WildFlyInitialContextFactory”);
props.put(Context.PROVIDER_URL,”remote+http://localhost:8080″);

3. Compile with $JBOSS_HOME/bin/client/jboss-client.jar

4. Lookup – when the client app is in the same JVM as the EJB

LibrarySessionBeanRemote libraryBean =
(LibrarySessionBeanRemote)this.ctx.lookup(“java:global/EjbComponent/LibrarySessionBean!com.tutorialspoint.stateless.LibrarySessionBeanRemote”);

    AdderImplRemote remote = (AdderImplRemote) getInitialContext().lookup(“ejb:/EjbRemote/AdderImpl!AdderImplRemote”);

   org.wildfly.naming.client.WildFlyInitialContextFactory

 

Reduce in Ruby

All
For numbers
array = [1,2,3,4,5,6,7,8,9,10]
puts array.reduce(:+) #very simplified
puts array.reduce(0,:+)
puts array.reduce(1,:+)
puts array.reduce(10,:+)
puts array.reduce(100,:+)
puts array.reduce(-1,:+)

 

For strings

array = [“say”, “my”,”name”,”say”,”my”,”name”]
puts array.reduce(:+)
puts array.reduce(“mario”,:+)
Output:
55
55
56
65
155
54
saymynamesaymyname
mariosaymynamesaymyname

EJB – pt1

All

EJB

EJB is deployed in Jar, War, Ear format. In WAR, if the EJB is packaged in jar format, it can be placed in WEB-INF/lib. If EJB classes are to be directly packaged in WAR, they can placed in WEB-INF/classes.

I will create a minimal project here to show a client accessing a Stateless bean (basically a simplified version from quickstart) and code on Github.

1. Create the project:

For this you need a home interface/remote interface and the implementation, as explained here:

1.a Create an interface

import javax.ejb.Remote;
@Remote
public interface SumRemote
{ int add(int a, int b); }

1.b Implement this interface

import javax.ejb.Stateless;

@Stateless
public class Sum implements SumRemote
{ public int add(int a, int b){ return a+b; } }

1.c Create a client (eap 7.1:)

Get the InitialContext:

public static Context getInitialContext() throws NamingException{
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, “org.wildfly.naming.client.WildFlyInitialContextFactory”);
props.put(Context.PROVIDER_URL,”remote+http://localhost:8080“);
final Context context = new InitialContext(props);
return context;

(The port here comes from <socket-binding name=”http” port=”${jboss.http.port:8080}”/>)

And then get the remote – attention that is stateless so the JNDI will be:

The class name we know, is SumRemote, so we can add it diretly, or use the .class.getName(0;

SumRemote remote = (SumRemote) getInitialContext().lookup(“ejb:/EjbSum/Sum!” + SumRemote.class.getName());

OR

AdderImplRemote remote = (AdderImplRemote) getInitialContext().lookup(“ejb:/EjbRemote/Sum!SumRemote”);

2. Export

JBOSS_HOME/modules/system/layers/base/javax/ejb/api/main/jboss-ejb-api_3.2_spec-1.0.1.Final-redhat-1.jar

3. Compile and package:

[fdemeloj@fdemeloj Bean]$ javac Sum*

[fdemeloj@fdemeloj Bean]$ jar -cvf EjbSum.jar .
added manifest
adding: SumRemote.class(in = 194) (out= 163)(deflated 15%)
adding: Sum.class(in = 335) (out= 253)(deflated 24%)

Compile the Client

#export CLASSPATH=/home/fdemeloj/jboss-eap-7.3/bin/client/jboss-client.jar:$CLASSPATH
#javac StandaloneClient.java

4.Deploy

[fdemeloj@fdemeloj Bean]$ cp EjbSum.jar $JBOSS_HOME/standalone/deployments

This is the JNDI:

23:17:47,545 INFO [org.jboss.as.ejb3.deployment] (MSC service thread 1-1) WFLYEJB0473: JNDI bindings for session bean named ‘Sum’ in deployment unit ‘deployment “EjbSum.jar”‘ are as follows:

java:global/EjbSum/Sum!SumRemote
java:app/EjbSum/Sum!SumRemote
java:module/Sum!SumRemote
java:jboss/exported/EjbSum/Sum!SumRemote
ejb:/EjbSum/Sum!SumRemote
java:global/EjbSum/Sum
java:app/EjbSum/Sum
java:module/Sum

5. Test

# java StandaloneClient
Getting the Remote
Apr 19, 2020 2:05:10 AM org.wildfly.naming.client.Version <clinit>
INFO: WildFly Naming version 1.0.11.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.wildfly.security.Version <clinit>
INFO: ELY00001: WildFly Elytron version 1.10.4.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.xnio.Xnio <clinit>
INFO: XNIO version 3.7.7.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.7.7.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 2.3.3.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 5.0.16.Final-redhat-00001
Apr 19, 2020 2:05:10 AM org.jboss.ejb.client.EJBClient <clinit>
INFO: JBoss EJB Client version 4.0.27.Final-redhat-00001
Got the remote InterfaceProxy for remote EJB StatelessEJBLocator for “/EjbSum/Sum”, view is interface SumRemote, affinity is None
20

The 20 is the answer.

5. Comparing Remote vs Local

When Same deploying in the same JVM use local and when using another JVM use remote:

@Local ~

Call by Reference, the overhead is minimal, since it is the same JVM so the parameters is the same, so the references are the same. As results, no overhead.

@Remote ~

Call by Value, processing overhead, since are different JVM, the location is remote, the parameters will be value. Remote method invocation: marshed parameters then.
There is a overhead, because of the marsheling. So no references, but a copy of the value.

@Local annotated beans can only be accessed if they are in the same application.

@Remote annotated beans can be accessed across different applications, residing in different jvms or across application servers.

As pointed here

6. JNDI Reference

ejb:<app>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful
<app>EAR name
<moduleName> name of EJB jar
<distinctName> Optional Name
<beanName> Bean’s class
<ViewClassName> fully qualified class name of the remote interface

7. To extract content from jar file:

jar xf jar-file [archived-file(s)]

8. Get the Environment from the context, it will return what is passed:

System.out.println(context.getEnvironment());

Returns:

{java.naming.factory.initial=org.wildfly.naming.client.WildFlyInitialContextFactory, java.naming.provider.url=remote+http://localhost:8080}

8. References:

For JBoss EAP 7.1:

Coding EJB clients for JBoss EAP 7.1

Infinispan/JDG Quickstarts Pt4 – HotRod

All

Intro

This tutorial I have been a long time thinking about doing. This will come in handy: Rod Hot Client Guide

Before start

Download and install the client and install it:

npm install /path/to/jboss-datagrid-7.0.0-nodejs-client/infinispan-0.2.0.Final-redhat-1.tgz

It will also require vorpal js lib =|===>

Deploying

[fdemeloj@fdemeloj hotrod-endpoint-js]$ node football-manager.js
football-manager >

Core

As the guide mentions, the main part is done after the connection, then the functions are added after, but they use vorpal – bsically all in football-manager.js:

   var infinispan = require(‘infinispan’);
var vorpal = require(‘vorpal’)();

infinispan.client({port: 11222, host: ‘127.0.0.1’}).then(function(client)

Commands in Vorpal:

vorpal
.command(‘at [teamName]’, ‘Add a team.’)
.action(addTeam(client));

addPlayer:

function addPlayer(client) {
return function(args, callback) {
var teamName = args.teamName;
var playerName = args.playerName;

var getTeam = client.get(teamName);
var putPlayer = getTeam.then(function(t) {
return client.put(teamName, appendPlayer(t, playerName));
});

return putPlayer.then(callback);

Printing value with `​p`

football-manager > at “Holand”
Add Team
true

football-manager > p
Add Team
=== Team: Holand ===

Interesting facts

  1. If you do ​`tree command` the list of files is huge, cause all the js scripts from the libs are there, apparently.
  2. Deploying in version JDG 7.2 gives an exception, but version JDG 7.3 works perfectly.
    1. ERROR [org.infinispan.server.hotrod.CacheDecodeContext]ISPN005003: Exception reported: org.infinispan.server.hotrod.InvalidMagicIdException: Error reading magic byte or message id: 13 at org.infinispan.server.hotrod.HotRodDecoder.readHeader(HotRodDecoder.java:184)
  3. Using vorpal makes the example pretty easy, with help and everything – tutorial here
  4. The package.json` has the dependencies and others info about the project
  5. `hotrod-client.properties` is not used.

Infinispan/JDG Quickstarts Pt3 – Hello World

All

Intro

This was suppose to be the first part, but ended up being the third. I should have showed this presentation as well, by Kylin Soon.

Deployment

The tests are failing for now, so let’s skip them.

[fdemeloj@fdemeloj target]$ mvn clean install -Dmaven.test.skip=true

Same approach copy to /standalone/deployments

INFO [org.jboss.as.server] (DeploymentScanner-threads – 1) WFLYSRV0010: Deployed “jboss-helloworld-jdg.war” (runtime-name : “jboss-helloworld-jdg.war”)

Core Part

Well, as expected the core part is the cache, which has the following configurations:

public DefaultCacheManager getCacheManager() {
if (manager == null) {

GlobalConfiguration glob = new GlobalConfigurationBuilder().clusteredDefault() // Builds a default clustered
.transport().addProperty(“configurationFile”, “jgroups-udp.xml”)
.globalJmxStatistics().allowDuplicateDomains(true).enable()
.build();
Configuration loc = new ConfigurationBuilder().jmxStatistics().enable() // Enable JMX statistics
.clustering().cacheMode(CacheMode.DIST_SYNC) /
.hash().numOwners(2)
.expiration().lifespan(ENTRY_LIFESPAN)
.build();
manager = new DefaultCacheManager(glob, loc, true);
}

Meaning

.expiration().lifespan(ENTRY_LIFESPAN) time to expire the data in the cache.

Lifespan property is pretty cool

jgroups-udp.xml

Differently than the other three, this one uses a specific jdg configuration file that set’s multicast – UDP properties, instead of TCP. Some recommendations for this file here.

 

<UDP
bind_addr=”${jgroups.bind_addr:127.0.0.1}”
mcast_addr=”${jgroups.udp.mcast_addr:228.6.7.8}”
mcast_port=”${jgroups.udp.mcast_port:46655}”
tos=”8″
ucast_recv_buf_size=”20000000″
ucast_send_buf_size=”640000″
mcast_recv_buf_size=”25000000″
mcast_send_buf_size=”640000″
max_bundle_size=”64000″
ip_ttl=”${jgroups.udp.ip_ttl:2}”
enable_diagnostics=”false”

thread_naming_pattern=”pl”

thread_pool.enabled=”true”
thread_pool.min_threads=”2″
thread_pool.max_threads=”30″
thread_pool.keep_alive_time=”5000″
/>

<PING />
<MERGE3 max_interval=”30000″ min_interval=”10000″/>
<FD_SOCK/>
<FD_ALL/>
<BARRIER />
<pbcast.NAKACK2 use_mcast_xmit=”true” discard_delivered_msgs=”true”/>
<UNICAST3/>
<pbcast.STABLE stability_delay=”1000″ desired_avg_gossip=”50000″ max_bytes=”1000000″/>
<pbcast.GMS print_local_addr=”false” join_timeout=”3000″ view_bundling=”true”/>
<UFC max_credits=”500000″ min_threshold=”0.20″/>
<MFC max_credits=”500000″ min_threshold=”0.20″/>
<FRAG2 frag_size=”60000″ />

Adding value

Pretty much standard, as before, get the (default) cache manager and put the value.

  INFO [org.jboss.as.quickstarts.datagrid.helloworld.PutController] (default task-1) put: jdg 8

Interesting parts

  1. The Security Manager
  2. double lines when creating the default cache manager and the configuration file
  3. Lifespan and UDP were the best part