hiboot

package module
v0.9.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 15, 2018 License: Apache-2.0 Imports: 0 Imported by: 0

README

Hiboot - web/cli application framework

hiboot

Build Status

About

Hiboot is a cloud native web and cli application framework written in Go.

Hiboot is not trying to reinvent everything, it integrates the popular libraries but make them simpler, easier to use. It borrowed some of the Spring features like dependency injection, aspect oriented programming, and auto configuration. You can integrate any other libraries easily by auto configuration with dependency injection support.

If you are a Java developer, you can start coding in Go without learning curve.

Overview

  • Web MVC (Model-View-Controller).
  • Auto Configuration, pre-create instance with properties configs for dependency injection.
  • Dependency injection with struct tag name `inject:""` or Constructor func.

Introduction to Hiboot

One of the most significant feature of Hiboot is Dependency Injection. Hiboot implements JSR-330 standard.

Let's say that we have two implementations of AuthenticationService, below will explain how does Hiboot work.

type AuthenticationService interface {
	Authenticate(credential Credential) error
}

type basicAuthenticationService struct {
}

func newBasicAuthenticationService() AuthenticationService {
	return &basicAuthenticationService{}
}

func (s *basicAuthenticationService) Authenticate(credential Credential) error {
	// business logic ...
	return nil
}

type oauth2AuthenticationService struct {
}

func newOauth2AuthenticationService() AuthenticationService {
	return &oauth2AuthenticationService{}
}

func (s *oauth2AuthenticationService) Authenticate(credential Credential) error {
	// business logic ...
	return nil
}

func init() {
	app.Register(newBasicAuthenticationService, newOauth2AuthenticationService)
}
Field Injection

In Hiboot the injection into fields is triggered by `inject:""` struct tag. when inject tag is present on a field, Hiboot tries to resolve the object to inject by the type of the field. If several implementations of the same service interface are available, you have to disambiguate which implementation you want to be injected. This can be done by naming the field to specific implementation.

type userController struct {
	web.Controller

	BasicAuthenticationService AuthenticationService	`inject:""`
	Oauth2AuthenticationService AuthenticationService	`inject:""`
}

func newUserController() {
	return &userController{}
}

func init() {
	app.Register(newUserController)
}
Constructor Injection

Although Field Injection is pretty convenient, but the Constructor Injection is the first-class citizen, we usually advise people to use constructor injection as it has below advantages,

  • It's testable, easy to implement unit test.
  • Syntax validation, with syntax validation on most of the IDEs to avoid typo.
  • No need to use a dedicated mechanism to ensure required properties are set.
type userController struct {
	web.Controller

	basicAuthenticationService AuthenticationService
}

// Hiboot will inject the implementation of AuthenticationService
func newUserController(basicAuthenticationService AuthenticationService) {
	return &userController{
		basicAuthenticationService: basicAuthenticationService,
	}
}

func init() {
	app.Register(newUserController)
}

Features

  • Apps

    • cli - command line application
    • web - web application
  • Starters

    • actuator - health check
    • locale - locale starter
    • logging - customized logging settings
    • jwt - jwt starter
    • grpc - grpc application starter
  • Tags

    • inject - inject generic instance into object
    • default - inject default value into struct object
    • value - inject string value or references / variables into struct string field
  • Utils

    • cmap - concurrent map
    • copier - copy between struct
    • crypto - aes, base64, md5, and rsa encryption / decryption
    • gotest - go test util
    • idgen - twitter snowflake id generator
    • io - file io util
    • mapstruct - convert map to struct
    • replacer - replacing stuct field value with references or environment variables
    • sort - sort slice elements
    • str - string util enhancement util
    • validator - struct field validation

and more features on the wey ...

Getting started

This section will show you how to create and run a simplest hiboot application. Let’s get started!

Getting started with Hiboot web application
Get the source code
go get -u github.com/hidevopsio/hiboot

cd $GOPATH/src/github.com/hidevopsio/hiboot/examples/web/helloworld/


Sample code

Below is the simplest web application in Go.

// Line 1: main package
package main

// Line 2: import web starter from hiboot
import "github.com/hidevopsio/hiboot/pkg/app/web"

// Line 3-5: RESTful Controller, derived from web.Controller. The context mapping of this controller is '/' by default
type Controller struct {
	web.Controller
}

// Line 6-8: Get method, the context mapping of this method is '/' by default
// the Method name Get means that the http request method is GET
func (c *Controller) Get() string {
	// response data
	return "Hello world"
}

// Line 9-11: main function
func main() {
	// create new web application and run it
	web.NewApplication(&Controller{}).Run()
}
Run web application
dep ensure

go run main.go
Testing the API by curl
curl http://localhost:8080/
Hello, world
Getting started with Hiboot cli application

Writing Hiboot cli application is as simple as web application, you can take the advantage of dependency injection introduced by Hiboot.

e.g. flag tag dependency injection


// import cli starter and fmt
import (
	"fmt"
	"github.com/hidevopsio/hiboot/pkg/app"
	"github.com/hidevopsio/hiboot/pkg/app/cli"
)

// define the command
type rootCommand struct {
	// embedding cli.BaseCommand in each command
	cli.BaseCommand
	To string
}

func newRootCommand() *rootCommand {
	c := new(rootCommand)
	c.Use = "hello"
	c.Short = "hello command"
	c.Long = "run hello command for getting started"
	c.Example = `
hello -h : help
hello -t John : say hello to John
`
	c.PersistentFlags().StringVarP(&c.To, "to", "t", "world", "e.g. --to=world or -t world")
	return c
}

// Run run the command
func (c *rootCommand) Run(args []string) error {
	fmt.Printf("Hello, %v\n", c.To)
	return nil
}

// main function
func main() {
	// create new cli application and run it
	cli.NewApplication(newRootCommand).
		SetProperty(app.PropertyBannerDisabled, true).
		Run()
}

Run cli application
dep ensure

go run main.go
Hello, world
Build the cli application and run
go build

Let's get help

./hello --help
run hello command for getting started

Usage:
  hello [flags]

Flags:
  -h, --help        help for hello
  -t, --to string   e.g. --to=world or -t world (default "world")

Greeting to Hiboot

./hello --to Hiboot
Hello, Hiboot
Dependency injection in Go

Dependency injection is a concept valid for any programming language. The general concept behind dependency injection is called Inversion of Control. According to this concept a struct should not configure its dependencies statically but should be configured from the outside.

Dependency Injection design pattern allows us to remove the hard-coded dependencies and make our application loosely coupled, extendable and maintainable.

A Go struct has a dependency on another struct, if it uses an instance of this struct. We call this a struct dependency. For example, a struct which accesses a user controller has a dependency on user service struct.

Ideally Go struct should be as independent as possible from other Go struct. This increases the possibility of reusing these struct and to be able to test them independently from other struct.

The following example shows a struct which has no hard dependencies.

package main

import (
	"github.com/hidevopsio/hiboot/pkg/app/web"
	"github.com/hidevopsio/hiboot/pkg/model"
	"github.com/hidevopsio/hiboot/pkg/starter/jwt"
	"time"
)

// This example shows that token is injected through method Init,
// once you imported "github.com/hidevopsio/hiboot/pkg/starter/jwt",
// token jwt.Token will be injectable.
func Example() {
	// the web application entry
	web.NewApplication().Run()
}

// PATH: /login
type loginController struct {
	web.Controller

	token jwt.Token
}

type userRequest struct {
	// embedded field model.RequestBody mark that userRequest is request body
	model.RequestBody
	Username string `json:"username" validate:"required"`
	Password string `json:"password" validate:"required"`
}

func init() {
	// Register Rest Controller through constructor newLoginController
	web.RestController(newLoginController)
}

// newLoginController inject token through the argument token jwt.Token on constructor
// the dependency token is auto configured in jwt starter, see https://github.com/hidevopsio/hiboot/tree/master/pkg/starter/jwt
func newLoginController(token jwt.Token) *loginController {
	return &loginController{
		token: token,
	}
}

// Post /
// The first word of method is the http method POST, the rest is the context mapping
func (c *loginController) Post(request *userRequest) (response model.Response, err error) {
	jwtToken, _ := c.token.Generate(jwt.Map{
		"username": request.Username,
		"password": request.Password,
	}, 30, time.Minute)

	response = new(model.BaseResponse)
	response.SetData(jwtToken)

	return
}

Community Contributions Guide

Thank you for considering contributing to the Hiboot framework, The contribution guide can be found here.

Documentation

Overview

Package hiboot is a web/cli app application framework

Hiboot is a cloud native web and cli application framework written in Go.

Hiboot integrates the popular libraries but make them simpler, easier to use. It borrowed some of the Spring features like dependency injection, aspect oriented programming, and auto configuration. You can integrate any other libraries easily by auto configuration with dependency injection support. hiboot-data is the typical project that implement customized hiboot starters. see https://godoc.org/github.com/hidevopsio/hiboot-data

Overview

Web MVC - (Model-View-Controller).
Auto Configuration - pre-create instance with properties configs for dependency injection.
Dependency injection - with struct tag name `inject:""` or Constructor func.

Introduction to Hiboot

One of the most significant feature of Hiboot is Dependency Injection. Hiboot implements JSR-330 standard.

Let's say that we have two implementations of AuthenticationService, below will explain how does Hiboot work.

type AuthenticationService interface {
	Authenticate(credential Credential) error
}

type basicAuthenticationService struct {
}

func newBasicAuthenticationService() AuthenticationService {
	return &basicAuthenticationService{}
}

func (s *basicAuthenticationService) Authenticate(credential Credential) error {
	// business logic ...
	return nil
}

type oauth2AuthenticationService struct {
}

func newOauth2AuthenticationService() AuthenticationService {
	return &oauth2AuthenticationService{}
}

func (s *oauth2AuthenticationService) Authenticate(credential Credential) error {
	// business logic ...
	return nil
}

func init() {
	app.Register(newBasicAuthenticationService, newOauth2AuthenticationService)
}

Field Injection

In Hiboot the injection into fields is triggered by `inject:""` struct tag. when inject tag is present on a field, Hiboot tries to resolve the object to inject by the type of the field. If several implementations of the same service interface are available, you have to disambiguate which implementation you want to be injected. This can be done by naming the field to specific implementation.

type userController struct {
	web.Controller

	BasicAuthenticationService AuthenticationService	`inject:""`
	Oauth2AuthenticationService AuthenticationService	`inject:""`
}

func newUserController() {
	return &userController{}
}

func init() {
	app.Register(newUserController)
}

Constructor Injection

Although Field Injection is pretty convenient, but the Constructor Injection is the first-class citizen, we usually advise people to use constructor injection as it has below advantages,

  • It's testable, easy to implement unit test.

  • Syntax validation, with syntax validation on most of the IDEs to avoid typo.

  • No need to use a dedicated mechanism to ensure required properties are set.

    type userController struct { web.Controller

    basicAuthenticationService AuthenticationService }

    // Hiboot will inject the implementation of AuthenticationService func newUserController(basicAuthenticationService AuthenticationService) { return &userController{ basicAuthenticationService: basicAuthenticationService, } }

    func init() { app.Register(newUserController) }

Features

App
	cli - command line application
	web - web application

Starters
	actuator - health check
	locale - locale starter
	logging - customized logging settings
	jwt - jwt starter
	grpc - grpc application starter

Tags
	inject - inject generic instance into object
	default - inject default value into struct object
	value - inject string value or references / variables into struct string field

Utils
	cmap - concurrent map
	copier - copy between struct
	crypto - aes, base64, md5, and rsa encryption / decryption
	gotest - go test util
	idgen - twitter snowflake id generator
	io - file io util
	mapstruct - convert map to struct
	replacer - replacing stuct field value with references or environment variables
	sort - sort slice elements
	str - string util enhancement util
	validator - struct field validation

Getting started

This section will show you how to create and run a simplest hiboot application. Let’s get started!

Getting started with Hiboot web application

Get the source code

go get -u github.com/hidevopsio/hiboot
cd $GOPATH/src/github.com/hidevopsio/hiboot/examples/web/helloworld/

Source Code

Example

This is a simple hello world example

package main

import "github.com/hidevopsio/hiboot/pkg/app/web"

// This is a simple hello world example
func main() {
	// the web application entry
	web.NewApplication(new(Controller)).Run()
}

// Controller is the RESTful Controller, derived from web.Controller.
// The context path of this controller is '/' by default
// if you name it HelloController, then the default context path will be /hello
// which the context path of this controller is hello
type Controller struct {
	web.Controller
}

// Get method, the context mapping of this method is '/' by default
// the Method name Get means that the http request method is GET
func (c *Controller) Get() string {
	// response data
	return "Hello world"
}
Output:

Directories

Path Synopsis
examples
cli
Package cli provides hiboot command line application examples
Package cli provides hiboot command line application examples
grpc
Package grpc provides hiboot web application service examples that communicate with gRpc protocol
Package grpc provides hiboot web application service examples that communicate with gRpc protocol
web
Package web provides hiboot web application examples
Package web provides hiboot web application examples
web/helloworld
Package helloworld provides the quick start web application example
Package helloworld provides the quick start web application example
pkg
app
Package app provides abstract layer for cli/web application Package app provides hiboot app application interface
Package app provides abstract layer for cli/web application Package app provides hiboot app application interface
app/cli
Package cli provides quick start framework for command line application.
Package cli provides quick start framework for command line application.
app/fake
Package fake provides fake.ApplicationContext for unit testing
Package fake provides fake.ApplicationContext for unit testing
app/web
Package web provides quick start framework for web application.
Package web provides quick start framework for web application.
app/web/at
Package web/annotation provides annotations for web RestController
Package web/annotation provides annotations for web RestController
factory
Package factory provides hiboot factory interface Package factory provides InstantiateFactory and ConfigurableFactory interface
Package factory provides hiboot factory interface Package factory provides InstantiateFactory and ConfigurableFactory interface
factory/autoconfigure
Package autoconfigure implement ConfigurableFactory
Package autoconfigure implement ConfigurableFactory
factory/depends
Package depends provides dependency resolver for factory
Package depends provides dependency resolver for factory
factory/depends/bar
Package bar is the test package for package depends
Package bar is the test package for package depends
factory/depends/fake
Package fake is the test package for package depends
Package fake is the test package for package depends
factory/depends/foo
Package foo is the test package for package depends
Package foo is the test package for package depends
factory/instantiate
Package instantiate implement InstantiateFactory
Package instantiate implement InstantiateFactory
inject
Package inject implements dependency injection.
Package inject implements dependency injection.
log
Package log provides logging with level debug, info, warn, error, fatal.
Package log provides logging with level debug, info, warn, error, fatal.
model
Package model provides common request and response models.
Package model provides common request and response models.
starter
Package starter provides quick starters for hiboot cli/web application.
Package starter provides quick starters for hiboot cli/web application.
starter/actuator
Package actuator provide the health check endpoint for web application
Package actuator provide the health check endpoint for web application
starter/actuator/controller
Package controller provide the controller for health check
Package controller provide the controller for health check
starter/grpc
Package grpc provides the hiboot starter for injectable grpc client and server dependency
Package grpc provides the hiboot starter for injectable grpc client and server dependency
starter/jwt
Package jwt provides the hiboot starter for injectable jwt dependency
Package jwt provides the hiboot starter for injectable jwt dependency
starter/jwt/at
Package annotation provides annotations for jwt controller
Package annotation provides annotations for jwt controller
starter/locale
Package locale provides the hiboot starter for injectable locale (i18n) dependency
Package locale provides the hiboot starter for injectable locale (i18n) dependency
starter/logging
Package logging provides the hiboot starter for injectable logging dependency
Package logging provides the hiboot starter for injectable logging dependency
system
Package system provides system builder which response for properties dependency injection.
Package system provides system builder which response for properties dependency injection.
system/types
Package types provides all const types name
Package types provides all const types name
utils
Package utils provides useful utilities
Package utils provides useful utilities
utils/cmap
Package cmap provides concurrent map
Package cmap provides concurrent map
utils/copier
Package copier provides utility that copy element between structs
Package copier provides utility that copy element between structs
utils/crypto
Package crypto provides crypto encryption/decryption utilities
Package crypto provides crypto encryption/decryption utilities
utils/crypto/aes
Package aes provides aes encryption/decryption utilities
Package aes provides aes encryption/decryption utilities
utils/crypto/base64
Package base64 provides base64 encryption/decryption utilities
Package base64 provides base64 encryption/decryption utilities
utils/crypto/md5
Package md5 provides md5 encryption utilities
Package md5 provides md5 encryption utilities
utils/crypto/rsa
Package rsa provides rsa encryption/decryption utilities
Package rsa provides rsa encryption/decryption utilities
utils/gotest
Package gotest provides function to check whether is running in go test mode.
Package gotest provides function to check whether is running in go test mode.
utils/idgen
Package idgen provides unique id generation utilities that use twitter's snowflake algorithm
Package idgen provides unique id generation utilities that use twitter's snowflake algorithm
utils/io
Package io provides file or directory io utilities.
Package io provides file or directory io utilities.
utils/mapstruct
package mapstruct provides utilities that decode map and inject values into struct
package mapstruct provides utilities that decode map and inject values into struct
utils/reflector
Package reflector provides utilities for reflection
Package reflector provides utilities for reflection
utils/replacer
Package replacer provides utilities that replace the reference and environment variables with its value
Package replacer provides utilities that replace the reference and environment variables with its value
utils/sort
Package sort provides utility that sort slice by length
Package sort provides utility that sort slice by length
utils/str
Package str provides enhanced string utilities
Package str provides enhanced string utilities
utils/validator
Package validator provides data validation utilities
Package validator provides data validation utilities

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL