I am getting internal server error dont konw reason for that - spring-boot

my code.....this was controller
controller
#Getmapping("/Transferabalance/{id}")
public List<Transaction> transfer(#PathVariable("Accbalance") long Accbalance) throws ResourceNotFoundException
{
List<Transaction> balance=Transservice.findByAccbalance(Accbalance);
if(balance==null)
throw new ResourceNotFoundException("NO BALANCE");
else
return balance;
}
This was service service
public List<Transaction> findByAccbalance(long Accbalance)
{
// TODO Auto-generated method stub
return transrepo.findByAccbalance(Accbalance);
}
transaction repository i used an query to retrive the elemnt from data base
public interface TransactionRepository extends CrudRepository<Transaction,Long>
{
#Query(value="select ACCBALANCE from TRANSACTION",nativeQuery = true)
List<Transaction> findByAccbalance(long Accbalance);
}

1st of all, CrudRepository itself provides you lots of methods to perform operation then why use JPQL though your query is simple.
you can simply use findByAccbalance(long Accbalance) that will return you expected result in your case.
List<Transaction> findByAccbalance(long Accbalance);
but if you wanna use Query then can you check with below Query:--
#Query(value="select c from TRANSACTION c")
List<Transaction> findByAccbalance(long Accbalance);

Related

Spring Transactions - how to split my method

I have the following method that is called by controller:
#Transactional
public Note getById(Long noteId, Collection<Authority> authorities) {
permissionService.actionAllowed(authorities, Permission.NOTE);
return getNote(noteId);
}
private Note getNote(Long noteId) {
return repository.findById(noteId)
.orElseThrow(() -> new MyException("Note does not exist"));
}
The problem is that we should keep transactions as short as possible so I have to call my validation method permissionService.actionAllowed outside of the trasaction scope. How to do it in the best way?
I don't want to create additional public method with #Transactional... I don't have any idea

How to throw exceptions on search methods in spring data jpa

I am using spring-data-jpa repositories for database operations. I want to throw exceptions if object doesn't exists in database for all methods in my repositories. For example Consider the following method in OrderRepository
findByCustomerAndPayment(Customer customer, Payment payment);
I want to query all orders based on customerId and paymentId. Both the objects are neccessry in the above query. But spring-data-rest returns null if I gave cutomerId doesn't exists in database. I expect spring-data-rest to throw exception if object doesn't exists in database.
How to achieve this?
You just need orElseThrow
orderRepository.findByCustomerAndPayment(customer, payment).orElseThrow(() -> new ResourceNotFoundException("customer", "id", customer.getId()));
If you're using Java 8, you can use Optional<Order> as the return type of the repository method. If the repository method returns an empty Optional calling get on it will throw a NoSuchElementException. Otherwise there is no support for throwing exceptions by repository methods if there are no results.
try {
Optional<Order> result = repository.findByCustomerAndPayment(customer,payment);
Order order = result.get();
} catch(NoSuchElementException e) {
// do something with the exception
}
You can make custom repository implementation like below:
public interface OrderRepositoryCustom {
Order findByCustomerAndPaymentRequired(Customer customer, Payment payment);
}
public class OrderRepositoryImpl implements OrderRepositoryCustom {
#Autowired
OrderRepository orderRepository;
#Override
public Order findByCustomerAndPaymentRequired(Customer customer, Payment payment) {
Order o = orderRepository.findByCustomerAndPayment(customer, payment);
if(o == null) {
throw new IncorrectResultSizeDataAccessException(1);
}
return o;
}
}
Your OrderRepository interface should extend customized:
public interface OrderRepository extends CrudRepository<Order, Long>, OrderRepositoryCustom {
Order findByCustomerAndPayment(Customer customer, Payment payment);
}
Edited
As IncorrectResultSizeDataAccessException is RuntimeException, then no need to throws declaration - i fixed that.
Use Optional together with orElseThrow.
Order findByCustomerAndPayment(Customer customer, Payment payment);
default Order findByCustomerAndPaymentOrThrow(Customer customer, Payment payment) {
return Optional.ofNullable(findByCustomerAndPayment(customer, payment)).orElseThrow();
};

Criteria in spring data

I'm working on a web application using angular js, spring mvc and spring jpa data.
I'm wondering if there is something similar to criteria and detachedcriteria(hibernate) to build advanced queries with spring jpa data.
Nothing stops you from still using Criteria
#Repository
public interface FooRepository extends JpaRepository<Foo, Long>, FooRepositoryCustom {
}
interface FooRepositoryCustom {
public List<Foo> findByBar(Bar bar);
}
class FooRepositoryImpl implements FooRepositoryCustom {
#PersistenceContext
protected EntityManager em;
#Transactional(readOnly = true)
public List<Foo> findByBar(Bar bar) {
Criteria crit = em.unwrap(Session.class).createCriteria(Foo.class);
crit.add(Restrictions.eq("name", bar.getName()));
...
crit.setResultTransformer(DetachedCriteria.DISTINCT_ROOT_ENTITY);
List<Foo> foos = crit.list();
return foos;
}
}
Yes, you can use Specifications, which basically uses the Criteria API (obviously, since Spring Data JPA is just a wrapper around JPA).
you can use Query Dsl
, it is less verbose than Specification, here is a blog containing both Specification and QueryDsl.
You can use Criteria with Spring Data, you don't need a Custom Repository, You could use JpaSpecificationExecutor, here an example:
Your repository:
#Repository("yourRepository")
public interface YourRepository extends JpaRepository, JpaSpecificationExecutor
{
}
Your Service
#Override
public List<YourModel> yourDataModel getAllEntitiesByAttr(String attrValue){
List<YourModel> yourDataModel = null;
try {
Specification specification=getAndSpecByAttribute("attribute",attrValue);
List list = userRepository.findAll(specification);
yourDataModel =orikaMapper.mapAsList(list, YourModel.class);
} catch (Exception e) {
throw e;
}
return yourDataModel;
}
private Specification getAndSpecByAttribute(String attribute, String valueAttribute){
return new Specification() {
#Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
Path path = root.get(attribute);
return cb.equal(path, valueAttribute);
};
};
}
It is enough.

How to define Spring Data Repository scope to Prototype?

I'm using Spring data jpa & hibernate for data access along with Spring boot. All the repository beans are singleton by default. I want to define the scope of all my repositories to Prototype. How can I do that?
#Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
Edit 1
The problem is related to domain object being shared in 2 different transactions which is causing my code to fail. I thought it is happening because repository beans are singleton. That's the reason I asked the question. Here is the detailed explanation of the scenario.
I have 2 entities User and UserSkill. User has 1-* relationship with UserSkills with lazy loading enabled on UserSkill relation.
In a UserAggregationService, I first make a call to fetch an individual user skill by id 123 which belongs to user with id 1.
public class UserAggregationService {
public List<Object> getAggregatedResults() {
resultList.add(userSkillService.getUserSkill(123));
//Throws Null Pointer Exception. See below for more details.
resultList.add(userService.get(1));
}
}
Implementation of UserSkillService method looks like
#Override
public UserSkillDTO getUserSkill(String id) {
UserSkill userSkill = userSkillService.get(id);
//Skills set to null avoid recursive DTO mapping. Dozer mapper is used
//for mapping.
userSkill.getUser().setSkills(null);
UserSkillDTO result = mapper.map(userSkill, UserSkillDTO.class);
return result;
}
In the call of user aggregation service, I call UserService to fetch userDetails. UserService code looks like
#Override
public UserDTO getById(String id) {
User user = userService.getByGuid(id);
List<UserSkillDTO> userSkillList = Lists.newArrayList();
//user.getSkills throws null pointer exception.
for (UserSkill uSkill : user.getSkills()) {
//Code emitted
}
....
//code removed for conciseness
return userDTO;
}
UserSkillService method implementation
public class UserSkillService {
#Override
#Transactional(propagation = Propagation.SUPPORTS)
public UserSkill get(String guid) throws PostNotFoundException {
UserSkill skill = userSkillRepository.findByGuid(guid);
if (skill == null) {
throw new SkillNotFoundException(guid);
}
return skill;
}
}
UserService method implementation:
public class UserService {
#Override
#Transactional(readOnly = true)
public User getByGuid(String guid) throws UserNotFoundException {
User user = userRepo.findByGuid(guid);
if (user == null) {
throw new UserNotFoundException(guid);
}
return user;
}
}
Spring boot auto configuration is used to instantiate entity manager factory and transaction manager. In the configuration file spring.jpa.* keys are used to connect to the database.
If I comment the below line of code, then I do not get the exception. I am unable to understand why change in the domain object is being affecting the object fetch in a different transaction.
userSkill.getUser().setSkills(null);
Please suggest If I have missed something.

Spring Data REST filtering data based on the user

If I have a repository setup like the following, making use of Spring Data REST, I can access the data at /receipts and see all data. However, I want to only return data for the user. I have a custom finder "findByStorer" which would do this. How would I get Spring Data REST to use this and get the storer value from the user rather than specifying a query parameter?
#RepositoryRestResource(collectionResourceRel = "receipts", path = "receipts")
public interface ReceiptRepository extends PagingAndSortingRepository<Receipt, BigDecimal> {
#Query
public Page<Receipt> findByStorer(String storer, Pageable pageable);
}
I haven't implemented any security yet, so this question is more theory at the moment than practice.
Thanks.
Building on #rpr's answer:
You should be able to reference properties of the joined entity (Storer). In your example if you have Receipt -> Storer -> User you can query the Receipts where Storer.user has a value injected from the Security Context.
#PreAuthorize("isFullyAuthenticated && (#userName==principal.username)")
Page<Receipt> findByStorer_User(#Param("userName") String userName)
For example, given a Repositoryfor SomeEntity you could override findAll method with a custom #Query filtering by attribute ownerwith value of`#{principal.username}
#RepositoryRestResource(path = "some-entities", collectionResourceRel = "some-entities", itemResourceRel = "some-entity")
interface SomeEntityRepository extends PagingAndSortingRepository<SomeEntity, String> {
#Override
#RestResource(exported = true)
#Query("select someEntity from SomeEntity someEntity where someEntity.owner = ?#{principal.username}")
Iterable<SomeResource> findAll();
}
If you use Spring Security you can use this approach:
#PreAuthorize("isFullyAuthenticated() && (#userName == principal.username)")
public List<User> findByUserName(#Param("userName")String userName);
This issue is a tipical cross-cutting concern so I tried apply AOP. Define Advice and update the args (String storer), as explain at: https://stackoverflow.com/a/46353783/1203628
#Aspect
#Transactional
#Component
public class FilterProjectsAspect {
#Pointcut("execution(* com.xxx.ReceiptRepository.findByStorer(..))")
public void projectFindAll() {
}
#Around("projectFindAll()")
public Object filterProjectsByUser(final ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs();
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof String) {
String storer=(String) args[i];
// Find storer by user
args[i]=storer; //Update args
}
return pjp.proceed(args);
}
}

Resources