Brutos Framework

The Brutos Application Framework is MVC controller written in Java. Designed to reduce the complexity of web development, with configurable mapping, view resolution as well as support for uploading and downloading files. Can be configured using XML, annotations and CoC.

Brutos Framework
Developer(s)UoU Technology
Initial releaseMay 17, 2009
Stable release
2.0-rc3 / 14 August 2018 (2018-08-14)
Written inJava
Operating systemCross-platform
PlatformJava Virtual Machine
TypeApplication framework
LicenseApache License 2.0
Websitewww.brutosframework.com.br

The framework follows the below principles:

  • flexibility;
  • loose coupling and
  • productivity.

Release bundle downloads

The Brutos team provides release bundles hosted on the SourceForge File Release System, in ZIP.

Each release bundle contains JARs, documentation, source code, and other information.

You can download releases of Brutos, from the list at sourceforge.net/projects/brutos/files/brutos/.

Maven repository artifacts

They are produced a number of artifacts. All under the org.brandao groupId.

  • brutos-core: The main artifact, it is needed to build applications using the Brutos native APIs.
  • brutos-annotation: Optional artifact that allows building applications using annotations. This artifact depends on the brutos-core.
  • brutos-web: Optional artifact that allows building web applications. This artifact depends on the brutos-core.

The official repository is www.brutosframework.com.br/maven/2.

How to configure?

Register the listener in web.xml

<listener>
    <listener-class>org.brandao.brutos.web.ContextLoaderListener</listener-class>
</listener>

Register the filter in web.xml

<filter>
        <filter-name>Brutos Framework Filter</filter-name>
        <filter-class>org.brandao.brutos.web.http.BrutosRequestFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Brutos Framework Filter</filter-name>
        <url-pattern>*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>
</filter>

Attention: If you are using a container that supports the Servlet 3.0 specification, the registration of ContextLoadListener and DispatcherServlet or BrutosRequestFilter are not necessary. They will be automatically registered.

Register the artifacts in pom.xml

...
<dependencies>
  <dependency>
      <groupId>org.brandao</groupId>
      <artifactId>brutos-core</artifactId>
      <version>2.0-rc3</version>
  </dependency>
  <dependency>
     <groupId>org.brandao</groupId>
     <artifactId>brutos-web</artifactId>
     <version>2.0-rc3</version>
  </dependency>
  <dependency>
     <groupId>org.brandao</groupId>
     <artifactId>brutos-annotation</artifactId>
     <version>2.0-rc3</version>
  </dependency>
</dependencies>
...

Create the file brutos-config.xml in /WEB-INF.

<?xml version="1.0" encoding="UTF-8"?>
<controllers  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
              xmlns='http://www.brutosframework.com.br/schema/controllers'
              xmlns:context='http://www.brutosframework.com.br/schema/context'
              xsi:schemaLocation='
   http://www.brutosframework.com.br/schema/controllers 
http://www.brutosframework.com.br/schema/controllers/brutos-controllers-1.1.xsd
   http://www.brutosframework.com.br/schema/context 
http://www.brutosframework.com.br/schema/context/brutos-context-1.1.xsd
   http://www.brutosframework.com.br/schema/web http://www.brutosframework.com.br/schema/web/brutos-web-1.1.xsd'>

</controllers>


Examples

Web Service

Methods:

URI HTTP method Method
/users GET UserWebService.list()
/users POST UserWebService.add(User)
/users/{user.id} PUT UserWebService.update(User)
/users/{id} DELETE UserWebService.delete(Integer)

Controller:

@Controller
@AcceptRequestType(MediaTypes.APPLICATION_JSON)
@ResponseType(MediaTypes.APPLICATION_JSON)
@ResponseError(code=HttpStatus.NOT_FOUND, target=NotFoundException.class)
public class UserWebService {

    @Inject
    private UserService userService;

    @Action("/users")
    public List<User> list() {
        return this.userService.list();
    }

    @Action("/users")
    @RequestMethod(RequestMethodTypes.POST)
    @ResponseStatus(HttpStatus.CREATED)
    public void add(User user) {
        this.userService.save(user);
    }

    @Action("/users/{user.id}")
    @RequestMethod(RequestMethodTypes.PUT)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void update(User user) throws NotFoundException {
        if (user == null) {
            throw new NotFoundException();
        }
        this.userService.update(user);
    }

    @Action("/users/{id}")
    @RequestMethod(RequestMethodTypes.DELETE)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(Integer id) throws NotFoundException {

        User e = this.userService.remove(id);

        if (e == null) {
            throw new NotFoundException();
        }
    }
}

Exception Handler

Controller Level

@ResponseError(value=HttpStatus.CONFLICT, 
               reason="Data integrity violation", target=DataIntegrityViolationException.class)
public class ExampleController {
  
   @Action("/action")
   public void action() throws DataIntegrityViolationException{
       ...
   }

}

Action Level

public class ExampleController{
  
   @Action("/action")
   @ResponseError(value=HttpStatus.CONFLICT, 
            reason="Data integrity violation", target=DataIntegrityViolationException.class)
   public void action() throws DataIntegrityViolationException{
       ...
   }

}

Method

public class ExampleController{
  
   @Action("/action")
   public void action() throws MyBadDataException {
       ...
   }

   @ResponseError(MyBadDataException.class)
   public WebActionResult myBadDataException(Throwable exception, WebActionResult result) {
       result
           .setResponseStatus(HttpStatus.BAD_REQUEST)
           .setView("errorView")
           .add("exception", exception);
       return result;
   }

}

Build Action Result

Controller

public class IndexController {
  
   public WebResultAction action1Action(WebResultAction result) {
      result.addHeader("Content-Type", "text/html; charset=utf-8")
            .setContentType(String.class)
            .setContent("<html><body>test</body></html>");
      return result;
   }

    public WebResultAction action2Action (WebResultAction result) {
        result.addHeader("Content-Type", "text/html; charset=utf-8")
            .setView("myView")
            .add("value1", BigDecimal.ONE);
        return result;
    }

}

Polymorphic Mapping

Methods:

URI Http Method method
/add POST ExampleController.add(Fruit)

Controller

public class ExampleController{

    @Action("/add")
    @RequestMethod(RequestMethodTypes.POST)
    public void add(
        @Any(
            metaBean=@Basic(bean="type")
            metaValues={
                @MetaValue(name="apple", target=Apple.class),
                @MetaValue(name="orange", target=Orange.class)
            }
        )
        Fruit fruit) {
            ...
    }
}

Beans

public abstract class Fruit {
    ...
}
public class Apple extends Fruit {
   ...
}
public class Orange extends Fruit {
   ...
}

Abstract action

URI mapping:

Controller/Action URI View
ExampleController /path /WEB-INF/views/view.jsp
ExampleController /path/ /WEB-INF/views/view.jsp

Controller

@Controller("/path", defaultAction="/")
@Action(value="/", view=@View("view"))
public class ExampleController{

}

Using URI template

URI mapping:

Controller/Action URI View
ExampleController /path/{user} /WEB-INF/views/index/index.jsp
ExampleController.getUser(String) /path/{userId}/showUser /WEB-INF/views/index/getuser/index.jsp

Controller

@Controller("/path/{userId}")
public class ExampleController{

    @Action("/showUser")
    public User getUser(String userId) {
        ...
    }

}

File upload and download

@Controller("/files")
public class ExampleController {
  
    @Action("/")
    @RequestMethod(RequestMethodTypes.POST)
    public void uploadAction(File file) {
         //the parameter file is a temporary file
         ...
    }

    @Action("/{fileName:.*}")
    @RequestMethod(RequestMethodTypes.GET)
    public File downloadAction(String fileName) {
        File file = ...;
        return file;
    }

}

Form and Session

public class PersonController{

    @Action("/save")
    public void saveAction(
        @Basic(scope="session") User loggerdUser, @Basic(bean="person") Person person) {
        ...
    }

}
gollark: In what way?
gollark: Read that as `gopher bind weird R in a gear or something post-increment`.
gollark: Haskell code example: https://a.thumbs.redditmedia.com/R8avhAOsAdBYe-wfSpzXc3YrSbxKuiQl3jp8g4UHmU4.png
gollark: Yes, but I want to say WAT.
gollark: WAT IS WAT?

See also

Book

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.