forcemvc3 0.1.0

VERSION! Build Status

Dart Force MVC #

LOGO!

Serverside MVC based implementation for Dart. Easy to setup and part of the dart force framework!

Introduction #

Dart ForceMVC is a dartlang web framework, with a lot of similarities to java spring mvc

First of all you need to setup a web server:

library x;
import 'package:wired2/wired2.dart';
import 'package:forcemvc2/forcemvc2.dart';

part 'controllers/x_controller.dart';

main() {
  WebApplication app = new WebApplication(startPage: "start.html");
  
  app.start(); 
}

And then of course we need to create our controller.

part of x;

@Controller
class XController {

  @RequestMapping(value: "/home", method: "GET")
  String home(Locale locale, Model model) {
    model.addAttribute("someprop", "value" );
    
    return "home";
  }
  
}

In the web folder of your application you can create a home.html file. That will be your view.

Walkthrough #

Use a Web Application Server with dart very easily, create controllers with annotations ... similar to java spring mvc.

First you will setup a new web application.

WebApplication app = new WebApplication(wsPath: wsPath, port: port, host: host, buildPath: buildPath);

Then you use the 'use' method to handle http requests.

app.use(url, (ForceRequest req, Model model) { /* logic */ }, method: "GET");

You can also use the annotation RequestMapping in a dart object

@RequestMapping(value: "/someurl", method: "GET")
void index(ForceRequest req, Model model)

You can also use the annotation @ModelAttribute to add an object to all the scopes in the methods. An @ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model, the argument should be instantiated first and then added to the model. Once present in the model, the argument's fields should be populated from all request parameters that have matching names.

@ModelAttribute("someValue")
String someName() {
	return mv.getValue();
}

Then you register that object on the WebApplication object.

app.register(someObjectWithRequestMappingAnnotations)

Or you can annotate a class with @Controller and then it will be registered automatically in the force WebApplication.

@Controller
class SomeObject {

}

Starting your web application #

You can do this as follow!

app.start();

It is also possible to start a web application with SSL possibilities.

app.startSecure();

ForceRequest #

ForceRequest is an extension for HttpRequest

forceRequest.postData().then((data) => print(data));

Interceptors #

You can define inteceptors as follow, the framework will pick up all the HandlerInterceptor classes or implementations.

class RandomInterceptor implements HandlerInterceptor {

  bool preHandle(ForceRequest req, Model model, Object handler) { return true; }
  void postHandle(ForceRequest req, Model model, Object handler) {}
  void afterCompletion(ForceRequest req, Model model, Object handler) {}
  
}

Path variables #

You can now use path variables in force mvc.

@RequestMapping(value: "/var/{var1}/other/{var2}/", method: "GET")
void pathvariable(ForceRequest req, Model model, String var1, String var2)

This is an alternative way how you can access path variables.

req.path_variables['var1']

You can also use the annotation @PathVariable("name") to match the pathvariable, like below:

  @RequestMapping(value: "/var/{var1}/", method: "GET")
  String multivariable(req, Model model, @PathVariable("var1") variable) {}

Redirect #

You can instead of returning a view name, performing a redirect as follow:

@RequestMapping(value: "/redirect/")
String redirect(req, Model model) {
	redirect++;
	return "redirect:/viewable/";
}

Asynchronous Controller #

In the controller you can have asynchronous methods to handle for example POST methods much easier.

On the ForceRequest object you have a method .async and his value is the return value that matters for the req.

When a method is asynchronous you must return req.asyncFuture.

This is an example how you can use it.

@RequestMapping(value: "/post/", method: "POST")
Future countMethod(req, Model model) {
     req.getPostParams().then((map) {
       model.addAttribute("email", map["email"]);
       
       req.async(null);
     });
     model.addAttribute("status", "ok");
     
     return req.asyncFuture;
}

Authentication #

You can now add the annotation @Authentication to a controller class. This will make it necessary to for a user to authenticate before accessing these resources.

An authentication in force is following a strategy. You can set a strategy by extending the class SecurityStrategy.

class SessionStrategy extends SecurityStrategy {
  
  bool checkAuthorization(HttpRequest req, {data: null}) {
    HttpSession session = req.session;
    return (session["user"]!=null);
  }   
  
  Uri getRedirectUri(HttpRequest req) {
    var referer = req.uri.toString();
    return Uri.parse("/login/?referer=$referer");
  }
} 

And then add this strategy to the web application.

app.strategy = new SessionStrategy();

Roles #

You can also define authorize roles. This can be done as follow.

@Controller
@PreAuthorizeRoles(const ["ADMIN"])
class AdminController {
		
}
ExceptionHandler #

This helps in defining methods that will be executed when an error or exception occured.

@ExceptionHandler()
String error_catch(req, Model model) {
	...
}

You can also specify a type, only when an error or exception happend of that Type, that method will be executed.

@ExceptionHandler(type: DoorLockedError)
String doorLockedError(req, Model model) {
	model.addAttribute("explanation", "This is a specific error!");
	return "error";  
}

Logging #

You can easily boostrap logging.

app.setupConsoleLog();

Wired #

Wired is a dependency injection package. You can use @Autowired and @bean and more in forcemvc find info here

LocaleResolver #

In ForceMVC you have a locale resolver to handle locale. The implementation that is been used by default is the AcceptHeaderLocale Resolver, this resolver looks at the request header accept-language.

You can choose for a fixed locale resolver implementation or a cookie locale resolver or just implement your own handling if need.

View / Templating #

In forcemvc you can define view templates. ForceMvc will look into the viewfolder and in the client 'build' folder for a .html file with the viewname that you provide the system in the controller.

@RequestMapping(value: "/hello/")
String redirect(req, Model model) {
	// do something
	model.addAttribute("text", "greetings");
	return "hello";
}

So in the example about we are returning a string with the value 'hello'. So the system will search in the view & build folder for a hello.html file.

The default implementation in ForceMVC for templating is mustache.

In the html file {{text}} will be replaced by greetings.

More info about creating your own viewrender implementation here

Development trick #

Following the next steps will make it easier for you to develop, this allows you to adapt clientside files and immidiatly see results with doing a pub build.

pub serve web --hostname 0.0.0.0 --port 7777 &&
export DART_PUB_SERVE="http://localhost:7777" &&
pub run bin/server.dart

GAE #

You can now easily run your Force apps on a Google App Engine infrastructure by the following code! The rest is the same as a normal dart force app.

WebApplication app = new WebApplication();

runAppEngine(app.requestHandler).then((_) { // Server running. and you can do all the stuff you want! });

You don't need to start WebApplication anymore, the start of the server will be done by AppEngine!

More info about GAE overall

Rest API's #

If you want to learn more about how to build Rest api's with ForceMVC go here

Example #

You can find a simple example with a page counter implementation here - live demo

Or visit Github issue mover here

Youtube #

You can watch a simple youtube video to get you started, have an idea between the transformation of java spring mvc and force mvc here

TODO #

  • get more annotations and options for sending the response back
  • writing tests

Notes to Contributors #

Fork Dart Force MVC #

If you'd like to contribute back to the core, you can fork this repository and send us a pull request, when it is ready.

If you are new to Git or GitHub, please read this guide first.

Dart Force #

Realtime web framework for dart that uses force MVC & wired source code

Twitter #

Follow us on twitter https://twitter.com/usethedartforce

Google+ #

Follow us on google+

Join our discussion group #

Google group

example/main.dart

library example;

import "package:forcemvc3/forcemvc2.dart";
import 'package:example/controllers.dart';

main() {
    print ("Opening localhost:8080 ...");
    WebApplication app = new WebApplication(views: 'views/');
    app.start();
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  forcemvc3: ^0.1.0

2. Install it

You can install packages from the command line:

with pub:


$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:forcemvc3/annotations/helpers.dart';
import 'package:forcemvc3/annotations/metadata.dart';
import 'package:forcemvc3/converters/abstract_message_converter.dart';
import 'package:forcemvc3/converters/csv_message_converter.dart';
import 'package:forcemvc3/converters/http_message_converter.dart';
import 'package:forcemvc3/converters/json_http_message_converter.dart';
import 'package:forcemvc3/converters/text_http_message_converter.dart';
import 'package:forcemvc3/error/handler_exception_resolver.dart';
import 'package:forcemvc3/error/simple_exception_resolver.dart';
import 'package:forcemvc3/forcemvc2.dart';
import 'package:forcemvc3/http/http_headers_wrapper.dart';
import 'package:forcemvc3/http/http_input_message.dart';
import 'package:forcemvc3/http/http_message.dart';
import 'package:forcemvc3/http/http_message_regulator.dart';
import 'package:forcemvc3/http/http_method.dart';
import 'package:forcemvc3/http/http_output_message.dart';
import 'package:forcemvc3/http/invalid_mime_type_error.dart';
import 'package:forcemvc3/http/media_type.dart';
import 'package:forcemvc3/http/mime_type.dart';
import 'package:forcemvc3/i18n/accept_header_locale_resolver.dart';
import 'package:forcemvc3/i18n/cookie_locale_resolver.dart';
import 'package:forcemvc3/i18n/default_locale_resolver.dart';
import 'package:forcemvc3/i18n/fixed_locale_resolver.dart';
import 'package:forcemvc3/i18n/locale_resolver.dart';
import 'package:forcemvc3/manager/cookie_holder_manager.dart';
import 'package:forcemvc3/render/mustache_render.dart';
import 'package:forcemvc3/render/view_render.dart';
import 'package:forcemvc3/security/no_security_strategy.dart';
import 'package:forcemvc3/security/security_context_holder.dart';
import 'package:forcemvc3/security/security_strategy.dart';
import 'package:forcemvc3/server/force_request.dart';
import 'package:forcemvc3/server/handler_interceptor.dart';
import 'package:forcemvc3/server/http_request_streamer.dart';
import 'package:forcemvc3/server/interceptors_collection.dart';
import 'package:forcemvc3/server/model.dart';
import 'package:forcemvc3/server/mvc_typedefs.dart';
import 'package:forcemvc3/server/path_analyzer.dart';
import 'package:forcemvc3/server/registry.dart';
import 'package:forcemvc3/server/request_method.dart';
import 'package:forcemvc3/server/response_hooks.dart';
import 'package:forcemvc3/server/serving_assistent.dart';
import 'package:forcemvc3/server/serving_files.dart';
import 'package:forcemvc3/server/simple_web_server.dart';
import 'package:forcemvc3/server/web_application.dart';
import 'package:forcemvc3/test.dart';
import 'package:forcemvc3/utils/mime_type_utils.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
9
Health:
Code health derived from static analysis. [more]
0
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
60
Overall:
Weighted score of the above. [more]
16
Learn more about scoring.

We analyzed this package on Aug 21, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19

Platforms

Detected platforms:

Error(s) prevent platform classification:

Error(s) in lib/test.dart: Target of URI doesn't exist: 'package:forcemvc2/force_mvc2.dart'.

Health issues and suggestions

Fix lib/server/registry.dart. (-99.99 points)

Analysis of lib/server/registry.dart failed with 32 errors, 5 hints, including:

line 27 col 56: Undefined class 'Scanner'.

line 30 col 61: Undefined class 'Scanner'.

line 33 col 57: Undefined class 'Scanner'.

line 35 col 10: The name 'MetaDataValue' isn't a type so it can't be used as a type argument.

line 35 col 66: The name 'MetaDataValue' isn't a type so it can't be used as a type argument.

Fix lib/test.dart. (-89.99 points)

Analysis of lib/test.dart failed with 8 errors, including:

line 4 col 8: Target of URI doesn't exist: 'package:forcemvc2/force_mvc2.dart'.

line 11 col 35: Classes and mixins can only implement classes.

line 11 col 35: Undefined class 'ForceRequest'.

line 20 col 4: Undefined class 'Intl'.

line 49 col 4: Undefined class 'HttpHeadersWrapper'.

Fix lib/annotations/helpers.dart. (-68.36 points)

Analysis of lib/annotations/helpers.dart failed with 4 errors:

line 5 col 5: Undefined class 'AnnotationScanner'.

line 6 col 13: Undefined class 'AnnotationScanner'.

line 11 col 5: Undefined class 'AnnotationScanner'.

line 12 col 13: Undefined class 'AnnotationScanner'.

Fix additional 37 files with analysis or formatting issues. (-77.83 points)

Additional issues in the following files:

  • lib/http/media_type.dart (36 hints)
  • lib/annotations/metadata.dart (16 hints)
  • lib/http/http_headers_wrapper.dart (14 hints)
  • lib/converters/abstract_message_converter.dart (12 hints)
  • lib/http/mime_type.dart (12 hints)
  • lib/server/simple_web_server.dart (12 hints)
  • lib/server/web_application.dart (8 hints)
  • lib/i18n/cookie_locale_resolver.dart (5 hints)
  • lib/manager/cookie_holder_manager.dart (5 hints)
  • lib/server/serving_assistent.dart (5 hints)
  • lib/utils/mime_type_utils.dart (4 hints)
  • lib/error/handler_exception_resolver.dart (3 hints)
  • lib/error/simple_exception_resolver.dart (3 hints)
  • lib/http/http_input_message.dart (3 hints)
  • lib/http/http_output_message.dart (3 hints)
  • lib/i18n/locale_resolver.dart (3 hints)
  • lib/http/http_method.dart (2 hints)
  • lib/i18n/accept_header_locale_resolver.dart (2 hints)
  • lib/i18n/default_locale_resolver.dart (2 hints)
  • lib/i18n/fixed_locale_resolver.dart (2 hints)
  • lib/security/security_context_holder.dart (2 hints)
  • lib/server/force_request.dart (2 hints)
  • lib/server/serving_files.dart (2 hints)
  • lib/forcemvc2.dart (1 hint)
  • lib/http/http_message.dart (1 hint)
  • lib/server/model.dart (1 hint)
  • lib/converters/json_http_message_converter.dart (Run dartfmt to format lib/converters/json_http_message_converter.dart.)
  • lib/converters/text_http_message_converter.dart (Run dartfmt to format lib/converters/text_http_message_converter.dart.)
  • lib/security/no_security_strategy.dart (Run dartfmt to format lib/security/no_security_strategy.dart.)
  • lib/security/security_strategy.dart (Run dartfmt to format lib/security/security_strategy.dart.)
  • lib/server/handler_interceptor.dart (Run dartfmt to format lib/server/handler_interceptor.dart.)
  • lib/server/http_request_streamer.dart (Run dartfmt to format lib/server/http_request_streamer.dart.)
  • lib/server/interceptors_collection.dart (Run dartfmt to format lib/server/interceptors_collection.dart.)
  • lib/server/mvc_typedefs.dart (Run dartfmt to format lib/server/mvc_typedefs.dart.)
  • lib/server/path_analyzer.dart (Run dartfmt to format lib/server/path_analyzer.dart.)
  • lib/server/request_method.dart (Run dartfmt to format lib/server/request_method.dart.)
  • lib/server/response_hooks.dart (Run dartfmt to format lib/server/response_hooks.dart.)

Maintenance issues and suggestions

Fix platform conflicts. (-20 points)

Error(s) prevent platform classification:

Error(s) in lib/test.dart: Target of URI doesn't exist: 'package:forcemvc2/force_mvc2.dart'.

Provide a file named CHANGELOG.md. (-20 points)

Changelog entries help developers follow the progress of your package. See the example generated by stagehand.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
http_server >=0.9.0 <0.10.0 0.9.8+3
intl ^0.15.8 0.15.8
locales ^0.1.0 0.1.0
logging >=0.11.0 <0.12.0 0.11.3+2
mockito ^4.0.0 4.1.0
mustache4dart2 ^0.1.0 0.1.0
path ^1.6.2 1.6.4
route2 ^0.1.1 0.1.1
wired2 ^0.1.0 0.1.0
Transitive dependencies
async 2.3.0
boolean_selector 1.0.5
charcode 1.1.2
collection 1.14.12
matcher 0.12.5
meta 1.1.7
mime 0.9.6+3
mirrorme2 0.1.0
pedantic 1.8.0+1
source_span 1.5.5
stack_trace 1.9.3
stream_channel 2.0.0
string_scanner 1.0.5
term_glyph 1.1.0
test_api 0.2.7
yaml 2.1.16
Dev dependencies
test ^1.0.0