25 Nisan 2022 Pazartesi

Jakarta EE @ConfigProperty Anotasyonu

Giriş
Şu satırı dahil ederiz
import javax.resource.spi.ConfigProperty;
Jakarta EE ResourceAdapter Arayüzünü tanımlarken pek çok bilgi XML içindedir. XML içindeki tag'lerden bazılarını @Connector Anotasyonu ile koda almak mümkün. 

Örnek
Şöyle yaparız
@ConfigProperty
private String token;

Jakarta EE @Connector Anotasyonu

Giriş
Şu satırı dahil ederiz
import javax.resource.spi.Connector;
Jakarta EE ResourceAdapter Arayüzünü tanımlarken pek çok bilgi XML içindedir. XML içindeki tag'lerden bazılarını @Connector Anotasyonu ile koda almak mümkün. 

displayName Alanı
Örnek
src/main/resources/META-INF/ra.xml dosyasında şöyle olsun
<connector ...> 
  <description></description>
  <display-name>MyResourceAdapter</display-name>
  <vendor-name>Java EE Tutorial</vendor-name>
  <eis-type></eis-type>
  <resourceadapter-version></resourceadapter-version>                                  
  <resourceadapter>
  
    <resourceadapter-class>
      com.foo.MyResourceAdapter
     </resourceadapter-class>
	  
      <config-property>
        <config-property-name>input</config-property-name>
	  <config-property-type>java.lang.String</config-property-type>
	  <config-property-value>mystring value</config-property-value>
      </config-property>
		
		
      <inbound-resourceadapter>
        <messageadapter>
          <messagelistener>
	    <messagelistener-type>com.InboundMessageEndpoint</messagelistener-type>
	      <activationspec>
	        <activationspec-class>com.EndpointActivationSpec</activationspec-class>
              </activationspec>
	  </messagelistener>
	</messageadapter>
      </inbound-resourceadapter>
	
  </resourceadapter>
</connector>
connector tag'indeki bazı bilgileri koda almak için şöyle yaparız
@Connector(
  displayName = "MyResourceAdapter",
  vendorName = "Java EE Tutorial",
  version = "7.0"
)
public class TrafficResourceAdapter implements ResourceAdapter, Serializable {
  ...
}
description Alanı
Örnek
Şöyle yaparız
@Connector(description = "Sample Resource Adapter", 
  displayName = "Sample Resource Adapter", 
  eisType = "Sample Resource Adapter", 
  version = "1.0")
public class SlackResourceAdapter implements ResourceAdapter {

  public void start(final BootstrapContext bootstrapContext) 
    throws ResourceAdapterInternalException {
  }

  public void stop() {
  }

  public void endpointActivation(MessageEndpointFactory messageEndpointFactory,
    ActivationSpec activationSpec)
    throws ResourceException {
  }

  public void endpointDeactivation(MessageEndpointFactory messageEndpointFactory,
    ActivationSpec activationSpec) {
  }

  public XAResource[] getXAResources(final ActivationSpec[] activationSpecs)
    throws ResourceException {
      return new XAResource[0];
  }
}

22 Nisan 2022 Cuma

Wildfly standalone.sh

-c seçeneği
Örnek
Şöyle yaparız
# This will boot WildFly in standalone mode and bind to all interfaces
/opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 -c standalone-full.xml

19 Nisan 2022 Salı

EJB @MessageDriven Anotasyonu

Örnek
Şöyle yaparız. destination kuyruk ismini belirtir. destinationType Queue veya Topic olduğunu belirtir, maxSession ise kaç tane eş zamanlı mesaj işleneceğini belirtir.
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName="destination", propertyValue="SendingSMSQueue"),
@ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="maxSession", propertyValue = "1")
})
public class SendgridEmail2SmsMessageListener implements MessageListener {...}


Wildfly Logging

Giriş
Loglama ayarları 
1. yönetim ekranından 
2. jboss-cli komutuyla 

değiştirilebiliyor. 

Ancak hangisi kullanılırsa kullanılsın, çalışma zamanında (run-time) loglama seviyesini dinamik olarak değiştirebilmenin bir yolunu bulamadım. Her iki komutta sadece standalone.xml'i değiştiriyor. Ya da hangi xml'i kullanıyorsak

Değişiklikleri Wildfly'ın tekrar okuması için Cli satırından "reload" yapmak gerekiyor.

Örnek - Custom Logger
Şöyle yaparız
<subsystem xmlns="urn:jboss:domain:logging:8.0">
<console-handler name="CONSOLE">
<level name="INFO"/>
<formatter>
<named-formatter name="COLOR-PATTERN"/>
</formatter>
</console-handler>
<periodic-rotating-file-handler name="FILE" autoflush="true">
<formatter>
<named-formatter name="PATTERN"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="server.log"/>
<suffix value=".yyyy-MM-dd"/>
<append value="true"/>
</periodic-rotating-file-handler>
<logger category="com.foo">
<level name="DEBUG"/>
</logger>

<root-logger>
<level name="INFO"/>
<handlers>
<handler name="CONSOLE"/>
<handler name="FILE"/>
</handlers>
</root-logger>
<formatter name="PATTERN">
<pattern-formatter pattern="%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
<formatter name="COLOR-PATTERN">
<pattern-formatter pattern="%K{level}%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n"/>
</formatter>
</subsystem>
Örnek - Root Logger
Şöyle yaparız
$JBOSS_HOME/bin/jboss-cli.sh -c

[standalone@localhost:9990 /] /subsystem=logging/console-handler=CONSOLE:write-attribute(name=level,value=DEBUG)
{"outcome" => "success"}

[standalone@localhost:9990 /] /subsystem=logging/root-logger=ROOT:write-attribute(name=level,value=DEBUG)
{"outcome" => "success"}
xml şöyle olur
<root-logger>
  <level name="DEBUG"/>
       <handlers>
          <handler name="CONSOLE"/>
          <handler name="FILE"/>
       </handlers>
</root-logger>



18 Nisan 2022 Pazartesi

Docker ve Wildfly

Örnek - Kullanmayın
Kullanmayın çünkü "jboss/wildfly" artık "quay.io" olarak değişti. Şöyle yaparız
FROM jboss/wildfly
ADD my-app.war /opt/jboss/wildfly/standalone/deployments/
ve şöyle yaparız
docker build --tag=my-app . && docker run -it my-app
Örnek - quay.io 
Şöyle yaparız. -b ile bind seçenekleri belirtiliyor.
FROM quay.io/wildfly/wildfly:26.0.0.Final
COPY my-standalone.xml /opt/jboss/wildfly/standalone/configuration/
#Deploy
COPY ./target/*.war /opt/jboss/wildfly/standalone/deployments/

# Run with custom configuration
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0",
  "-c","my-standalone.xml"]
Bu image için kullanılan DockerFile GitHub'da burada. Burada FROM jboss/base-jdk:11 görülebilir.
jboss/base-jdk:11 için kullanılan DockerFile GitHub'da burada. FROM jboss/base:latest görülebilir
jboss/base için kullanılan DockerFile GitHub'da burada. FROM centos:7 görülebilir

Örnek -  quay.io  + runtime
Şöyle yaparız
FROM quay.io/wildfly/wildfly-runtime-jdk11
COPY --chown=jboss:root target/server $JBOSS_HOME
RUN chmod -R ug+rwX $JBOSS_HOME
Örnek - Admin Kullanıcısı
Şöyle yaparız
FROM quay.io/wildfly/wildfly
#Create user
RUN /opt/jboss/wildfly/bin/add-user.sh admin Admin#70365 --silent

CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0"]
Örnek - Olmayan bir Wildfly Sürümünü İndir ve JDK Kur
Şöyle yaparız. Burada JDK 17 de kuruluyor
#Bring centos
FROM redhat/ubi8

# Create a user and group used to launch processes
# The user ID 1000 is the default for the first "regular" user on Fedora/RHEL,
# so there is a high chance that this ID will be equal to the current user
# making it easier to use volumes (no permission issues)
RUN groupadd -r jboss -g 1000 && useradd -u 1000 -r -g jboss -m -d /opt/jboss -s /sbin/nologin -c "JBoss user" jboss && \
    chmod 755 /opt/jboss

# Set the working directory to jboss' user home directory
WORKDIR /opt/jboss

# Install JDK 17
RUN yum -y install java-17-openjdk-devel && yum clean all

# Switch back to jboss user
USER jboss

# Set the JAVA_HOME variable to make it clear where Java is located
ENV JAVA_HOME /usr/lib/jvm/java

##Install Wildfly
# Set the WILDFLY_VERSION env variable
ENV WILDFLY_VERSION 25.0.0.Final
ENV WILDFLY_SHA1 238e67f48f1bd1e79f2d845cba9194dcd54b4d89
ENV JBOSS_HOME /opt/jboss/wildfly

USER root

# Add the WildFly distribution to /opt, and make wildfly the owner of the extracted tar content
# Make sure the distribution is available from a well-known place
RUN cd $HOME \
    && curl -L -O https://github.com/wildfly/wildfly/releases/download/$WILDFLY_VERSION/wildfly-$WILDFLY_VERSION.tar.gz \
    && sha1sum wildfly-$WILDFLY_VERSION.tar.gz | grep $WILDFLY_SHA1 \
    && tar xf wildfly-$WILDFLY_VERSION.tar.gz \
    && mv $HOME/wildfly-$WILDFLY_VERSION $JBOSS_HOME \
    && rm wildfly-$WILDFLY_VERSION.tar.gz \
    && chown -R jboss:0 ${JBOSS_HOME} \
    && chmod -R g+rw ${JBOSS_HOME}

# Create folders for batch processing
RUN bash -c 'mkdir -p /advdata/TspFt/BatchProcessingRoot/rwbat/{input,tmp,output,classicInput,classicTmp,classicOutput}'
RUN chown -R jboss /advdata/TspFt/BatchProcessingRoot/rwbat/

# Ensure signals are forwarded to the JVM process correctly for graceful shutdown
ENV LAUNCH_JBOSS_IN_BACKGROUND true

USER jboss

# Expose the ports in which we're interested
EXPOSE 8080
EXPOSE 9990


#Deploy
ADD  modules/system/layers/base/com /opt/jboss/wildfly/modules/system/layers/base/com/
COPY standalone-full.xml /opt/jboss/wildfly/standalone/configuration
COPY ./build/libs/rwGuiEar.ear /opt/jboss/wildfly/standalone/deployments/

#Create user
RUN /opt/jboss/wildfly/bin/add-user.sh admin Admin#70365 --silent

# Set the default command to run on boot
# This will boot WildFly in standalone mode and bind to all interfaces
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-b", "0.0.0.0", "-bmanagement", "0.0.0.0", "-c","standalone-full.xml"]
Eğer deploy işlemini bir artifactory sunucusundan yapıyorsak şöyle yaparız
...

USER root
RUN curl http://artifactory.foo.com/artifactory/release-local/mysql-connector-java-8.0.17.jar > /opt/jboss/wildfly/modules/system/layers/base/com/mysql/main/mysql-connector-java-8.0.17.jar

USER jboss
COPY files/standalone-full.xml /opt/jboss/wildfly/standalone/configuration
RUN curl http://artifactory.foo.com/release/rwGuiEar.ear > /opt/jboss/wildfly/standalone/deployments/rwGuiEar.ear

...
Çalıştırmak için şöyle yaparız. Burada yerelde çalışan vitesstestserver isimli container, wildfly25 ile aynı ağa alınıyor
# Create a network
docker network create myNetwork

# build image
docker build -t wildfly25 .
docker run -d --rm --network myNetwork --name wildfly25
  -p 8080:8080 -p 9990:9990 wildfly25

# Connect a running container to a network
docker network connect myNetwork vitesstestserver
veya vitesstestserver'ı başlatırken ağa almak için şöyle yaparız
docker build -t vitesstestserver .
docker run --rm --name vitesstestserver --network myNetwork
  -p 33577:33577 vitesstestserver
Bağlanmak için şöyle yaparız
http://localhost:8080/rwgui/
Örnek - /usr/sbin/sshd kullanan Redhat/ubi8
Burada wildfly + ssh kuruluyor. Şöyle yaparız
#Bring OS
FROM redhat/ubi8

# Create a user and group that is used to launch processes
# The user ID 1000 is the default for the first "regular" user on Fedora/RHEL,
# so there is a high chance that this ID will be equal to the current user
# making it easier to use volumes (no permission issues)
RUN groupadd -r jboss -g 1000 && useradd -u 1000 -r -g jboss -m -d /opt/jboss -c "JBoss user" jboss && \
    chmod 755 /opt/jboss


# Set the working directory to jboss user's home directory
WORKDIR /opt/jboss

# Install SSH Server, JDK 17
RUN yum -y install \
    sudo \
    openssh-server \
    openssh-clients \
    java-17-openjdk-devel && yum clean all

USER jboss
RUN ssh-keygen -A

USER root
RUN ssh-keygen -A

# Set passwords
RUN echo root:login-1 | chpasswd
RUN echo jboss:login-1 | chpasswd

# Set the JAVA_HOME variable to make it clear where Java is located
ENV JAVA_HOME /usr/lib/jvm/java

##Install Wildfly
# Set the WILDFLY_VERSION env variable
ENV WILDFLY_VERSION 25.0.0.Final
ENV WILDFLY_SHA1 238e67f48f1bd1e79f2d845cba9194dcd54b4d89
ENV JBOSS_HOME /opt/jboss/wildfly

ADD start.sh /
RUN chmod +x /start.sh

# Add the WildFly distribution to /opt/jboss, and make jboss user the owner of the extracted tar content
# Make sure the distribution is available from a well-known place
RUN cd $HOME \
    && curl -L -O https://github.com/wildfly/wildfly/releases/download/$WILDFLY_VERSION/wildfly-$WILDFLY_VERSION.tar.gz \
    && sha1sum wildfly-$WILDFLY_VERSION.tar.gz | grep $WILDFLY_SHA1 \
    && tar xf wildfly-$WILDFLY_VERSION.tar.gz \
    && mv $HOME/wildfly-$WILDFLY_VERSION $JBOSS_HOME \
    && rm wildfly-$WILDFLY_VERSION.tar.gz \
    && chown -R jboss:0 ${JBOSS_HOME} \
    && chmod -R g+rw ${JBOSS_HOME}

# Create folders for batch processing
RUN bash -c 'mkdir -p /advdata/TspFt/BatchProcessingRoot/rwbat/{input,tmp,output,classicInput,classicTmp,classicOutput}'
RUN chown -R jboss /advdata/TspFt/BatchProcessingRoot/rwbat/

# Ensure signals are forwarded to the JVM process correctly for graceful shutdown
ENV LAUNCH_JBOSS_IN_BACKGROUND true

USER jboss

# Expose the ports in which we're interested
EXPOSE 22
EXPOSE 8080
EXPOSE 9990


#Deploy local files
ADD  modules/system/layers/base/com /opt/jboss/wildfly/modules/system/layers/base/com/
COPY standalone-full.xml /opt/jboss/wildfly/standalone/configuration
COPY ./build/libs/rwGuiEar.ear /opt/jboss/wildfly/standalone/deployments/

#Create user on wildfly for management
RUN /opt/jboss/wildfly/bin/add-user.sh admin login-1 --silent

# Run as root
USER root

# Set the default command to run on boot
CMD ["/start.sh"]
start.sh şöyle
#!/bin/bash
/usr/sbin/sshd -D &

# This will boot WildFly in standalone mode and bind to all interfaces
sudo -u jboss /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 -c standalone-full.xml
Örnek 
4 tane ubi image var.
micro, minimal, standard, ve init.

micro için açıklama şöyle
The ubi-micro is the smallest possible UBI image, obtained by excluding a package manager and all of its dependencies which are normally included in a container image. This minimizes the attack surface of container images based on the ubi-micro image and is suitable for minimal applications, even if you use UBI Standard, Minimal, or Init for other applications. The container image without the Linux distribution packaging is called a Distroless container image.
Açıklaması şöyle
In the following Dockerfile, we utilize the ubi-init (multi-service) image, which supports systemd and has the CMD /sbin/init as the default to start the systemd init service. 
Şöyle yaparız
FROM ubi8/ubi-init

ARG ADMIN_PUBLIC_KEY
ARG TESTER2_PUBLIC_KEY

RUN yum -y install openssh-server openssh-clients 
  && yum clean all && systemctl enable sshd;
...
EXPOSE 2022

CMD ["/sbin/init"]
Örnek - service komutunu kullanan Ubuntu
Şöyle yaparız. Burada ssh için "UsePAM yes" kullanılıyor.
#Bring OS
FROM ubuntu

# Create a user and group that is used to launch processes
# The user ID 1000 is the default for the first "regular" user on Fedora/RHEL,
# so there is a high chance that this ID will be equal to the current user
# making it easier to use volumes (no permission issues)
RUN groupadd -r jboss -g 1000 && useradd -u 1000 -r -g jboss -m -d /opt/jboss -c "JBoss user" jboss && \
    chmod 755 /opt/jboss


# Set the working directory to jboss user's home directory
WORKDIR /opt/jboss

# Install SSH Server, JDK 17
RUN apt-get update && apt-get install -y \
    sudo \
    curl \
    openssh-server \
    openssh-client \
    openjdk-17-jdk && apt-get clean all


# Set passwords
RUN echo root:login-1 | chpasswd
RUN echo jboss:login-1 | chpasswd

# Set the JAVA_HOME variable to make it clear where Java is located
ENV JAVA_HOME /usr/lib/jvm/java-1.17.0-openjdk-amd64

##Install Wildfly
# Set the WILDFLY_VERSION env variable
ENV WILDFLY_VERSION 25.0.0.Final
ENV WILDFLY_SHA1 238e67f48f1bd1e79f2d845cba9194dcd54b4d89
ENV JBOSS_HOME /opt/jboss/wildfly

ADD docker/ubuntu/start.sh /
RUN chmod +x /start.sh

# Add the WildFly distribution to /opt/jboss, and make jboss user the owner of the extracted tar content
# Make sure the distribution is available from a well-known place
RUN cd $HOME \
    && curl -L -O https://github.com/wildfly/wildfly/releases/download/$WILDFLY_VERSION/wildfly-$WILDFLY_VERSION.tar.gz \
    && sha1sum wildfly-$WILDFLY_VERSION.tar.gz | grep $WILDFLY_SHA1 \
    && tar xf wildfly-$WILDFLY_VERSION.tar.gz \
    && mv $HOME/wildfly-$WILDFLY_VERSION $JBOSS_HOME \
    && rm wildfly-$WILDFLY_VERSION.tar.gz \
    && chown -R jboss:0 ${JBOSS_HOME} \
    && chmod -R g+rw ${JBOSS_HOME}

# Create folders for batch processing
RUN bash -c 'mkdir -p /advdata/TspFt/BatchProcessingRoot/rwbat/{input,tmp,output,classicInput,classicTmp,classicOutput}'
RUN chown -R jboss /advdata/TspFt/BatchProcessingRoot/rwbat/

# Ensure signals are forwarded to the JVM process correctly for graceful shutdown
ENV LAUNCH_JBOSS_IN_BACKGROUND true

USER jboss

# Expose the ports in which we're interested
EXPOSE 22
EXPOSE 8080
EXPOSE 9990


#Deploy local files
ADD  docker/modules/system/layers/base/com /opt/jboss/wildfly/modules/system/layers/base/com/
COPY docker/standalone-full.xml /opt/jboss/wildfly/standalone/configuration
COPY build/libs/rwGuiEar.ear /opt/jboss/wildfly/standalone/deployments/

#Create user on wildfly for management
RUN /opt/jboss/wildfly/bin/add-user.sh admin login-1 --silent

# Run as root
USER root

# Set the default command to run on boot
CMD ["/start.sh"]
start.sh şöyledir
service ssh restart

# This will boot WildFly in standalone mode and bind to all interfaces
sudo -u jboss /opt/jboss/wildfly/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 -c standalone-full.xml


11 Nisan 2022 Pazartesi

Jakarta EE Generics

Örnek
Şöyle yaparız
interface MyInterface<T> { }

class MyStringBean implements MyInterface<String> { }

class MyIntegerBean implements MyInterface<Integer> { }

// resolves to MyStringBean:
@Inject
MyInterface<String> myString;

// resolves to MyIntegerBean:
@Inject
MyInterface<Integer> myInteger;

Jakarta EE Instance Arayüzü

Giriş
Açıklaması şöyle
A more powerful solution is Instance (resembles Spring’s ObjectProvider, and extends Provider) because it comes with

an iterator, which allows running for-loops over multi-valued dependencies (0..n)
a stream() method
methods for checking the availability and uniqueness of the dependency
Açıklaması şöyle
The following table summarizes the return value of the three boolean check methods, depending on the number of provided bean instances:                               

# OF INSTANCES ISRESOLVABLE ISUNSATISFIED ISAMBIGUOUS
0                         false                 true                         false
1                         true                         false                 false
>1                         false                 false                 true
Instance also allows applying additional filters (based on type and qualifier) when invoking its “select()” method, which is most useful in combination with programmatic injection
Örnek
Şöyle yaparız
@Inject
Instance<Pet> petInstances;

...

// loop over instances:
for (Pet pet : petInstances) {
  ...
}

// instance stream:
petInstances.stream().forEach(...);

// boolean check methods:
petInstances.isResolvable();
petInstances.isUnsatisfied();
petInstances.isAmbiguous();

Jakarta EE CDI Sınıfı - Programmatic Injection

Örnek
Şöyle yaparız
// type filter for retrieving a Cat:
Cat cat = CDI.current().select(Cat.class).get();

// type and annotation filter for retrieving a @Feline Pet:
MyInterface myBean = CDI.current()
  .select(
    Pet.class, 
    new AnnotationLiteral<Feline>() {})
  .get();

Jakarta EE Provider Arayüzü

Giriş
Açıklaması şöyle
Delayed injection is possible with a Provider, which resembles Spring’s ObjectFactory:
...
The call to “get()” throws an exception if there is no unique bean for this dependency.
Örnek
Şöyle yaparız
@Inject
private Provider<Pet> petProvider;

...

Pet pet = petFactory.get();

Jakarta EE @Named Anotasyonu

Giriş
Açıklaması şöyle
It is a special qualifier with a String value attribute. When used at an injection point, only beans with a matching @Named qualifier are considered:
Örnek
Şöyle yaparız
@Named("feline")
class Cat implements Pet { }

@Inject
@Named("feline")
Pet felinePet;
Örnek
Açıklaması şöyle
@Named is special in that it does not replace the implicit @Default qualifier. Hence, the following definition-injection pair is a match (given that there is no other Pet candidate):
Şöyle yaparız
// bean definition with @Named,
// retains the implicit @Default qualifier: @Named("feline") class Cat implements Pet { } // injection point with implicit @Default qualifier: @Inject Pet felinePet;


Jakarta EE @AlternativeAnotasyonu - Belirsizlik (Disambiguation) İçindir

Örnek
Şöyle yaparız
@Alternative
class Dog implements Pet { }

@Alternative
class Cat implements Pet { }
Örnek - beans.xml
Şöyle yaparız
<beans>
  <alternatives>
    <class>foo.bar.Cat</class>
  </alternatives>
</beans>


Jakarta EE @Vetoed Anotasyonu - Belirsizlik (Disambiguation) İçindir

Giriş
Açıklaması şöyle.  @Alternative ile karşılaştırılabilir
The simplest way to eliminate ambiguity among injectable beans is to apply the @Vetoed annotation to the beans that shall not be considered for injection
Örnek
Şöyle yaparız
@Vetoed
class Dog implements Pet { }

class Cat implements Pet { }

Bean Validation @GroupSequence Anotasyonu

Örnek Elimizde şöyle bir kod olsun public class SampleRequest {   @NotNull   LocalDate startDate;   @NotNull   LocalDate endDate;   @AssertT...