Thursday, 28 November 2019

JUnit 5

JUPITER

Juipter - For newer test cases
Vintage package -- Older
EXT - JAp

Core platform, Jupiter dependecies to be added
junit-jupiter-api
junit-jupiter-engine
junit-vintage-engine //optional for prev versions of junit  ex: junit 4

@Test annotation: It marks the method that we want to test
@Test
    void testDivide() {       
        assertThrows(ArithmeticException.class, () -> mUtils.divide(1, 0), "divide by Zero exception");
     }

assertEquals(expected, actual) // provided by junit framework matches the expected &actual values.
assertArrayEquals(expectedArray, actualArray) //verify each item in array are equal in the right position
assertIterableEquals(expectedArray, actualArray)//verify each item in iterable are equal in the corresponding position
assertFalse()
assertTrue()

Maven Surefire plugin

When a method is throwing exceptions we use : assertThrows

Test Life Cycle:: Project instance created, managed & destroyed
Junit creates new class instance for every method / test run

Junit provides a mechanism which can be run before every test
@BeforeEach to get rid of multiple class instantiation, please run this before anything else
@BeforeEach
    void init() {
        mUtils = new MathUtils();
    }


@AfterEach


    void cleanup() {
        System.out.println("Cleaning up.....");
    }


@BeforeAll, @AfterAll needs to be defined static class level as there could be some methods which would be instantiating objects. Without instantiating if you want to access class these methods have to be static.

@TestInstance

@DisplayName  -> method name how it is displayed in test results
@Disabled ->If we want to some test method from being executed, to prevent it from blocking the program. Skip the test. Make it disabled

Conditional Execution:
@EnabledOnOs(OS>LINUX) -> Enable test on only particular OS.
@EnabledOnJre(JRE.JAVA_11)


assertAll -> Way to run bunch of assertions altogether
@Test
    @DisplayName("Multiple Addition ")
    void testAdd() {
        //Using lambdas multiple assert statements
        assertAll(
                () -> assertEquals(4, mUtils.add(2, 2)),
                () -> assertEquals(2, mUtils.add(2, 0)),
                () -> assertEquals(1, mUtils.add(2, -1))
                );
    }

@Nested -> Create a bunch of tests and group them together
@Nested
    class AddTest {
       
        @Test
        @DisplayName("Multiple Addition ")
        void testAdd() {
            //assertEquals(4, mUtils.add(2, 2),"Addition");
            //Using lambdas multiple assert statements
            assertAll(
                    () -> assertEquals(4, mUtils.add(2, 2)),
                    () -> assertEquals(2, mUtils.add(2, 0)),
                    () -> assertEquals(1, mUtils.add(2, -1))
                    );
        }
        @Test
        @DisplayName("Multiple Addition ")
        void testAddPositive() {
            assertAll(
                    () -> assertEquals(4, mUtils.add(2, 2))
                    );
        }
       
    }

Lazy Assert messages:

Tuesday, 26 November 2019

RabbitMQ

RabbitMQ is one of the most popular open source message brokers. Use the below link to download it.
https://www.rabbitmq.com/download.html
>Click on Windows installer
>Save the exe file. Before installing Rabbitmq, it will prompt us to install Erlang/OTP.

>Enable management center so that you can access the console through browser:
rabbitmq-plugins enable rabbitmq_management

>Url to access RabbitMq console
http://localhost:15672/
guest/guest - default userid & password


Sample Sender:
package rabbitmq;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

import java.nio.charset.StandardCharsets;

public class Sender {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            String message = "Hello World!";
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println(" [x] Sent '" + message + "'");
        }
    }
}




Sample Receiver:

package rabbitmq;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class Receiver {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    }
}




Reference:
https://www.cloudamqp.com/blog/2015-05-18-part1-rabbitmq-for-beginners-what-is-rabbitmq.html

Friday, 27 September 2019

Spring Boot Microservices

Spring Boot Microservices Demonstration:::

Consider we have 3 services which give info about Movie information and user ratings:

1)   Movie Info Service - i/p: MovieID,    o/p:Movie details
2)   Ratings Data Service - i/p:userId,    o/p:MovieId & ratings & i/p:movieId,    o/p:MovieId & ratings
3)   Movie Catalog service - i/p:userId   o/p:Movie list with details(mname, descr, details)

Steps to create individual APIs and their communication::
  • Using "start.spring.io" create 3 Maven web projects.
  • Extract downloaded projects and import them into workspace.
  • Each project will have:                                                                                                                      >A bean to hold data  (Getters, setters, default constructor, parameterized constructor)              >Resource class which will handle input requests. (@RestController, @RequestMapping with get methods)
  • In each project search for application.properties file and assign separate port number for each service. Foe ex: server.port = 8082 //catalog service
  • 3 services are buil independently with some data and can be accessed as:
http://localhost:8082/catalog/ss
http://localhost:8081/movies/ss
http://localhost:8083/ratingsdata/sam
  •  Now we will have to make these servicescommunicate to each other. This can be done by using RestTemplate / WebClient
  • In the movie catalog service we can do below steps
  1. Using userId get the movieId
  2. Using  movieId get the ratings from ratings service.
  3. Using movieId get movie name from movie info services.
Note: These calls are synchronous
  • Since RestTemplateis called everytime we hot the individual webservice url, why can't we make it singleton> This can be achieved by @Bean anootation. In MovieCatalogServiceApplication clss add below code:
@Bean
public RestTemplate getRestTemplate() {
 return new RestTemplate();
}                                                                                                                                    
  •  In the catalog resource class use it as @Autowired
@Autowired
private RestTemplate restTemplate //inject me the bean created by container

*Use Eureka server for service URL registration and discovery.
1) Create Maven project with Eureka server dependency in "start.spring.io" and add it in workspace
   >change properties so that eureka is not client and trying to find any other server
Update application.properties as:
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false

2) Register the client by including eureka client in pom.xml and required update project to get spring cloud jar. This service will be registered as client. Do this for all the 3 services.

3) @LoadBalanced -- does service discovery in load balanced way
@LoadBalanced
    public RestTemplate getRestTemplate() {
                return new RestTemplate();
    }
   
The created jars with the deployed paths are as below::

cf push testSam -p ratings-data-service-0.0.1-SNAPSHOT.jar
https://testsam.cfapps.io/ratingsdata/users/sam

cf push testSam -p movie-info-service-0.0.1-SNAPSHOT.jar
https://testsam.cfapps.io/movies/sam

cf push testSam -p discovery-server-0.0.1-SNAPSHOT.jar

cf push testSam -p movie-catalog-service-0.0.1-SNAPSHOT.jar
https://testsam.cfapps.io/catalog/sam - This is the integrated service which calls
http://ratings-data-service/ratingsdata/users/sam
http://movie-info-service/movies/1111

Friday, 6 September 2019

Spring Boot course API

::Welcome to Course API::

Actions to be performed

1) Get All the available topics

2) Get a particular topic from the list
    Java course details
    C++ course details

3) POST, DELETE, PUT operations are included in the below postman project



The relevant screens:


GET

POST

PUT

DELETE

Tuesday, 27 March 2018

Error 404: SRVE0190E: File not found: /stores/servlet/.. in Websphere Commerce

You might encounter this error in various scenarios. The scenario for which I got this error was when I tried removing stores project from the workspace and checked out a fresh version from svn. The metadata was corrupt and was facing this issue on loading any pages from the local.

To solve this issue:
1. Open properties for WC
WC-> Properties-> Deployment Assembly -> Add the Stores project.
2. Right click server -> Add remove WC
3. Publish the server.

This should solve any dependency issues. Also do not forget to check for other dependencies between the rest projects that exist in your application.

Friday, 5 January 2018

Disabling Process order call

If your workspace console is flooded with too many process order calls for the pending orders, you can disable the event in wc-server.xml file as below. This event is used by an event listener to transfer an order to a back end system.

<component
            compClassName="com.ibm.commerce.event.impl.ECEventEnableComponent"
            enable="false" name="OrderSubmit Event">
            <property display="false">
                <event name="OrderSubmit"/>
            </property>
        </component>

Source: https://www.ibm.com/support/knowledgecenter/en/SSZLC2_7.0.0/com.ibm.commerce.admin.doc/tasks/tlsdisablebusevents.htm

Friday, 13 October 2017

Creating List using JSTL

We can create a list and add items to the list using existing jstl tag library (wcf).

Here is the simple example to create new list and add items to list in jsp:

<wcf:useBean var="myNewList" classname="java.util.ArrayList"/>

<c:forEach var=eachItem items="${myOldList}">
<wcf:set value="${eachItem}" target="${myNewList}"/>
</c:forEach>


Sunday, 6 March 2016

Configure Test Environment URL in Websphere Commerce

In your project there could be a requirement to change the URL of existing test environment application / Or if it is the first time you are trying to configure a URL for websphere application. The url changes can be done in WAS admin console. But there are some more settings needed to be done based on your webserver type and if it is hosted locally or in a different machine. The webserver example that I have used below here is an IIS server hosted in different machine.

1. First make the necessary host name / port number changes in WAS admin console.
For ex: You might need your host name to look like www.test1.com. So accordingly you can add the entry in virtual hosts of deployment manager.
Got to -> WAS admin console -> Environment -> Virtual Hosts -> click on the virtual host of your environment -> Under Additional Properties, click Host Aliases.-> New -> Give the new host name for port number 80 and 443. -> Save.
Now this change has to be updated to the webserver plugin file. And this can be done by update plugin option just below the Virtual Hosts option. Click on it.

This option updates the plugin-cfg.xml file present in the path F:\IBM\WebSphere\AppServer\profiles\testProfile\config\cells\plugin-cfg.xml. (The path may vary based on your WCS installation path)

See the below note highlighted in red carefully - 

So this means if your IIS server is hosted in different machine then you need to copy the plugin XML change to the IIS server.
So copy the xml file from  F:\IBM\WebSphere\AppServer\profiles\...\config\cells\ path to ex: E:\Program Files\IBM\WebSphere\Plugins\config\webserver1 based on your webserver installation path.

And you will be able to hit the environment with your new URL!

More info : - http://www-01.ibm.com/support/docview.wss?uid=swg21216587

Saturday, 30 January 2016

EJB Deploying error in QuickBuild

Courtesy: http://masteringwcs.blogspot.in/2013/03/ejb-deploying-error-in-quickbuild.html
EJB Deploying error in QuickBuild
   Error
[zip] Building zip: E:\working\compile\ejb\WebSphereCommerceServerExtensionsData.input.jar
[wsejbdeploy] EJB Deploy configuration directory: f:\IBM\WebSphere\AppServer\deploytool\itp\configuration/
[wsejbdeploy] framework search path: f:\IBM\WebSphere\AppServer\deploytool\itp\plugins
[wsejbdeploy] build: RAD7555-I20111019_1739
[wsejbdeploy] 30-Jan-2016 08:00:32 DDLGenerationOperation runDDL
[wsejbdeploy] SEVERE:
[wsejbdeploy] Throwable occurred: java.lang.NoSuchFieldError: com/ibm/datatools/internal/core/util/EngineeringOptionID.GLOBAL_VARIABLE
[wsejbdeploy]     at com.ibm.datatools.db2.luw.ddl.LUWDdlGenerator$SingletonOptionDependency.getSingletonObject(LUWDdlGenerator.java:2414)

   

Cause

     This is a known issue cause by two old data tool plugins that existed in "deploytools/itp/plugins/" directory:
  • com.ibm.datatools.core_3.0.101.v200811190853.jar
  • org.eclipse.datatools.modelbase.sql.query_1.0.1.v200811050430.jar

  Resolving the problem

  1. Remove the old data tool plugins 
  • ​Navigate to "deploytools/itp/plugins/" directory
  • Back up the following jar files
    • com.ibm.datatools.core_3.0.101.v200811190853.jar
    • ​org.eclipse.datatools.modelbase.sql.query_1.0.1.v200811050430.jar
  • Remove the jar files from step #2 in the "deploytools/itp/plugins/" directory
  • Navigate to "/opt/IBM/WebSphere/AppServer/deploytool/itp/configuration" 
  • Back up the "/configuration" directory
  • Delete all the files and directories within "/configuration" directory
  1. Note: Except "config.ini" if present. 
Run wcbd-build again and verify the result.

Friday, 31 July 2015

JSTL Tag libraries

JSTL tag library is a component technology for J2EE applications handled by Sun microsystems. They are a package of simple tag libraries useful for buiding dynamic jsps. They are easily understandabe and useful for non programmers which can be used as alternative for the scriptlets:

Types of JSTL tags:
c - core
fmt - formatting
x - XML processing
sql - db access
fn - functions

Types of C tags:
1. <c:set var="name" value="sam" />
2. <c:out value="${name}" />
3. <c:choose>
      <c:when test="${}">
           ....
      </c:when>
      <c:otherwise>
          ....
      </c:otherwise>
    </c:choose>
4. <c:if test="${name eq 'same'}" ></c:if>
5. <c:import url="src/main.jsp" />
6. <c:import url="src/main.jsp" >
         <c:param var="id" value="1001" />
    </c:import>
7. <c:url var="main" url="src/main.jsp"/>
8. <c:redirect url="${src/redirect.jsp}" />
etc..

fmt tags:
1. <fmt:setBundle var="storeText" basename="${jspStoreDir}StoreText" /> - set it in a scoped variable
2. <fmt:message bundle="${storeText}" key="errMsg" var="errMsg" />
3. <fmt:setLocale value="${CommandContext.locale}" /> - set defualt locale value for the scope
4. <fmt:bundle basaename="${jspStoreDir}StoreText" prefix="label" /> - sets localization context
5. <fmt:param > EX:
    <fmt:message key="errMsg">
       <fmt:param userId="${userId}" />
    </fmt:message>
6.<fmt:formatNumber  type="currency" value="2.5" />
7. <fmt:formatDate var="bday" value="05/01/99" pattern="MM/DD/YY" />
8. <fmt:formatNumber var="rate" value="400" pattern="###.##" type="number" />
etc..

SQL tags:
For executing SQl queries
1. <sql:query var="users">
     SELECT * FROM USERS WHERE NAME="sam"
    </sql:query>
2. <sql:update var=count>
      UPDATE USERS SET LASTNAME="SSS" WHERE users_id=1001
  </sql:update>
3. sql:param EX:
   <sql:update var=count>
      UPDATE USERS SET LASTNAME="SSS" WHERE users_id=?
     <sql:param value="1001" />
     </sql:update>
4. <sql:transaction>
       <sql:update sql="INSERT INTO USERS VALUES(1002, 'XXX', 'YYY')" />
    </sql:transaction>
etc..

xml tags:
1. <x:parse> - Fo parsing XML content
2. <x:out> printing xpath expression
3. <x:set> -
4. <x:if>
5. <x:choose>
etc..

fn tags
1. fn:replace (string, beforeStr, afterStr)
2. fn:subString (string, beginindex, endIndex)
3. fn:length(string)
4.  fn:escapeXml(string)
5.fn:containsIgnoreCase(string, subString)

etc..

wcbase:useBean tag
<wcbase:useBean id=usersDataBean className=com.ibm.commerce.myBeans.MyDataBean  scope="page">
 <c:set property="my_id" value="1001" target="${usersDataBean}" />
</wcbase:useBean>

Other way of inoking databean from jsp is using jsp:useBean tag
<jsp:useBean id="mydataBean" className="com.ibm.myBeans.MyDataBean" scope="page">
<% com.ibm.commerce.beans.DataBeanManager.actiate(mydataBean,request,response);%>
<jsp:useBean>

Wednesday, 29 July 2015

Command registry framework in websphere commerce

Websphere commerce controller command and task commands are registered in command registry framework.

Interfacename
MyControllerCmd --> extends --> com.ibm.commerce.commands.ControllerCommand

Implementation class:
MyControllerCmdImpl --> extends --> com.ibm.commerce.commands.ControllerCommandImpl
and 
MyControllerCmdImpl implements MyControllerCmd
            
CommandFactory is a bean used for instantiating commands in websphere commerce.
Ex:
MyControllerCmd myCmd   = null;
myCmd  = (MyControllerCmd) CommandFactory.CreateCommand(com.ibm.commerce.myCommands.MyControllerCmd, getStoreId());
myCmd.setComandContext(getCommandContext());
myCmd.setRequestProperties(this.requestProperties);
myCmd.execute();
Where this.requestProperties is a TypedProperty object has all the request properties set.

There are 2 ways of defining implementation class for the inteface in websphere commerce:

1) defaultCommandClassName -The implementation class for the interface is defined in the interface by defaultCommandClassname
Ex:
public interface MyControllerCmd  extends ControllerCommand {
public Static final String defaultCommandClassName = com.ibm.commerce.myCommands.MyControllerCmdImpl;
}
      
2) CMDREG entry- Command Registry
 This table has following columns:
STORE_ID- 0 if the same implementation command  is used for all the stores.                    
INTERFACENAME- Name of the interface
CLASSNAME - implementation class name
DESCRIPTION - short description about the command
PROPERTIES - properties that are to be passed to command

CMDREG is preferred when different implementation classes are used for different stores. i.e the logic implementation changes based on the storeID

If suppose there is different entry in defaultCommandClassName and CMDREG table for the implementation class then Command Registry takes the precedence.

Simillarly for the taskcommands
Interfacename
myTaskCommand extends  --> com.ibm.commerce.commands.TaskCommand

Implementation class:
myTaskCommandImpl extends --> com.ibm.commerce.commands.TaskCommandImpl
and 
myTaskCommandImpl implements myTaskCommand

Imp Points:
  • A controller command and task command both can be called from a controller command.
  • A task command can call a taskcommand and even controller command.
  • Both task command and controller command can have entry in CMDREG table.

Differences between controller command and task command:


Controller Command
Task Command
This is the entry point for fulfilling any request
This contains a part f business logic to be executed
This has struts entry
This cannot have an entry in struts file
Access Control policy (ACP) is enabled by default
ACP is not enabled
It has a viewname entry for redirecting the flow to the viewname after successful execution
It does not have viewname, the control is returned back to the called command.
Can be called from JSP
Cannot be called from JSP