23 Aralık 2021 Perşembe

Hamcrest

Giriş
Açıklaması şöyle
Hamcrest is an assertion library that helps to build a declarative pipeline of matchers.
assertThat 
Şu satırı dahil ederiz
import static org.hamcrest.MatcherAssert.assertThat;
Daha sonra hazır gelen Matchers.XX metodları ile kullanırız

Collection Matcher
empty(), hasSize(), arrayWithSize(),containsInAnyOrder(),contains(),hasItemInArray(),isOneOf(),isIn(),arrayContainingInAnyOrder(), arrayContaining(),hasKey(),hasValue(),hasEntry()

gibi bir sürü metod var

hasSize
Şu satırı dahil ederiz
import static static org.hamcrest.collection.IsCollectionWithSize.hasSize;
Örnek
Şöyle yaparız
assertThat(res, hasSize(3));
TypeSafeMatcher
matchesSafely() ve describeTo() metodlarını override etmek yeterli.
Örnek
Şöyle yaparız
Matcher<List<PostView>> hasComments(int count) {
  return new TypeSafeMatcher<>() {
    @Override
    protected boolean matchesSafely(List<PostView> item) {
      return item.stream()
            .allMatch(post -> post.comments().size() == count);
    }

    @Override
    public void describeTo(Description description) {
      description.appendText(count + " comments in each post");
    }

    @Override
    protected void describeMismatchSafely(List<PostView> item,
                                          Description mismatchDescription) {
      mismatchDescription.appendText(
        item.stream()
          .map(postView -> format(
                    "PostView[%d] with %d comments",
                    postView.id(),
                    postView.comments().size()
           ))
           .collect(joining(" ; "))
      );
    }
  };
}


22 Aralık 2021 Çarşamba

Mockito @MockitoSettings Anotasyonu

Giriş
Şu satırı dahil ederiz
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
Örneği ilk burada gördüm. Aslında bu çözümler sadece UnnecessaryStubbingException fırlatılmasını engelliyor. Testleri halen temizlemekte fayda var. Verilen hata şöyle
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at pl.nsn.railway.grkeepalive.MyTest.testLenient(MyTest.java:41)
  2. -> at pl.nsn.railway.grkeepalive.MyTest.testLenient(MyTest.java:42)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.

Örnek - JUnit 4
Şöyle yaparız. Böylece artık UnnecessaryStubbingException dikkate alınmaz
@RunWith(MockitoJUnitRunner.Silent.class)
public class FooTest {
  ...
}
Örnek - JUnit 5 
@MockitoSettings(strictness = Strictness.LENIENT) kullanırız. Böylece artık UnnecessaryStubbingException dikkate alınmaz
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class MyTest {

  public class MyFrameworkRuntimeProvider {
    String getContainer(String name) {
      return name;
    }
    String getComponentHandle() {
     return null;
    }
  }
  //@Mock
  //MyFrameworkRuntimeProvider mock;

  @Test
  public void testLenient(){

    MyFrameworkRuntimeProvider mock = Mockito.mock(MyFrameworkRuntimeProvider.class);
    Mockito.when(mock.getContainer("1")).thenReturn("1");
    Mockito.when(mock.getContainer("2")).thenReturn("2"); //not called
    Mockito.when(mock.getComponentHandle()).thenReturn(null);//not called
    
    mock.getContainer("1");

    Mockito.verify(mock,Mockito.atLeast(1)).getContainer(Mockito.anyString());
  }
}

16 Aralık 2021 Perşembe

args4j - Command Line (CLI) Parsing

Gradle
Şu satırı dahil ederiz
dependencies {
  implementation 'args4j:args4j:2.32'
}
Bu kütüphaneyi kullanmak Apache CLI kütüphanesine göre daha kolay.

Örnek
Elimizde şöyle bir kod olsun. 
- name ile parametrenin kısa ismi belirtilir
- alias ile parametrenin uzum ismi belirtilir
- usage ile yardım metni belirtilir. 
- required ile parametrenin zorunlu olup olmadığı belirtilir
import org.kohsuke.args4j.Option;

public class CLIParams {
  
  String user;
  String password;
  
  boolean help;

  @Option(name = "-u", aliases = "--user", usage = "user name", required = true,
                 metaVar = "<name>")
  public void setUser(String user) {
    this.user = user;
  }

  @Option(name = "-p", usage = "password", required = true, metaVar = "<password>")
  public void setPassword(String password) {
    this.password = password;
  }

  @Option(name = "-h", usage = "help screen", required = false)
  public void setHelp(boolean help) {
    this.help = help;
  }
}
Şöyle yaparız
import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;

public static void main(String[] args) {

  CLIParams params = new CLIParams();
  CmdLineParser cliParser = new CmdLineParser(params);
  try {
    cliParser.parseArgument(args);
    ...
  } catch (CmdLineException e) {
    showHelp();
    System.exit(1);
}

public void showHelp() {
  CLIParams params = new CLIParams();
  CmdLineParser cliParser = new CmdLineParser(params);
  cliParser.printUsage(System.out);
}


12 Aralık 2021 Pazar

CompactNumberFormat Sınıfı

Giriş
Şu satırı dahil ederiz
import java.text.CompactNumberFormat;
Açıklaması şöyle
CompactNumberFormat class is the subclass of NumberFormat class in java.text package, NumberFormat class formats a number in compact form. 

The NumberFormat Style, SHORT would display 1000 as 1K and 10000 as 10K. Whereas the Style LONG will display 1000 as 1 thousand and 10000 as 10 thousand.  
format metodu
Örnek
Şöyle yaparız
NumberFormat format = NumberFormat.getCompactNumberInstance(Locale.US,Style.SHORT);
System.out.println(format.format(1000);
//Output : 1K

format = NumberFormat.getCompactNumberInstance(Locale.US,Style.LONG);
System.out.println(format.format(1000);
//Output : 1 thousand
parse metodu
Örnek
Şöyle yaparız
NumberFormat format = NumberFormat.getCompactNumberInstance(Locale.US,Style.LONG);
System.out.println(format.parse("1 thousand"); //1_000 
System.out.println(format.parse("10 million"); //10_000_000


9 Aralık 2021 Perşembe

Java Server Pages - JSP

Giriş
JSP dosyası src/main/webapp/WEB-INF/jsp/ dizinine yerleştirilir
Jsp tag'leri şöyledir
<%= ...%>
Nesnelere şöyle erişilir.
<h1>${message}</h1>
JSTL - Jakarta Standard Tag Library
jsp içine yazılan Java kodunu html gibi yazabilmeyi sağlar. JSP ile kullanılan Java nesneleri bean olmak zorunda

Maven
Şu satırı dahil ederiz. Bu kütüphanelerden herhangisi birisi olur
<dependency>
  <groupId>org.glassfish.web</groupId>
  <artifactId>jakarta.servlet.jsp.jstl</artifactId>
  <version>2.0.0-M1</version>
</dependency>

<dependency>
  <groupId>org.eclipse.jetty</groupId>
  <artifactId>apache-jstl</artifactId>
  <version>11.0.0.beta2</version>
</dependency>
Kütüphaneler şöyle
core Tags :  http://java.sun.com/jsp/jstl/core
fmt Tags : http://java.sun.com/jsp/jstl/fmt
function Tags : http://java.sun.com/jsp/jstl/functions
sql Tags : http://java.sun.com/jsp/jstl/sql
xml Tags  : http://java.sun.com/jsp/jstl/xml

core Tags variable,url management, flow control içindir
function Tags string manipulation içindir
fmt Tags message,number,date formatlama içindir

Core Tags
Core JSTL taglerini almak için şöyle yaparız.  Burada c ön eki core anlamına geliyor. Diğer kütüphanaler için fn, fmt, x, sql ön ekleri kullanılıyor. taglib ise bir JSP directive
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
...
Bazı metodlar şöyle
catch
choose
forEach
forTokens
if
import
otherwise
out
param
redirect
remove
set
url
when

c:cout
Örnek 
Elimizde şöyle bir kod olsun
<%
String name = request.getAttribute("label").toString(); out.println(name) %>
Buna erişmek için şöyle yaparız
<c:cout value="${label}"/>
Örnek
Şöyle yaparız
If you are using Java Server Pages (JSP), you need to be aware that JSP templates do not 
escape dynamic content by default. Let’s say that you want to display a message this way:

<h1>${message}</h1>

You will need to use the <c:out> tag or fn:escapeXml() function to escape potentially dangerous content in untrusted input:


<h1><c:out value="${message}"/></h1> <h1>${fn:escapeXml(message)}</h1>

c:forEach
Örnek 
students listesi üzerinde dolaşır
<c:forEach items="${students}" var="e">
  ${e.name}<br/>
</c:forEach>
c:if
Örnek 
Şöyle yaparız
<c:if test="${requestScope.isGeoRedEnabled && isAdmin}">
  ...
</c:if>


8 Aralık 2021 Çarşamba

Bouncy Castle

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15on</artifactId>
  <version>1.70</version>
</dependency>
RSA Provider
Bouncy Castle bir RSA provider. 
Örnek
Kullanmak için şöyle yaparız
import org.bouncycastle.jce.provider.BouncyCastleProvider;

   
// Load Bouncy Castle provider
Security.addProvider(new BouncyCastleProvider());

// Encrypt data using public key
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
Örnek
Elimizde şöyle bir kod olsun
KeyPair generateKeyPair() {
  try {
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048, new SecureRandom());
    return keyPairGenerator.generateKeyPair();
  } catch (GeneralSecurityException var2) {
    throw new AssertionError(var2);
  }
}
Import'lar için şöyle yaparız
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
Şöyle yaparız
Security.addProvider(new BouncyCastleProvider());

String name = ...;
Map<String, String> labels = ...;
String host = ...;

X500Principal subject = new X500Principal("CN=" + host);
X500Principal signedByPrincipal = subject;

KeyPair keyPair = generateKeyPair();
KeyPair signedByKeyPair = keyPair;

long notBefore = System.currentTimeMillis();
long notAfter = notBefore + (1000L * 3600L * 24 * 365);

ASN1Encodable[] encodableAltNames = new ASN1Encodable[]{ alonew GeneralName(GeneralName.dNSName, host)};
KeyPurposeId[] purposes = new KeyPurposeId[]{KeyPurposeId.id_kp_serverAuth, KeyPurposeId.id_kp_clientAuth};

X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( signedByPrincipal,
  BigInteger.ONE, new Date(notBefore), new Date(notAfter), subject, keyPair.getPublic());

certBuilder.addExtension(Extension.basicConstraints, true, new BasicConstraints(false));
certBuilder.addExtension(Extension.keyUsage, true, new KeyUsage( KeyUsage.digitalSignature + KeyUsage.keyEncipherment));
certBuilder.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(purposes));
certBuilder.addExtension(Extension.subjectAlternativeName, false, new DERSequence(encodableAltNames));

ContentSigner signer = new JcaContentSignerBuilder(("SHA256withRSA")) .build(signedByKeyPair.getPrivate());
X509CertificateHolder certHolder = certBuilder.build(signer);

1 Aralık 2021 Çarşamba

JasperReports

Giriş
Şu satırı dahil ederiz
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
import net.sf.jasperreports.export.SimpleCsvExporterConfiguration;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import net.sf.jasperreports.export.SimpleWriterExporterOutput;
import net.sf.jasperreports.export.SimpleXlsxReportConfiguration;
Açıklaması şöyle
JasperReports is an open source reporting engine. It provides ability to deliver rich content onto to the printer, the screen, or into various formats such as PDF, HTML, XLS, RTF, ODT, CSV, TXT and XML files.

It is a Java library and can be used in a variety of Java-enabled applications to generate dynamic content. Its main purpose is to help create page-oriented, ready-to-print documents in a simple and flexible manner. JasperReports can also be used to provide reporting capabilities in our applications.

As it is not a standalone tool, it cannot be installed on its own. Instead, it is embedded into Java applications by including its library in the application’s CLASSPATH.

Features of JasperReports :
- Flexible report layout.
- Data can be presented either textually or graphically.
- Developers can supply data in multiple ways.
- Multiple data sources can be used to transfer data.
- Watermarks can also be applied.
- Sub reports can also be generated.

Various formats of reports can be exported.
Maven
Şöyle yaparız
<dependency>
  <groupId>net.sf.jasperreports</groupId>
  <artifactId>jasperreports</artifactId>
  <version>6.4.0</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>4.1.1</version>
</dependency>
Örnek
Şöyle yaparız
private String reportPath;

public String generateReport() {
  List<Employee> employees = ...
  try {
    File file = ResourceUtils.getFile("classpath:employee-rpt.jrxml");
    InputStream input = new FileInputStream(file);
    // Compile the Jasper report from .jrxml to .japser
    JasperReport jasperReport = JasperCompileManager.compileReport(input);
    // Get your data source
    JRBeanCollectionDataSource source = new JRBeanCollectionDataSource(employees);
    // Add parameters
    Map<String, Object> parameters = new HashMap<>();
    parameters.put("createdBy", "JavaHelper.org");
    // Fill the report
    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters,
    source);
    // Export the report to various formats
    JasperExportManager.exportReportToPdfFile(jasperPrint, reportPath + "\\Emp.pdf");
    System.out.println("PDF File Generated !!");
    JasperExportManager.exportReportToXmlFile(jasperPrint, reportPath + "\\Emp.xml",
    true);
    System.out.println("XML File Generated !!");
    JasperExportManager.exportReportToHtmlFile(jasperPrint, reportPath + "\\Emp.html");
    System.out.println("HTML Generated");
    
  } catch (Exception e) {
    ...
  }
}
Daha sonra JasperReport farklı formatlara dönüştürülür. Şöyle yaparız
void csv(JasperPrint jasperPrint) throws JRException {
  JRCsvExporter exporter = new JRCsvExporter();
  exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
  exporter.setExporterOutput(new SimpleWriterExporterOutput(reportPath +
    "\\Employee.csv"));
  SimpleCsvExporterConfiguration configuration = new SimpleCsvExporterConfiguration();
  configuration.setFieldDelimiter(",");
  exporter.setConfiguration(configuration);
  exporter.exportReport();
}


void xlsx(JasperPrint jasperPrint) throws JRException {
  // Exports a JasperReports document to XLSX format. 
  //It has character output type and exports the document to a grid-based layout.
  JRXlsxExporter exporter = new JRXlsxExporter();
  exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
  exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(reportPath +
    "\\Employee.xlsx"));
  SimpleXlsxReportConfiguration configuration = new SimpleXlsxReportConfiguration();
  configuration.setOnePagePerSheet(true);
  configuration.setRemoveEmptySpaceBetweenColumns(true);
  configuration.setDetectCellType(true);
  exporter.setConfiguration(configuration);
  exporter.exportReport();
} 
Raport xml şöyledir. title, columnHeader, detail alanlarından oluşur
<?xml ...>

  <property name="ireport.zoom" value="1.0"/>
  <property name="ireport.x" value="0"/>
  <property name="ireport.y" value="0"/>
  <parameter name="createdBy" class="java.lang.String"/>
  <field name="id" class="java.lang.Integer"/>
  <field name="name" class="java.lang.String"/>
  <field name="organization" class="java.lang.String"/>
  <field name="designation" class="java.lang.String"/>
  <field name="salary" class="java.lang.Integer"/>
  <background>
    <band splitType="Stretch"/>
  </background>
  <title>
    <band height="42" splitType="Stretch">
      <staticText>
        <reportElement x="64" y="0" width="481" height="42"/>
	  <textElement textAlignment="Center">
	    <font size="20" isBold="true"/>
	  </textElement>
	  <text><![CDATA[Employee Details]]></text>
      </staticText>
    </band>
  </title>
  <columnHeader>
    <band height="61" splitType="Stretch">
      <staticText>
        <reportElement x="0" y="41" width="111" height="20"/>
	  <box>
            ...
	  </box>
	  <textElement textAlignment="Center">
	    <font size="12" isBold="true" isItalic="false"/>
	  </textElement>
	  <text><![CDATA[ID]]></text>
      </staticText>
      ...
    </band>
  </columnHeader>
  <detail>
    <band height="20" splitType="Stretch">
      <textField>
        <reportElement x="0" y="0" width="111" height="20"/>
	  <box>
	    ...
          </box>
          <textElement textAlignment="Center"/>
	  <textFieldExpression><![CDATA[$F{id}]]></textFieldExpression>
      </textField>
      ...
    </band>
  </detail>
</jasperReport>