Do we have any in-built transaction management when using Spring Data REST or it has to be manually maintained/handled from the calling application/service.
Say, I have two calls(first POST(for creation) and PATCH(update/insert association resource using uri-lists)) which I want to be considered as a transaction.
Thanks
Bharath
In spring data rest every repository action runs within a transaction. Even the event handlers are not running inside the repository transaction. And of course different actions on the REST API do run in separate transactions.
Here is an interesting question on this topic:
Handle spring-data-rest application events within the transaction
If you want to have creation and association in one transaction then the only way to achieve this with your current entity mapping is to create a custom controller that does just that.
An alternative mapping strategy would be to treat the associated entity as a containment - so the associated entity does not have an exported repository and is maintained within the parent.
The who point of REST is to have isolated units of work. If you are wanting to keep transactions open across calls it's probably a sign you need to adjust your RESTful strategy.
Have a look at: Transaction strategy for microservices
I found this question when researching the transaction behavior of data-rest.
I needed control over the transaction behavior of the default controllers, especially during serialization of relationships, so i could mark transactions as read-only and route them to read-replicas of our database.
By default every call to a repository has its own transaction and database access during events or resource-assembly is managed by hibernate directly, outside of these transactions. There is no intended way for users to control transactions.
Spring does however provide methods to do that using aop-interceptors. These interceptors use a property source do decide weather or not a method requires a transaction. Springs own Transactional-Annotation is nothing more than one of these property-sources.
The following Configuration creates an advisor for the default rest-controllers that creates customized transactions for some Methods:
#Configuration
#ConditionalOnClass(name = {
"org.springframework.data.rest.webmvc.RepositoryEntityController",
"org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController",
"org.springframework.data.rest.webmvc.RepositorySearchController"
})
public class RepositoryRestControllerTransactionConfiguration {
/**
* A custom Transaction Advisor that starts customized transactions based on what data-rest controller method is called
*
* #param transactionManager
* #return
*/
#Bean
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionManager transactionManager) {
//Specify transaction management methods and attribute values required for transaction control
MethodMapTransactionAttributeSource source = new MethodMapTransactionAttributeSource();
Map<String, TransactionAttribute> methodMap = new HashMap<>();
// methods are identified by their FQDN, simple placeholders using * are possible
// methods that should only require reads
methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.get*", createTransactionRule(true));
methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.headForItemResource", createTransactionRule(true));
methodMap.put("org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.follow*", createTransactionRule(true));
methodMap.put("org.springframework.data.rest.webmvc.RepositorySearchController.execute*", createTransactionRule(true));
// methods that will require write
methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.put*", createTransactionRule(false));
methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.patch*", createTransactionRule(false));
methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.delete*", createTransactionRule(false));
methodMap.put("org.springframework.data.rest.webmvc.RepositoryEntityController.post*", createTransactionRule(false));
methodMap.put("org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.delete*", createTransactionRule(false));
methodMap.put("org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController.create*", createTransactionRule(false));
source.setMethodMap(methodMap);
source.afterPropertiesSet();
// Generate an AOP Advisor that controls transactions
// Advice for transaction control (TransactionInteceptor)
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(source);
advisor.setAdvice(new TransactionInterceptor(transactionManager, source));
return advisor;
}
private RuleBasedTransactionAttribute createTransactionRule(boolean readOnly) {
RuleBasedTransactionAttribute rule = new RuleBasedTransactionAttribute();
rule.setReadOnly(readOnly);
return rule;
}
}
Related
I am having trouble finding information about this issue I am running into. I am interested in implementing row level security on my Postgres db and I am looking for a way to be able to set postgres session variables automatically through some form of an interceptor. Now, I know that with hibernate you are able to do row-level-security using #Filter and #FilterDef, however I would like to additionally set policies on my DB.
A very simple way of doing this would be to execute the SQL statement SET variable=value prior to every query, though I have not been able to find any information on this.
This is being used on a spring-boot application and every request is expected to will have access to a request-specific value of the variable.
Since your application uses spring, you could try accomplishing this in one of a few ways:
Spring AOP
In this approach, you write an advice that you ask spring to apply to specific methods. If your methods use the #Transactional annotation, you could have the advice be applied to those immediately after the transaction has started.
Extended TransactionManager Implementation
Lets assume your transaction is using JpaTransactionManager.
public class SecurityPolicyInjectingJpaTransactionManager extends JpaTransactionManager {
#Autowired
private EntityManager entityManager;
// constructors
#Override
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
super.prepareSynchronization(status, definition);
if (status.isNewTransaction()) {
// Use entityManager to execute your database policy param/values
// I would suggest you also register an after-completion callback synchronization
// This after-completion would clear all the policy param/values
// regardless of whether the transaction succeeded or failed
// since this happens just before it gets returned to the connection pool
}
}
}
Now simply configure your JPA environment to use your custom JpaTransactionManager class.
There are likely others, but these are the two that come to mind that I've explored.
I am trying to create a transaction comprising two REST web services, whose data source point to the same data base. The first service, named 1, invokes another web service named 2 using Spring RestTemplate.
To implement the transaction I am using a JNDI connection pool, the MySql JDBC driver (version 5.1.35), JTA, XA, Spring and the GlassFish 5 AppServer.
Now, I have downloaded the maven dependencies in the Spring project, defined a configuration class using JtaTransactionManager, and configured the datasource and JTA properties in an application.yml file, like in the following code:
Configuration class:
#Configuration
#EnableTransactionManagement
public class Transacciones {
#Bean
public PlatformTransactionManager platformTransactionManager(){
return new JtaTransactionManager();
}
}
application.yml file
spring:
datasource:
jndi-name: jdbc/Prueba
driver-class-name: com.mysql.jdbc.Driver
jta:
enabled: true
I configured the JNDI datasource in GlassFish 5 defining a "JDBC Resource" named jdbc/Prueba in the "Connections pools" page using a javax.sql.XADataSourcedatasource named pruebaXA:
In the control layer of the web service 1, the method calls the service 2 using the RestTemplate class of Spring Framework:
Service 1 code:
#RestController
#RequestMapping("/servicio")
#EnableTransactionManagement
public class a {
#Autowired
private JdbcTemplate objJdbcTemplate;
#Transactional(rollbackFor = RuntimeException.class)
#GetMapping("/1")
public Integer getValor(){
try{
int numero;
int n=50;
RestTemplate restTemplate = new RestTemplate();
Integer intRes1;
Integer intRes2;
numero = (int) (Math.random() * n) + 1;
intRes2 = restTemplate.postForObject("http://localhost:8080/servicio2-1.0-SNAPSHOT/servicio/2",numero,Integer.class);
intRes1=objJdbcTemplate.update("INSERT INTO A VALUES(" +numero + ")");
return numero;
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
Service 2 code:
#RestController
#RequestMapping("/servicio")
public class a {
#Autowired
private JdbcTemplate objJdbcTemplate;
#Transactional(rollbackFor = RuntimeException.class)
#PostMapping("/2")
public Integer getValor(#RequestBody Integer intNum){
try{
Integer intRes;
intRes=objJdbcTemplate.update("INSERT INTO B VALUES(" + intNum + ")");
return intRes;
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
If the two services work without errors, there is not problem. However, when the service 1 falls, the service 2 does not know about the error and does not do the rollback.
I do not know if I need to configure another feature/option in the GlassFish 5, or in the Spring program.
I have read that in Spring only needs a JtaTransactionManager bean and the framework performs all the work related to configure and use JTA-transactions.Spring and JTA
JTA
Now, if you still need to use JTA, at least the choice is yours to
make. There are two common scenarios: using JTA in a heavyweight
application server (which has all the nasty disadvantages of being
tied to a JavaEE server), or using a standalone JTA implementation.
Spring provides support for JTA-based global transaction
implementations through a PlatformTransactionManager implementation
called JtaTransactionManager. If you use it on a JavaEE application
server, it will automatically find the correct
javax.transaction.UserTransaction reference from JNDI. Additionally,
it will attempt to find the container-specific
javax.transaction.TransactionManager reference in 9 different
application servers for more advanced use cases like transaction
suspension. Behind the scenes, Spring loads different
JtaTransactionManager subclasses to take advantage of specific, extra
features in different servers when available, for example:
WebLogicJtaTransactionManager, WebSphereUowTransactionManager and
OC4JJtaTransactionManager.
So, if you’re inside a Java EE application server, and can’t escape,
but want to use Spring’s JTA support, then chances are good that you
can use the following namespace configuration support to factory a
JtaTransactionManager correctly (and automatically):
Alternatively, you can register a
JtaTransactionManager bean instance as appropriate, with no
constructor arguments, like this:
#Bean public PlatformTransactionManager platformTransactionManager(){
return new JtaTransactionManager(); } Either way, the end result in a JavaEE application server is that you can now use JTA to manage
your transactions in a unified manner thanks to Spring.
Thanks for your help and time.
How to do Distributed Transactions XA ?
If you invoke first a REST or web service and then another one, both operations will not be part of a transaction. To form a transaction, these operations must "start" a transaction or be "joined" to an existing one. To execute that transaction, your program must interact with a transaction monitor (TM) such as the proposed by AT&T/Oracle Tuxedo (released in the 80s), the X/Open XA standard (released in the 90s) and the JTA-based systems.
Note how the TM-based transaction works:
A transaction using XA datasources is basically a program that invokes database operations on two different databases. The same program (e.g. invoking methods in one or more bean) starts the transaction, performs some operations on a database and performs other operations on another database. If one of the operation fails, the other operations are not performed or are rollbacked.
A transaction using XA datasources and JTA-enabled components is basically a program that combines operations on one or more databases with other transaction-enabled operations. For instance, you can combine operations on a database with operations on a content repository or a network-based file system. You can define transactions that, when a database operation fails, does not perform or rollbacks operations on the file system. Non-transactional applications such as COBOL-based programs can be integrated in a transaction by defining operations and compensations in the transaction monitor.
A transaction integrating web-services requires an special handling. For instance, there is a proposal for webservice transactions such as the WS-Transaction and WS-Coordination specification. There is a coordinator that works like the transaction monitor. The software must invoke the coordinator to start the transaction. Each participant in the transaction reports if each operation is successful or failed. The coordinator invokes the other operations or invokes the compensations according to the results.
Nowadays, there are some proposals for software architecture that do not rely on TM-based transactions. Designs based on CQRS and Event Sourcing implement transactions using the Sagas design pattern. If you are interested on defining a transaction-like operation that invokes two REST services, you may consider to avoid the XA/JTA and program a Sagas.
How to do Distributed Transactions XA in Spring and GlassFish 5?
You may check many tutorials in the Internet. For instance,
a tutorial that shows you three use cases: one updating two databases, one combining database operations and outgoing JMS-messages, and another one combining incoming JMS messages and database operations.
a video describing how to manage distributed transactions in Spring with JTA
and the documentation from the Spring Framework.
If the two services work without errors, there is not problem. However, when the service 1 falls, the service 2 does not know about the error and does not do the rollback.
That is the correct behavior. When you invoke a REST/webservice, the operations performed by that REST/webservice do not join to the transaction. If the invoking service fails, the invoked service will not notice it and will not rollback their operations in the database.
I do not know if I need to configure another feature/option in GlassFish 5, or in the Spring program.
No. You only have to configure the XA-datasources. Spring will use your configuration class and annotations to join automatically into a transaction the operations performed by your application on these datasources. For instance, if you have a bean that invokes multiple methods that performs operations on one or more XA-datasources, these operations will join into a transaction.
However, when you invoke a method in REST/webservice in another application, the database operations performed by that REST/webservice will not join to the transaction.
rest web services (http based) are non-transactional by their nature (they are http based). you have made each method/operation transactional, but they do not share any state between the resources (rest operations). generally - you can have XA transactions over database or mesaging, not over http calls.
intRes2 = restTemplate.postForObject("http://localhost:8080/servicio2-1.0-
SNAPSHOT/servicio/2",numero,Integer.class);
Calling a remote web service is without any transaction context. If you need to maintains transaction between services, call the secord service as EJB (or as an injected managed bean)
Basically: using http-based rest services - forget any transactions between them. The protocol (HTTP) is not built for that.
The only thing I've seen transactional is SOAP with WS-RM extension (SOAP with reliable messaging)., however it is not very easy to setup (read: it can be nightmare to make it work when you don't know what are you doing) and not all WS frameworks support it.
When you really need reliable delivery between web services, there's a way. what is comonly used to achieve assured delivery is messaging with idempotent services (https://en.m.wikipedia.org/wiki/Idempotence) with store-and-forward pattern. In simple terms - service 1 stores a JMS message to a queue and there's a processor (MDB) which calls service 2. (yes, calling a remote web service it may happen that the service 2 will receive a message multiple times. Indempotency is a way how to deal with it.)
Transactions across REST services are supported by http://www.atomikos.com
Cheers
I'm developing an import module to load in a bulk way from an excel file. I'm using spring to manage the transactional context and spring-data-jpa like DAO, to read a excel file I'm using POI.
#Service
public class ImportService{
#Autowired
UserRepository userRepository;
#Autowired
UserDetailRepository userDetailRepository;
#Autowired
AddressRepository addressRepository;
#Transactional(propagation = Propagation.REQUIRES_NEW)
public Map<String,StringBuffer> import(byte[] bytesUploaded) {
wb = new XSSFWorkbook(new ByteArrayInputStream(bytesUploaded));
XSSFSheet mySheet = (XSSFSheet) wb.getSheetAt((short)0);
for(Row row: mySheet){
if(row.getRowNum() >= 2 ){
readRowFromExcel(row);
}
}
}
#Transactional(propagation = Propagation.NESTED,rollbackFor=Exception.class)
private void readRowFromExcel(Row row) {
try{
User user = readUserFromFile(row);
UserDetail = readUserDetailFromFile(row,user);
Address address = readAddressFromFile(row,user);
//A few check to verify the corretly load of the entities
userDetailRepository.save(userDetail);
addressRepository.save(address);
userRepository.save(user);
}
catch (Exception e){
//Do something
}
}
}
I would want that if an exception occurred during read or the save of the row nothing become persistent, however an internal exception mustn't cause rollback the outer transaction.
How can I manage this kind of situation?
Am I facing the problem correctly?
Can you give me some suggestion about this (I'm new of spring)?
Thanks
A good start is the Transaction management section of the Spring framework reference documentation
There are a few things in your sample code that needs improvements:
Declarative transaction management
See section 11.5.1
The most important concepts to grasp with regard to the Spring Framework’s
declarative transaction support are that this support is enabled via AOP
proxies, and that the transactional advice is driven by metadata (currently
XML- or annotation-based). The combination of AOP with transactional metadata
yields an AOP proxy that uses a TransactionInterceptor in conjunction with
an appropriate PlatformTransactionManager implementation to drive transactions
around method invocations.
What that means typically is that calling your private method will not honour the transaction demarcation as you expect. Calling other methods of your service internally won't work either by default as it does not go through the proxy. In your case, Using #Transactional provides additional useful references.
The #Transactional on readRowFromExcel seems useless as you have the guarantee that a fresh transaction will be created before calling import.
Exception handling
In order for the AOP proxy to manage an exception thrown during a transactional method, you have to actually make sure the exception is thrown outside the method boundary so that the proxy can see it. In the case of your example, the do something part should make sure to throw the appropriate exception. If you want fine-grained management of the exception, you should probably define another exception type than Exception.
Wrapping up
If you want to read your excel file and save the content to your store using Spring data, you should probably have a single public annotated method whose purpose is to read an item and store it using Spring data. This would need some refactoring of your API. If the excel sheet is fairly large, you should also consider Spring Batch to process it.
What would be the purpose of the outer transaction here? You should also consider failure scenario such as when one particular row cannot be read (or written to the store). Are you leaving the file half-processed or are you flagging this error somewhere?
Environment: Spring 3, Custom Transaction Management, JDBC Transactions
I just read the Spring docs on using the transaction template to handle transaction management. It seemed overly complex so I want to ask:
Most of my transactions are JDBC related, meaning I just declare an #Transactional on my service. But now I am making a REST service call to another site which needs to rollback if any of the following JDBC operations fail, I'll provide the rollback code in this case.
As I progress in my method, in my transaction - I want to save a reference to the REST service call (needed to roll back that action), and upon exception I just want a method myCustomRollback() called which can access the previously stored object.
Why not just provide a map in the transactionTemplate for storing stuff and define a custom rollback method on the #Transactional annotation?
This is the way I think about it, I'm not following the way Spring thinks about this. Can someone help me bridge the gap between what I want and how I accomplish it most efficiently in Spring? I only need to do this for a few special case operations.
To anyone still reading this:
I solved a similar problem with spring events - as suggested by Den Roman in option 3.
Here's the basic idea (scenario is fictional):
Whenever I perform external operations that need to be rolled back together with the transaction, I publish an event inside my #Transactional method using support from spring (org.springframework.context.ApplicationEventPublisher):
#Transactional
public String placeOrder(Order order) {
String orderId = orderServiceGateway.createOrder(order);
applicationEventPublisher.publishEvent(new OrderCreatedEvent(orderId));
workflowService.startWorkflow(orderId);
return orderId;
}
The event itself can be any object - I created a POJO with details about the remote entity to be deleted.
Then I registered a special event listener that is bound to a transaction phase - in my case to the rollback:
#TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void rollBackOrder(OrderCreatedEvent orderCreatedEvent) {
String orderId = orderCreatedEvent.getOrderId();
orderServiceGateway.deleteOrder(orderId);
}
Of course, it's recommended to catch & log the exception from rollback operation, not to lose the original exception from the placeOrder() method.
By default these events are synchronous, but they can be made async by additional configuration.
Here's a very good article on this mechanism, including detailed configuration and pitfalls: Transaction Synchronization and Spring Application Events (DZone)
While I don't like the solution 100% because it clutters the business logic with event publishing stuff and binds to spring, it definitely does what I expect it to do and makes it possible to pass context from the transactional method to the rollback method - which is not available through a traditional try/catch block outside of the transactional method (unless you put your context in the exception itself, which is not very nice).
I've re-read your question a few times and am not sure I understand your question completely. I assume your executing someCode and if that fails you would like to execute myCustomRollback which has some information about someCode. So I'll try to provide a Generic answer.
If you want spring to rollback some code. It will only rollback that which is rollBackAble, like jdbc transactions. Assume you have a method which performs 2 calls.
#Transactional
public void doStuff(SomeEntity entity, File file) {
persist(entity);
customFileService.createOnFileSystem(file);
throw new RunTimeException();
}
So the code above will always rollback. It will undo the persisting of your entity, but not the creation of your file, since that is not managed by Spring transactions, unless you provide custom implementation for it to be.
Second, Spring provides 2 ways of working with transactions:
Spring AOP: a proxy is created at runtime which will decorate your code with transactional stuff. If your class would be named MyClass, then Spring will create a class names MyClassProxy, which will wrap your code in transactional code.
AspectJ: at compile time your .class file will be adjusted and transactional code will be embedded inside your method.
The aspectJ approach seems harder to configure, but isn't so much and is way easier to use. Since anything which is annotated with #Transactional will be embedded (weaved) with code. For Spring AOP this is not the case. Transactional inner method calls for instance in Spring will be ignored! So aspectJ provides a more intuitive approach.
Back to what I think your question is (the code is all in 1 class):
public void doSomeCode() {
Object restCall = initialize();
try {
execute(restCall);
} catch (CustomException e) {
myCustomRollback(restCall; e);
}
}
#Transactional(rollbackFor = CustomException.class)
private void execute(Object restCall) throws CustomException {
// jdbc calls..
restCall = callRest(restCall);
throw new CustomException();
}
void myCustomRollback(Object restCall, CustomException e) {
...
}
The code above will only work with AspectJ! Since your making inner method calls which also seems to be private! AOP at runtime cannot handle this.
So what happens is everything (which is rollbackAble) in execute will be rollbacked. And in doStuff you have information about the objects which were used in execute, you now can use in myCustomRollback to rollback your REST stuff manually.
Not sure if I answered this question properly, but I hope it helps someone with a similar problem.
1 solution is to implement your own transactional manager by extending a one
2 solution is to use TransactionSynchronizationManager class
3 solution is to use #TransactionalEventListener in case you have Spring 4
Spring transaction management the default behavior for automatic rollback is for unchecked exceptions
so for a custom exception,
#Transactional(rollbackFor = CustomException.class, noRollbackFor = RuntimeException.class)
public void doSomething(...
)
the transaction be rolled back if it there is an exception that matches the specified. If an exception not matches, it is propagated to caller of the service or TransactionRolledBackException wrapper
if you use use the org.springframework.transaction.PlatformTransactionManager it is more manageable handling exceptions than template
check the documentation http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html
you can use the AfterThrowing advice (when an exception is thrown) & call your method (myCustmRollback()) there, you can use TransactionSynchronizationManager class to get thecurrent transaction & roll it back...
alternatively.. you can use the AroundAdvice to begin & commit/rollback your transaction (this way you can use the spring provided transaction manager by using the TransactionSynchronizationManager class)
I have a Transaction problem on Spring 3.0.5. In my case I get the so-called exception "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"... I have tried everything so far. I can see in my log that the transactional services are detected and registered as Spring beans and I can also see in the logs that they are proxied and associated with underlying Spring transaction interceptors. (Advise) When I run my Spring MVC app my controller will call the service...... :-( but the transaction interceptors are not triggered. (??) I expect my Spring service proxy to open a session and start a transaction before calling my target service method. Since this does not happen, I get the above exception. I have been almost two days on this problem. Tried everything which I found on the internet...but in vain.
I have layered architecture: presentation (springmvc), service (transaction annotated), dataacess (Spring/Hibernate classic sessionfactory). My model objects are annotated with jpa (javax.persistence.*). My spring context config files are separated in appContext.xml, appContext-service.xml and appContext-dao.xml. I have defined my Spring LocalSessionFactoryBean, Datasource and TransactionManager (HibernateTransactionManager) in appContext-dao.xml. I have put in appContext-service.xml where my service implementations resides. In all of my config files I have included and to detect my beans through Controller, Service and Repository annotations.
I appreciate any kind of help.
It sounds like you are doing everything correctly and you know what you are doing. There's not much we can do here unless you show some configuration.
What I'd suggest is some debugging.
First: do you have Unit tests in the service layer that test the queries you are using? Perhaps you can find the error in the service layer.
Then: debug the MVC app, check the types of the injected services. Verify that they are proxies, not the original types.
If they are the original types, you
have an error in your transaction
configuration .
If they are proxies, step through the
query methods and verify that the
transaction logic is applied.
This sounds like accessing a lazily-loaded list or set of you dao after the closing of the transaction. This typically happens if you access that list in the view in stead of the controller, as your controller probably calls methods in transaction scope, and then leaves the transaction and forwards the loaded bean to the view.
Simple solutions:
Configure your data bean to eagerly load
Force loading of the dependencies in the controller (just loop through them)
have a look at this article ans possibly also quite a few right here on SO on lazy loading / lazy fetching of one-to-many associations and the like
Imagine:
// your dao
public class Foo {
// lots of other properties
List<Something> stuff;
// getters and setter for stuff
}
// repository
#Transactional
public class FooRepo {
public Foo loadFoo(int id) {
...
}
}
// Controller
public class Controller {
public void Control() {
sessionContext.set("foo", repo.loadFoo(1)); // transaction managed by spring
}
public void setFooRepo(FooRepo repo) {this.repo = repo};
}
// View
for (Something something : foo.getStuff()) {
// Ooops transaction is closed! stuff is lazily loaded so NOT AVAILABLE
// practical solutions:
// - do not load lazily (Foo.hbm.xml)
// - or force loading by getting all Somethings in the controller
}