Linkedin is bad on basic stuff

All

I mean, I barely see the website, and I think it is great for looking for jobs and such – I think for searching people is an amazing tool. But it fails in some basic features very badly when you are not looking for job and don’t have the time to keep several profiles being updated. Main reasons below:

The default/main profile written in stone, meaning it is a pain to switch your default profile. You need to go there, delete it and re-create from scratch <– and that’s because they enable this now, for years you just couldn’t. If you moved from one country to the other, just give up on writing your profile in a new language and not being able to set as primary.

The languages integration is none. I have to literally write 5 profiles if I want to keep portuguese, english, french, german, and italian as profile languages. Any minimal change in anything at your current work, it is a pain to go there, change everything back again. I gave up and keep only 3 main profiles.

No language verification. You can add a new spanish profile, write everything in another language. No validation will be made. This is good and bad, because at least you can re-write your main profile in another language, like I did.

Jobs are dynamics like life not static. This is a more general problem, also correlated to writing a CV. You start doing one thing, focus on another, then do another thing, the role you are assign has the duties you are suppose to do, but from time to time the focus changes. Keeping updating all this, every time, from time to time is painful. Creating a more interactive experience would be more useful instead of a few lines for description. Maybe a better timeline, I mean, you start doing that, now you do this, your were someone mentee, now you are a mentor. And so on, sometimes by product. Or even maybe show by project/product.

Sometimes I even think about deleting it there and keeping just my personal blog. But then I cannot see my friends work, or their promotions, or even job changes. Maybe they should try to do less of a Facebook/Meta journal updates/network and more on professional graph network. You can select the other people you interact, see their projects, how they are being displayed.

DG Kubernetes Operators

All

I’m sure if you are into Kubernetes/OCP you already played with those bundles of Go automation scripts called operators. If you haven’t that’s pretty cool stuff in the sense of automating the deployment, some operators cover the whole deployment life and as usual, if a pod or a resource is different than the spec, on the status, it will self adjust – for instance it will pop up another pod if the number of pods is different than the operator settings.

What is interesting about this, I would say for DevOps teams is the facility to deploy applications/start EAP/DG/SSO with the operators. As soon as you download one from OperatorHub in OCP for instance, and install in your respective project (given you have storage setup) the deployment is complete seamlessly, only the namespace is will need to be known before hand.

Depending on the operator you can have more or less features, like seemly upgrade up to complete autopilot.

I think it is amazing how powerful it is, with a few oc apply using some templates one can spawn a complete cluster very easily: oc apply rhdg-setup.yaml -f –, where the template defines a namespace for the operator, a namespace for the pods, the operator itself (subscription and OperatorGroup) and the cluster itself:

- apiVersion: operators.coreos.com/v1 <--- api version
  kind: OperatorGroup          <----- OperatorGroup
  metadata:
    name: datagrid
    namespace: ${OPERATOR_NAMESPACE}
  spec:
    targetNamespaces:
      - ${CLUSTER_NAMESPACE}
      # - ${GRAFANA_NAMESPACE}
- apiVersion: operators.coreos.com/v1alpha1
  kind: Subscription            <----- Subscription
  metadata:
    name: datagrid-operator
    namespace: ${OPERATOR_NAMESPACE} <---- the namespace
  spec:
    channel: 8.2.x  <--- channel to fetch the operator, on this case channel 8.2.x instead of 8.1.x or 8.3.x
    installPlanApproval: Manual  <----- manual approval
    name: datagrid
    source: redhat-operators     <----- source
    sourceNamespace: openshift-marketplace <---- source namespace
    startingCSV: datagrid-operator.v8.2.8 <----- starting version

Above the fields are complete for subscription and operator group – as described here. Also the api version and so on defined here. It is very easy to add jvm flags or add routes, just do it in the custom resource, for instance infinispan or cache cr, and that’s all.

Learning nihongo update – Ado

All

After about 6 months of learning nihongo – aka Japanese, I can say I moved from A1 to A1. The language is considerably difficulty and one must be very disciplined to continue studying every day and make progress. But I did some progress though, when listening to a song, now I can recognize a few words (yes, that was my progress). But I want to end in a good note (and hopeful) and will continue to learn for the next 2/3y and be able to progress considerably. It takes more discipline than anything else – and consistence.

For sure I will make more progress when learning Japanese in Japan, but I will push the max I can do here in カナダ.

For sharing (シェアする – she a su ru) here is a song that I like very much by a Japanese Australian singer (yes born in 2002) ~ Ado. She has a magnificent and strong voice.

Verbs to learn on this song:

喰らって –> eat

 アンダスタン –> lol! anderstand

Spring boot multiple profiles

All

Development java web applications with spring is comes in handy considerably when developing production (and fast non production software). I mean, just adding an application.properties with the below can make it very simple to use several profiles, for each development (since Spring Boot 1.3):

spring.profiles.active=@activatedProperties@

And then setting on the mvn’s pom.xml the profiles:

<profiles>
		<profile>
			<id>local</id>
			<properties>
				<activatedProperties>local</activatedProperties>
			</properties>
			<activation>
				<activeByDefault>false</activeByDefault> <!-- here if false or true -->
                                <!-- <activeByDefault>true</activeByDefault> -->
			</activation>
		</profile>

And then you have a series of application-*.properties files, mandatorily pattern application-{custom_suffix}.properties, which is place on src/main/resources/application-*.properties, like src/main/resources/application-test.properties, where you will define the properties:

# AUTO-CONFIGURATION - set false for those which is not required
#spring.autoconfigure.exclude= # Auto-configuration classes to exclude.
spring.main.banner-mode=off
spring.jmx.enabled=false
...
server.jsp-servlet.registered=false
spring.freemarker.enabled=false

Interesting logging.config seems to be found in the server deployment, not in the application sources. We can use JAVA_OPTS=”$JAVA_OPTS -Dlogfile.name=test_file_name” to set a file name on runtime:

#appender.R.fileName = ${sys:logfile.name}
appender.R.fileName = ${filename}

reading about fusion energy

All

I’ve seen recently an amazing number of startups that aim to achieve production ready energy generation with fusion energy. It is very exciting, and the number of Canadian companies (or Canadian people behind it), very interesting and really exciting! Some of those have very short term goals, like Zap Energy

However, I’ve started to go deep on the understand of this (as much as possible, during holidays, with not such much technical books). There are several books and I’ve just started, but here is a short list.

I’ve started with a brand new book, The Fairy Tale of Nuclear Fusion (2021), by L.J. Reinders. Based from one of the comments on the video. Well, I’m still on chapter six and it is very well written, but very critical in regards to any timeline for this to be achieved. It is very critical and it seems an honest view, i.e. no assumptions were made and the writer indeed searched before coming to an conclusion, then wrote the book (not the other way around). But clearly the author has a very hard instance on the over-promises some scientists made with goals.

My interested started more because of the recent discoveries (public ones) and because of this video, by Sabine Hossenfelder. Later I’ve seen a couple comparing Tokamak VS Stellarator, VS Inertial confinement, ITER vs JET vs fusion. There is a lot of hard core (deep) information out there, one just need to look for it, and where to do it.

EJB with wildfly-services and wildfly-config

All

I think I’ve written here some topics about wildfly-config and EJB setting for client configuration. Let me go deep on this topic this time (these are the previous topics about it: here1 and here2).

Wildfly-config.xml will have its own syntax, but it is quite simple to understand, let see complete example. Basically everything must be in configuration, below authentication client, where we can defined the key stores, ssl contexts, and ssl context rules. Where the rules -> context -> key store. The default authentication rule is used and the defined at the bottom.

<?xml version="1.0" encoding="UTF-8"?>
...
<configuration>
  <authentication-client xmlns="urn:elytron:1.0">
      <!-- key stores-->
      <key-stores>
        <key-store name="qsKeyStore" type="JKS">
          <file name="server.keystore"/>
          <key-store-clear-password password="secret"/>
        </key-store>
      </key-stores>
      <!-- ssl context definition -->
      <ssl-contexts>
        <ssl-context name="aContext">
          <trust-store key-store-name="qsKeyStore"/>
          <cipher-suite selector="DEFAULT"/>
          <protocol names="TLSv1.2"/> <!-- tls v 1.2 -->
        </ssl-context>
      </ssl-contexts>
      <!-- usage -->
      <ssl-context-rules>
            <rule use-ssl-context="aContext"/>
      </ssl-context-rules>

        <!-- authentication rules use teh default configuration -->
        <authentication-rules>
                    <rule use-configuration="default" />
        </authentication-rules>
        <!-- Default configuration defined below \, and used above ^-->
        <authentication-configurations>
            <configuration name="default">
                <sasl-mechanism-selector selector="#ALL" />
                <set-mechanism-properties>
                    <property key="wildfly.sasl.local-user.quiet-auth" value="true" />
                 </set-mechanism-properties>
                <providers>
                    <use-service-loader/>
                </providers>
                <!-- Used for EJB over HTTP, remoting invocations will use transparent auth-->
                <set-user-name name="auser" />
                <credentials>
                    <clear-password password="apassword!" />
                </credentials>
             </configuration>
        </authentication-configurations>
    </authentication-client>
</configuration>

Now, in regards to using wildfly-config.xml, we can just do the following lookup for http and for https:

  <authentication-client xmlns="urn:elytron:1.0">
      <!-- key stores-->
      <key-stores>
        <key-store name="qsKeyStore" type="JKS">
          <file name="server.keystore"/>
          <key-store-clear-password password="secret"/>
        </key-store>
      </key-stores>
      <!-- ssl context definition -->
      <ssl-contexts>
        <ssl-context name="qsSSLContext">
          <trust-store key-store-name="qsKeyStore"/>
          <cipher-suite selector="DEFAULT"/>
          <protocol names="TLSv1.2"/>
        </ssl-context>
      </ssl-contexts>
      <!-- usage -->
      <ssl-context-rules>
            <rule use-ssl-context="qsSSLContext"/>
      </ssl-context-rules>

        <!-- authentication rules use teh default configuration -->
        <authentication-rules>
                    <rule use-configuration="default" />
        </authentication-rules>

And the initial context, for latest Wildfly, we can do as follows:

	//Get Initial Context
	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,"https://localhost:8443/wildfly-services");// <----  https:8443
			final Context context = new InitialContext(props);
			return context;
	}

So then we have, basically, http:8080/wildfly-services or https:8443/wildfly-services

Create jars and manifest files

All

Continuing my last posts. Let’s create a simple jar with the default content, using the -v option, for verbose (which will tell us exactly what is being added). Example:

jar cvf Example.jar * (or MyClass.class)

And compare with 0 option (which avoids compacting the files, and therefore will be heavier). In some tests Ive done here, the -0 can save considerable space sometimes, 30% in some cases).

jar -c0vf 

Now let’s set the main class with the `-e` option:

#using the v for verbose, f for file, -c for xx, and -e for setting the main file
jar -cvfe ClientJar.jar StandaloneClass Standalone.class

Now, let’s present we want to create a sealed jar, for instance when sending to the customer, to do so let’s add a customized manifest file, so we use the java -cvfm (m to use a custom manifest file), and create a manifest with the following content (with some other customizations):

manifest
sealed <---- set it to sealed

What is more interesting is that creating jars manually, makes me learn much more about the inner compilation of java classes, and the fact that inner classes generates a , like: StandaloneClient$innerclass.class, that is quite expected and obvious, but when creating the jar, so then we need to set jar -cvf *class, to not ended forgetting to add the inner class!

That’s the same if we implement the runnable and such, which makes a StandaloneClient$1.class <— which is de facto an anonymous inner class just because we implemented Runnable. If not, you will clearly face this (and wonder how come this happens):

NoClassDefFound: standaloneclient$1 <---- here

So must of the times, we don’t even bother creating/editing the Manifest file (since the IDE creates it and package it). But it is actually very useful and can come in hand in some scenarios.

Well, I guess that’s all the suggestions for today. Maybe next week I’ll do a blog post about o11y (observability), complementing my posts about java and k8s (and OCP).

Taking the world by storm: Log4Shell vulnerability CVE-2021-44228

All

Friday Nov 10th morning the news of Log4Shell vulnerability (CVE-2021-44228) started to appear, a few hours later several sites were already having their IPs shown in Github, examples were TSLA, twitter, Apple, Amazon, Twitter.

This vulnerability is very much related to one topic I usually post about it here, which is JNDI lookup, and LDAP in the context of EJB for returning Java Objects – aka serialization. And CVE 44228 is basically this, a JNDI lookup().

Updating your JDK for the latest will not save your from this one, but depending on the JDK it will much easier to get it. Explanation:

JDK versionsVulnerability
<8u121Starting with Java 8u121 remote codebase were no longer permitted by default for RMI (but not LDAP).
<=8u191There is a direct path from a controlled JNDI lookup to remote classloading of arbitrary code
8u191>RMI, References and object construction can still happen. Example: Apache Xbean BeanFactory

Solutions were already much much already described, basically updating the log4j or removing the JNDI lookup class. Since from log4j 2.15.0, this behavior has been disabled by default.

javac

All

Javac is this very well known tool will read the class files, .java, and create bytecode. Very useful and can be used with the following options. I think the -cp and -d are the most well known options. However, it has some many features we pretty much overlook that I think it is worth considering a second look (some examples from Nam Ha blog).

For instance, there is also the -verbose, example (from my favorite suite of java programs from Univ of Texas):

[fdemeloj@fdemeloj javac]$ javac -version FilterExample.java 
javac 1.7.0_171 <------------------------------------------------------ yes, javac is default for JDK 7, use alternatives to fix this
...
[fdemeloj@fdemeloj javac]$ javac -verbose First.java 
[parsing started RegularFileObject[First.java]]
[parsing completed 14ms]
[search path for source files: .]
[search path for class files: 
...pulse-java.jar,.]
../rt.jar/java/awt/Frame.class)]]
../rt.jar/java/awt/MenuContainer.class)]]
../rt.jar/java/lang/Object.class)]]
../rt.jar/java/awt/Window.class)]]
../rt.jar/javax/accessibility/Accessible.class)]]
../rt.jar/java/awt/Container.class)]]
...
[wrote RegularFileObject[First.class]]
[total 520ms]
[fdemeloj@fdemeloj javac]$ java First 

And given a certain directory (already there) you can use -d to set the compiled classes there: javac -d classes, so the .class files will be under /classes dir.

Interestingly -Xdiags:verbose (and compact) options does not seem to add much more on top of the verbose, in fact it adds 0 from when comparing to -verbose option, perhaps depending on the issue it shows more. I mean it helps a lot because it will show what is required vs what was found (see below – Driver class):

[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -verbose Driver01.java  <--------------------------------------- verbose
[parsing started SimpleFileObject[/home/fdemeloj/Downloads/cases/EJBtests/javac/Driver01.java]]
[parsing completed 29ms]
[loading /modules/java.xml.crypto/module-info.class] 
<<several others>>>
...
Driver01.java:41: error: incompatible types: possible lossy conversion from double to int
            swap(j, range, enterArray);
                 ^
[total 366ms]
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdiags:compact Driver01.java  <----------------------------------- compact
Driver01.java:41: error: incompatible types: possible lossy conversion from double to int
            swap(j, range, enterArray);
                 ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdiags:verbose Driver01.java <----------------------------------- verbose
Driver01.java:41: error: method swap in class Driver01 cannot be applied to given types;
            swap(j, range, enterArray);
            ^
  required: int,int,double[]
  found: double,int,double[]
  reason: argument mismatch; possible lossy conversion from double to int
1 error

And some extra options can be found with –help-extra:


[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac --help-extra
  --add-exports <module>/<package>=<other-module>(,<other-module>)*
        Specify a package to be considered as exported from its defining module
        to additional modules, or to all unnamed modules if <other-module> is ALL-UNNAMED.
  --add-reads <module>=<other-module>(,<other-module>)*
        Specify additional modules to be considered as required by a given module.
        <other-module> may be ALL-UNNAMED to require the unnamed module.

One the most useful options is actually the Xlint (maybe because of my background in python and python lint process, pep-8 and so forth), I will ended doing a blog post about PMD, Checkstyle, and PetitDej as well:

[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xlint First.java 
First.java:3: warning: [serial] serializable class First has no definition of serialVersionUID <------ 
class First extends Frame{
^
1 warning

In JDK 11, interestingly it is possible to set –release flag not only sets source and target versions, but it also causes the compiler to use the symbol table for the JDK libraries corresponding to the specified release. This flag was added after and basically replace –source and –target.

Note: On JDK 11, I think I already mentioned this here that you can just run java, instead of javac, and the class will run:

java Hello.java
Hello, so much snow today in MTL!

I think one of the most useful, which makes javac almost like maven, is the ability to halt the compilation in case a warning happens with -Werror so it makes a default error when it seems a warning:

[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdoclint:all -Werror First.java 
First.java:3: warning: no comment
class First extends Frame{
^
First.java:5: warning: no comment
First(){
^
First.java:15: warning: no comment
public static void main(String args[]){
                   ^
error: warnings found and -Werror specified
1 error <--------------------------------------------------------------------------- 1 error
3 warnings <------------------------------------------------------------------------ 3 warnings
[fdemeloj@fdemeloj javac]$ $JAVA_HOME/bin/javac -Xdoclint:all First.java 
First.java:3: warning: no comment
class First extends Frame{
^
First.java:5: warning: no comment
First(){
^
First.java:15: warning: no comment
public static void main(String args[]){
                   ^
3 warnings <--------------------------------------------------------------------------- 3 warnings