Wednesday, November 20, 2019

Working with shared files in remote server using SMB in Java

Introduction

We are used to working with shared files where sharing is limited to users either in some domain to certain users. The remote application needs to access the shared resource and take actions such as add, delete resources in the shared location.

A server has shared resources that typically uses the Server Message Block (SMB) protocol (Server Message Block)in the Windows machine. The SMB protocol enables an application to access files on the remote servers, as well as other resources allowing a client application to open, read, move, update files on the remote server. The resource is limited to certain users. The user needs to pass credentials to access the shared resource. The activities that the user can do on the shared resource is defined in the sharing permission. Let's assume that the user has both read and write permission.

In this article, I am demonstrating a use case where an application needs to interact with shared files in Windows server machines using a simple java application. The use case makes the following assumption:

  • The server is a windows machine
  • There exists a local user named 'Test' and the password for the user is 'Password'. 
  • The shared location is '127.0.0.0.1\temp' 
  • The user 'Test' has access to the shared location 'temp' which can be anywhere in the machine that has IP of '127.0.0.1'.
  • The client application has access to the network

CodeBase:

The application that we are designing is in Java using Maven for build and dependency management. I am using JCIFS, an open-source client library that implements the CIFS/SMB networking protocol (https://www.jcifs.org/). The library is available from Maven Repository (https://mvnrepository.com/artifact/jcifs/jcifs/1.3.17).

The dependencies are shown in the following pom.xml file:
Currently, the application has one file Main.java with the following content:

Here, the main method uses a url pattern of for smb protocol and points to shared location at line 8.
Local variables for userName, password and domains are initialized in lines 9 through 11 and authenticates the user in line 13 at which time, the application has successfully connected to the shared folder.

The application creates a SmbFile object in line 15 and passes that folder to a method called doRecursiveLookup(..) in line 24. The method simply iterates through all the files and folders within the shared location and prints the names in the console in a recursive fashion. Note that the SmbFile object is the same for file or folders and .isDirectory() method was used to test if the object in scope is file or folder.

In the demo, I showed reading the resources in the remote server using SMB protocol.

Update:

Some institutions tend to disable SMB 1.0 in which case we need to use library from https://repo1.maven.org/maven2/org/codelibs/jcifs/ for newer version of the protocol. 

Additional Resources


Tuesday, August 6, 2019

Using EntityFramework in a .Net Core Project

Introduction

While I work with EntityFramework every day, I do not add an EntityFramework (EF) to an existing project every day. Time and again, I have to create a new project or add EntityFramework to the existing project and I have to re-do many steps that are hard to remember. I decided to document the steps in the form of this article.

In this article, I am going to show how to get started with EntityFramework. I will start a project without support to EntityFramework and add the EF support to the project and use a migration to update the database. The code related to this article is available at GitHub. The sample project uses in Visual Studio 2017 IDE using C#, MS SQL Server with SQL Server Management Studio (SSMS) and EntityFrameworkCore with .Net Core SDK 2.2.


Create Solution and Project

I started with the creation of an empty solution and added a WebAPI project targetting .NetCore 2.2.





As I am using MS SQL Server, I added a reference to

Microsoft.EntityFrameworkCore.SqlServer and Microsoft.EntityFrameworkCore.Design using Nuget Package Manager.


I updated the appsetting.json file for the connectionstring by adding the following property:

 "ConnectionStrings": { 
     "DefaultConnection":
        "Server=(localdb)\\mssqllocaldb;Database=ApplicationDb;Trusted_Connection=True;" }



Configure Database and Models

I have created models for Customer, Contact, and CustomerContact. The code example has these models in DBContext folder. In addition, there are classes for IAuidtable and Audit and some enums which can be ignored for now. Customer and Contact entity have many to many relationships and thus I added CustomerContact entity to store the relationship.


public class Customer : IAuditable
    {
        public Guid Id { get; set; }
        public String AccountNumber { get; set; }
        public String Name { get; set; }
        public DateTime? CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public String LastModifiedBy { get; set; }
        public bool IsInactive { get; set; }
        public ICollection<CustomerContact> CustomerContacts { get; set; }
    }

    public class Contact : IAuditable
    {
        public Guid Id { get; set; }
        public String Name { get; set; }
        public String Title { get; set; }
        public String Phone { get; set; }
        public String Email { get; set; }
        public ContactTypeEnum ContactType { get; set; }
        public String Note { get; set; }
        public DateTime? CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public String LastModifiedBy { get; set; }
        public bool IsInactive { get; set; }
        public ICollection<CustomerContact> CustomerContacts { get; set; }

    }

    public class CustomerContact:IAuditable
    {
        public Guid Id { get; set; }
        public DateTime? CreatedDate { get; set; }
        public DateTime? ModifiedDate { get; set; }
        public string LastModifiedBy { get; set; }
        public bool IsInactive { get; set; }
        public Guid CustomerId { get; set; }
        public Customer Customer { get; set; }
        public Guid ContactId { get; set; }
        public Contact Contact { get; set; }
    }

    public class Audit
    {
        public Guid Id { get; set; }
        public Guid? EntityId { get; set; }
        public string User { get; set; }
        public String Entity { get; set; }
        public DateTime DateTime { get; set; }
        public string ColumnName { get; set; }
        public String OldValue { get; set; }
        public String NewValue { get; set; }
        public EntityStateChangeTypeEnum ChangeType { get; set; }

    }
    /// <summary>
    /// This interface determines what will be automatically tracked.
    /// </summary>
    interface IAuditable
    {
        Guid Id { get; set; }
        DateTime? CreatedDate { get; set; }
        DateTime? ModifiedDate { get; set; }
        String LastModifiedBy { get; set; }
        bool IsInactive { get; set; }
    }

    public enum EntityStateChangeTypeEnum
    {
        Added,
        Deleted,
        Modified,
    }

    public enum ContactTypeEnum
    {
        Primary,
        Secondary,
        Emergency,
    }


With these changes, I am ready to set up code-first logic for creating database tables. I am going to create a class ApplicationDbContext that derives from DbContext of EntityFrameworkCore. In this class, I create DbSet objects of the type of Customer, Contact, CustomerContact, and Audit. This is what makes EF aware of the tables I need to create.


using Microsoft.EntityFrameworkCore;

namespace AutotrackEntityChange.DBContext
{
    public class ApplicationDbContext: DbContext
    {
        //Define DbSets
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Contact> Contacts { get; set; }

        public DbSet<CustomerContact> CustomerContacts { get; set; }
        public DbSet<Audit> Audits { get; set; }

        public ApplicationDbContext(
          DbContextOptions<ApplicationDbContext> options)
            : base(options) {}
    }
}


Now I need to add service in the Startup.cs class to use ApplicationDbContext within the application. The service can be added inside the ConfigureService method using the following code:


 services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration
            .GetConnectionString("DefaultConnection")));


Note that the service addition above uses the same DefaultConnection that was defined in the appsetting.json earlier.


Migration and Database Update

I can run the 'Add-Migration 'InitialCreate'' command in the Package Manager Console within the Visual Studio to generate necessary migration scripts.


This will create necessary Migration files in the solution under Migration folder.


Now I can run 'Update-Database' command in the Package Manager Console to apply the migration. 

Note that at this time, the migration code will generate the database and the tables inside 'ApplicationDb' database. I can now open SSMS and navigate to the database and see the tables.



Summary

In this article, I showed steps to add EntityFramework support to a .Net Core project using Code-First approach and migrations. I provided an example using a WebAPI project with SQL Server, but the steps mentioned here can be used for other database and other project types. The migration I used was really for creating the database and entities, but a similar approach can be used to update the entities. am hoping this will help someone and I welcome comments and suggestions.

References

Sunday, August 4, 2019

Remove commit history in git

Have you ever had a need to clean up all the history in the git repository? I have. I dealt with this old fashioned way until I started interacting with the command line.  The old fashioned way is to create a new repository and update files and replace the old with a new one. In this article, I am going to show how to clean the commit history in git using tools and technique using command lines.  

Method 1: Re-init the repository

In this method, I remove and recreate the git and modify the origin and then I can push the code to remote. The following set of commands can be used:
$ rm -rf .git
$ git init
$ git add .
$ git commit -m "Starting Commit"
$ git remote add origin [......]
$ git push -u --force origin master

Method 2: Alter the branch


In this method, I initially create a temp branch, add all the files to that branch, delete the old branch and then rename the current branch to master and then push the changes to remote. Following sets of commands can do the job. 
$ git checkout --orphan temp
$ git add -A
$ git commit -am "Starting Commit"
$ git branch -D master
$ git branch -m master
$ git push -f origin master

Method 3:  Squashing the commits 

In this method, I combine all the commits into one which is known as squashing. For example, if I have 25 commits since the beginning, then I can combine all commits into one by using the following steps for squashing commits into one and amending the commit message:
$ git rebase -i Head~25
$ #edit the commits mannually
$ git commit –amend

Wednesday, July 31, 2019

Unit Testing C++ Code with Visual Studio

Unit Testing has been an inherent part of software development today. In Unit Testing, individual units of software are tested. While manual testing of individual functionality has been part of the development cycle, more recently these testing is automated with a testing framework.

In this article, I am going to illustrate the unit testing example in C++ using Visual Studio 2017 IDE and Native Unit Test Project. For illustration, unit test and actual software are contained within a solution. The code is contained in the basiccpp solution which currently includes one project and one test project and can be obtained from GitHub.

To get started, I have a solution named ‘basiccpp’ solution. The solution currently contains a console application, basiccpp, written in C++.

Step 1: Add a test project.
In the solution explorer, right-click to get the context menu and click ‘Add’ and select Test. Select the test framework. In this example, I am using ‘Native Unit Test Project’. The native unit test project resides in namespace “Microsoft::VisualStudio::CppUnitTestFramework”.


The test project created will test the functions within the basiccpp project. The basiccpp project is a window console application written in C++. 


Step 2: Add a reference

For the test project to get access to the basiccpp project, I will add a reference to the project.
Right-click the ‘References’ in the test project, and click Add Reference and in the window displayed, check the basiccpp project. If a single test project needs to test multiple projects, then I would select all the projects I am testing. 


Now the reference is added, I can start creating tests for the projects.

Step 3: Add Test
By default, Visual Studio template provides us with a unittest1.cpp file. I am going to rename this such that I know by looking at the file name the behavior I am testing. In this example, I am going to test Array.cpp file. Thus, I would name it as ‘ArrayTest.cpp’.

The specification of Array is in Array.hpp file and actual impelementaiton is in Array.cpp file. The content of this Array.hpp file is shown below:

#pragma once
#ifndef ARRAY_HPP_INCLUDED
#define ARRAY_HPP_INCLUDED
#endif

#include <cassert>
#include <ostream>
#include <utility>

template <typename T>
class Array {
private:
       T* m_ptr{ nullptr };
       int m_size{ 0 };
public:
       Array() = default;
       ~Array();
       //Constructor to create an array of defined size
       explicit Array(int size);
       //copy constructor
       Array(const Array& source);
       T& operator[](int index);
       T operator[](int index) const;
       void print() const;
       int Size() const;
       bool IsValidIndex(int index) const;
};

For testing, I will add test targeting publicly exposed the function of Array<T> class.
Since I am targeting functions defined in Array.hpp in basiccpp project, I am going to include Array.cpp in the ArrayTest.cpp by adding the following line:

#include "..\basiccpp\Array.cpp"

The Visual Studio will provide the IntelliSense as I am typing to the referenced project and I can select the correct include file.  




Step 4: Create tests

I am going to update the content of ‘ArrayTest.cpp’. In minimum, the structure of the test class one method with the following structure: 

namespace basicTest
{
       TEST_CLASS(my_test_class)
       {
       public:

              //test creation, size and [] operators.
              TEST_METHOD(my_test_method)
              {
                      //TODO: add test logic here.
              }
}
}

I can create as many methods within the class. The full content of the file test class for ArrayTest is shown below:

#include "stdafx.h"
#include "CppUnitTest.h"
#include "..\basiccpp\Array.cpp"
#include <functional>
#include <assert.h>

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace basicTest
{
       TEST_CLASS(ArrayTest)
       {
       public:

              //test creation, size and [] operators.
              TEST_METHOD(ArrayTest_Size)
              {
                     int size = 5;
                     Array<int> mArray{ size };
                     for (int i = 0; i < size; i++) {
                           mArray[i] = i;
                     }
                     Assert::AreEqual(size, mArray.Size());
                     Assert::IsTrue(mArray[0] == 0);
                     Assert::IsTrue(mArray[4] == 4);
              }

              //test the empty function
              TEST_METHOD(ArrayTest_Empty)
              {
                     int size = 5;
                     Array<int> mArray0{ 0 };
                     Assert::IsTrue(mArray0.IsEmpty());

                     Array<int> mArray{ size };
                     for (int i = 0; i < size; i++) {
                           mArray[i] = i;
                     }
                     Assert::IsFalse(mArray.IsEmpty());
              }

              //test  isValidIndex function
              TEST_METHOD(ArrayTest_IsValidIndex)
              {
                     int size = 5;
                     Array<int> mArray{ size };
                     Assert::AreEqual(size, mArray.Size());
                     Assert::IsTrue(mArray.IsValidIndex(1));
                     Assert::IsFalse(mArray.IsValidIndex(5));
              };

              //Test the method indexoutofbount by passing the invalid index and checking
              //if the exception is thrown
              TEST_METHOD(ArrayTest_IndexoutOfBound)
              {
                     int size = 5;
                     Array<int> mArray{ size };
                     auto func = [mArray, size] {
                           mArray[size + 100]; };
                     Assert::ExpectException<IndexOutOfBoundsException>(func);
              }

              //test copy constructor
              TEST_METHOD(ArrayTest_CopyConstructor)
              {
                     int size = 5;
                     Array<int> mArray{ size };
                     for (int i = 0; i < size; i++) {
                           mArray[i] = i;
                     }
                     Array<int> cArray = mArray;
                     cArray[0] = 100;
                     Assert::IsTrue(cArray[0] != mArray[0]);
              }
       };
}

Step 5: Run the test using Test Explorer
Once I have written the test, I can build and run the test using Test Explorer. In addition, by adding breakpoints to the method as well as in the test, I can debug the test. 


Additional Reference:
Write unit tests for C/C++ in Visual Studio
Using Assert::ExpectException with Native Unit Testing in VS11
GitHub page for the code
GitHub Link for Code

Friday, June 14, 2019

Combine multiple git commits into a single commit in GIT using squash



Introduction

As a developer, one wants to keep the commits cleaner. At the same time, while developing I also want to keep the detailed record of changes I made and commits I make. From the start to the end, depending on scope, I might have made many trivial commits and after I am happy with the changes, I would like a few (sometimes one while at other times multiple) commits to indicate what changed, rather than to have several commit messages.

Squash in GIT can be used to combine multiple individual commits into one. This makes commits in the repository cleaner. For illustration, let’s say that we have about 25 commits from the beginning through the end of development on an issue. During those 25 commits, several code changes were made which may not be of high importance to remain in the repository. Those 25 commits can be wrapped to a single commit before it can be merged into a master branch.

The rebase command in the interactive mode (i.e. -i or –interactive) can be used to combine those comments into one.

I am using git bash in this article and I have 25 commits on a branch which I want to modify to have just one commit reflecting a feature has been completed.

Git commit history


Rebasing

Run the following command to ensure that I am picking 25 commits in the branch I am in.
git rebase -i Head ~25
Git Bash Window

The above command is instructed to get 25 commits from the head. Upon execution, the git opens a text editor showing the commit details (messages) of the last 25 commits.  

Editor to mark commits as squash or pick

I can edit the commits by putting ‘Squash’ on all the commits by changing ‘pick’ to ‘squash’ and leaving one commit with ‘pick’, probably the first one in the list i.e. the latest. We can change that message later on. In the example, I am picking the first one as shown in the figure: 

Editor after marking the commits as squash or pick


Save the changes in the editor by clicking the save button on the top left and close by the window by clicking ‘x’ on top right.

After rebasing in completed, the branch will change to show the commit message what had ‘pick’ in the editor.

Updating Commit Message
The commit message may not be relevant at this point and thus one may want to change the commit message. This can be achieved by
git commit –amend
The above command will open an editor just like before showing all the previous commit messages that can be changed to relevant message and save and close the editor. After which git would have updated the message.

Handling Remote
If the branch was previously pushed to remote, we need to synchronize the commits to remote as well.

Since the branch appears different in remote it might find conflicts. Thus, we must force the local branch which will replace the remote with the latest local changes by squash.
Git push –force

With the rebase, amend and force I was able to combine the twenty-five smaller commits into one with one clear message, both in remote and local.