i have a #Service that is composed:
#Service
public class TestService implements ITestService {
#Autowired
private TestRepository testRepository;
#Autowired
private TransactionTableRepository transactionRepository;
#Transactional
#Override
public void post(String data) throws Exception {
testRepository.post(data);
//here i have finish my process and i want to save the current
//transaction id in a db oracle table
transactionRepository.save(getCurrentTransactionId());
}
}
How can i have the getCurrentTransactionId()??
Thanks for the help
Related
Let's say we got two different controller classes, AController.java and BController.java.
public class AController {
#Autowired
private AdminService adminService;
}
public class BController {
#Autowired
private AdminService adminService;
}
I wonder if this is okay.
+ EDIT
AdminService (Interface)
The top three are from Acontroller, and the other is from BController.
I have no issue with trigger selectNormalList() until I create selectCouponByTerm().
public interface AdminService {
List<Member> selectNormalList();
List<Member> selectPartnerList();
List<Coupon> selectCouponByDate(String date);
List<Coupon> selectCouponByTerm(String startDate, String endDate);
}
AdminServiceImpl(that implements interface AdminService)
#Service
public class AdminServiceImpl implements AdminService{
#Autowired
private static AdminDao adminDao;
#Override
public List<Member> selectNormalList() {
return adminDao.selectNormalList();
}
#Override
public List<Member> selectPartnerList() {
return adminDao.selectPartnerList();
}
#Override
public List<Coupon> selectCouponByDate(String date) {
return adminDao.selectCouponByDate(date);
}
#Override
public List<Coupon> selectCouponByTerm(String startDate, String endDate) {
return adminDao.selectCouponByTerm(startDate, endDate);
}
}
I suggest the following approach for the Service class
The way you are structured the logic will lead you to NULLPointerException
#Service
public class AdminServiceImpl implements AdminService{
private AdminDao adminDao;
#Autowired
private AdminService adminService;
public AdminServiceImpl (AdminDao adminDao){
this.adminDao= adminDao;
#Override
public List<Member> selectNormalList() {
return adminDao.selectNormalList();
}
#Override
public List<Member> selectPartnerList() {
return adminDao.selectPartnerList();
}
#Override
public List<Coupon> selectCouponByDate(String date) {
return adminDao.selectCouponByDate(date);
}
#Override
public List<Coupon> selectCouponByTerm(String startDate, String endDate) {
return adminDao.selectCouponByTerm(startDate, endDate);
}
Then in your controllers
#Controller
public class AController {
#Autowired
private AdminService adminService;
}
#Controller
public class BController {
#Autowired
private AdminService adminService;
}
Yes.
This is the point of dependency injection. You can inject a dependency into whatever else needs it.
Do pay attention to what you're injecting where, though; if two controllers share common functionality to the degree that they have the same dependencies, should they really be two controllers?
Yes. It is ok. Spring will inject AdminService in both controllers. You have to use #Controller on AController and BController and #Service on AdminService class.
I have a weird issue with #Transactional, the thing is, it's not doing a complete rollback on an error and I don't get why.
This is my service:
#Transactional
public class AService {
#Autowired
private AuditRepository auditRepository;
#Autowired
private RequestStatusRepository requestStatusRepository;
#Autowired
private ApprovementRepository approvementRepository;
public void approve(long approvementId) {
updateStatus();
}
private void updateStatus(long approvementId){
Approvement approvement = approvementRepository.findById(approvementId);
updateApprovement(approvement);
Request request = requestRepository.findById(approvement.getRequest().getId());
updateRequest(request);
}
private void updateApprovement(){
approvementRepository.save(approvement);
}
private void updateRequest(Request request){
requestRepository.save(request);
auditRepository.save(new Audit(request));
}
}
This is the Approvement Repository they are all similar:
#Repository
public class ApprovementRepositoryImpl implements ApprovementRepository {
#Autowired
private JpaApprovementRepository jpaApprovementRepository;
private Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance();
#Override
public Approvement findById(long id) {
return jpaApprovementRepository.findById(id).map(this::to).orElse(null);
}
#Override
public void save(Approvement approvement) {
jpaApprovementRepository.save(from(approvement));
}
public Approvement to(ApprovementEntity from){
return mapper.map(from, Approvement.class);
}
public ApprovementEntity from(Approvement to){
return mapper.map(from, ApprovementEntity.class);
}
}
Ok, the request I'm getting has a very long field and the auditRepository isn't being able to store it, the change in audit never happened, and the change in request gets rolled back, but, the change in approvement it's being commited.
Why is this happening? I've been trying different types of propagations, and moving the #Transactional annotation from the class to the public method without success, any ideas would be great, thanks.
I have the following Mongo repository classs in my Spring-boot application, which is called ExpertRepository.java:
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.repository.MongoRepository;
public interface ExpertRepository extends MongoRepository<Experts, ObjectId>{
Experts findBy_id(ObjectId _id);
}
And I have implemented this Service in my ExpertsServiceImpl.java class:
#Service
#RequiredArgsConstructor
public class ExpertsServiceImpl implements ExpertsService{
private final ExpertRepository repository;
public Experts findExpertById(ObjectId id) {
Experts searchedExpert = repository.findBy_id(id);
return searchedExpert;
} }
And I have implemented also the following test class for my Service :
#SpringBootTest
public class ExpertsServiceTest {
#Autowired
private ExpertRepository repository;
#Autowired
private ExpertsServiceImpl service;
Experts demoExpert = new Experts(ObjectId.get(),"Steve Jobs", "Enterpreneur",
Availability.BUSY, Language.CHINESE);
#Before
public void setUp() throws Exception{
service.deleteAll();
service.createExpert(demoExpert);
}
#After
public void tearDown() throws Exception{
service.deleteAll();
}
#Test
public void testfindExpertById(){
ObjectId id = new ObjectId(demoExpert.get_id());
Experts expert = service.findExpertById(id);
assertEquals(demoExpert.get_id(), expert.get_id());
} }
Despite that the test fails and when debugging I figured out that my searchedExpert object in the findExpertById method of the ExpertsServiceImpl class is Null as shown in the picture below:
Does anyone understand why this happens and how I could correct it? I apppreciate any help you can provide
I want to call all the request mapping method(which has #Resource injection) before the server starts. How I can do this?
#Controller
public class ServiceController {
#Resource(name="userService")
private IUserService userService;
#RequestMapping("/getAllCountry")
public String getAllCountry() {
return userService.getAllCountry();
}
#RequestMapping("/getAllStates")
public String getAllStates() {
return userService.getStates();
}
#PostConstruct
public void cacheData(){
cache.put("ALL_COUNTRY_DATA", getAllCountry());
cache.put("ALL_STATE_DATA", getAllStates());
}
}
The above code fails and give me IllegalStateException. What is the best way to call the request mapping methods before the server is up and populate the cache.
Try using ApplicationListener in conjunction with ContextRefreshedEvent:
#Controller
public class ServiceController implements ApplicationListener<ContextRefreshedEvent> {
private static final Map<String, String> cache = new HashMap<>();
#Resource(name = "userService")
private IUserService userService;
#RequestMapping("/getAllCountry")
public String getAllCountry() {
return userService.getAllCountry();
}
#RequestMapping("/getAllStates")
public String getAllStates() {
return userService.getStates();
}
public void cacheData() {
cache.put("ALL_COUNTRY_DATA", getAllCountry());
cache.put("ALL_STATE_DATA", getAllStates());
}
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
cacheData();
}
}
I'm doing unit test using spring mvc test framework.
The following is my source code:
com.exmple.main
MyController.java
#Controller
public class MyController {
#Autowired
private MyService myService;
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public Map<Object, Object> myControllerFunction(#RequestBody final Object jsonRequest) {
/* do something */
return response;
}
}
MyRepository.java
#Repository
public interface MyRepository extends JpaRepository<My, String> {
#Query(value="select * from my d where (d.start_date<to_date(:date,'YYYY/DD/MM')) and (d.end_date>to_date(:date,'YYYY/DD/MM'))", nativeQuery=true)
List<My> findByDate(#Param("date") String date);
}
MyService.java
public interface MyService {
List<My> findByDate(String date);
}
MyServiceImpl.java
#Service
public class MyServiceImpl implements MyService {
#Autowired
MyRepository destRepo;
#Override
public List<My> findByDate(String date) {
List<My> listDest = destRepo.findByDate(date);
return listDest;
}
}
com.example.test
MyControllerTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={TestConfig.class})
#WebAppConfiguration
public class MyControllerTest {
private MockMvc mockMvc;
#Autowired
MyService myService;
#Autowired
protected WebApplicationContext webApplicationContext;
#Before
public void setup() throws Exception {
// this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void listAllMy() throws Exception {
}
}
TestConfig.java
#Configuration
public class TestConfig {
#Bean
public MyService myService() {
// set properties, etc.
return new MyServiceImpl();
}
}
When I run test, the following error is displayed
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException
I know the exception occurred because MyService didn't find any bean of MyRepository.
But I don't know how to create a bean of repository.
Please teach me how to create a bean of repository class using Java (not xml).
You need to enable the JPA repositories in your config class, specify the package that contains the repositories as below
#Configuration
#EnableJpaRepositories(basePackages = {
"com.example.repository"
})
public class TestConfig {
#Bean
public MyService myService() {
// set properties, etc.
return new DestinationServiceImpl();
}
}
Edit: looks like you haven't defined entityManager, and dataSource. Refer to a tutorial here and also answer to similar question here